docs: 문서 업데이트 및 code-review.md 삭제
- architecture.md: routes/ 폴더 구조 추가 - development.md: API 클라이언트 헬퍼 사용법 추가 - code-review.md: 모든 작업 완료로 삭제 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
bd7fbea082
commit
d29c966ae0
3 changed files with 29 additions and 165 deletions
|
|
@ -216,7 +216,17 @@ fromis_9/
|
||||||
│ │ │ └── common/
|
│ │ │ └── common/
|
||||||
│ │ │ └── NotFound.jsx
|
│ │ │ └── NotFound.jsx
|
||||||
│ │ │
|
│ │ │
|
||||||
│ │ ├── App.jsx # 라우팅 (PC/모바일 분기)
|
│ │ ├── routes/ # 라우트 정의
|
||||||
|
│ │ │ ├── index.js # 라우트 export
|
||||||
|
│ │ │ ├── pc/
|
||||||
|
│ │ │ │ ├── admin/
|
||||||
|
│ │ │ │ │ └── index.jsx # PC 관리자 라우트
|
||||||
|
│ │ │ │ └── public/
|
||||||
|
│ │ │ │ └── index.jsx # PC 공개 라우트
|
||||||
|
│ │ │ └── mobile/
|
||||||
|
│ │ │ └── index.jsx # 모바일 라우트
|
||||||
|
│ │ │
|
||||||
|
│ │ ├── App.jsx # PC/모바일 분기
|
||||||
│ │ └── main.jsx
|
│ │ └── main.jsx
|
||||||
│ │
|
│ │
|
||||||
│ ├── vite.config.js
|
│ ├── vite.config.js
|
||||||
|
|
|
||||||
|
|
@ -1,163 +0,0 @@
|
||||||
# 코드 리뷰 결과
|
|
||||||
|
|
||||||
> 작성일: 2025-01-23
|
|
||||||
> 범위: app 폴더 제외한 backend, frontend, docker 설정
|
|
||||||
|
|
||||||
## 잘 된 점
|
|
||||||
|
|
||||||
### 백엔드 구조
|
|
||||||
- Fastify 플러그인 패턴을 적절히 활용
|
|
||||||
- 서비스/라우트 계층 분리가 명확함
|
|
||||||
- `withTransaction` 유틸리티로 트랜잭션 처리 일관성 확보
|
|
||||||
- N+1 쿼리 최적화 적용 (`getAlbumsWithTracks`)
|
|
||||||
|
|
||||||
### 캐싱
|
|
||||||
- Redis 캐시 유틸리티(`utils/cache.js`)가 깔끔하게 구현됨
|
|
||||||
- TTL 상수화로 관리 용이
|
|
||||||
- 캐시 키 생성 헬퍼 함수 제공
|
|
||||||
|
|
||||||
### 프론트엔드
|
|
||||||
- API 클라이언트의 에러 처리와 인증 토큰 관리가 잘 구현됨
|
|
||||||
- PC/Mobile 분리 구조 적용
|
|
||||||
- Zustand를 활용한 상태 관리
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 개선 필요 사항
|
|
||||||
|
|
||||||
### ~~1. 보안 (우선순위: 높음)~~ ✅ 완료
|
|
||||||
|
|
||||||
#### ~~1.1 JWT Secret 하드코딩~~ ✅ 완료
|
|
||||||
**파일**: `backend/src/config/index.js`
|
|
||||||
|
|
||||||
기본값을 제거하고 서버 시작 시 필수 환경변수 검증 로직을 추가함.
|
|
||||||
|
|
||||||
### 2. Docker 설정 (우선순위: 중간)
|
|
||||||
|
|
||||||
#### 2.1 Meilisearch 버전
|
|
||||||
~~현재 `v1.6` 사용 중. 최신 버전으로 업데이트 권장.~~ ✅ `latest`로 변경 완료 (v1.33.1)
|
|
||||||
|
|
||||||
#### 2.2 리소스 제한 없음
|
|
||||||
```yaml
|
|
||||||
redis:
|
|
||||||
# ... 기존 설정
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 256M
|
|
||||||
|
|
||||||
meilisearch:
|
|
||||||
# ... 기존 설정
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 512M
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2.3 프로덕션 Dockerfile
|
|
||||||
현재 개발용 Dockerfile만 활성화됨. 배포 시 주석 해제 또는 multi-stage build 적용 필요.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 3. 백엔드 코드 (우선순위: 중간)
|
|
||||||
|
|
||||||
#### ~~3.1 에러 유틸리티 미활용~~ ✅ 완료
|
|
||||||
모든 라우트 파일에 에러 유틸리티(`utils/error.js`) 적용 완료.
|
|
||||||
- `badRequest`, `unauthorized`, `notFound`, `conflict`, `serverError` 함수 사용
|
|
||||||
|
|
||||||
#### 3.2 SELECT * 사용
|
|
||||||
**파일**: `services/album.js:16-19`
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
// 현재
|
|
||||||
'SELECT * FROM albums WHERE folder_name = ? OR title = ?'
|
|
||||||
|
|
||||||
// 권장
|
|
||||||
'SELECT id, title, folder_name, album_type, album_type_short, release_date, cover_original_url, cover_medium_url, cover_thumb_url, description FROM albums WHERE folder_name = ? OR title = ?'
|
|
||||||
```
|
|
||||||
|
|
||||||
#### ~~3.3 앨범 삭제 시 관련 데이터 누락~~ ✅ 완료
|
|
||||||
**파일**: `services/album.js`
|
|
||||||
|
|
||||||
앨범 삭제 시 관련 테이블(photos, teasers, photo_members) 및 S3 파일도 함께 삭제하도록 개선됨.
|
|
||||||
|
|
||||||
### 4. 프론트엔드 코드 (우선순위: 낮음)
|
|
||||||
|
|
||||||
#### 4.1 App.jsx 라우트 분리
|
|
||||||
현재 194줄로 너무 큼. 라우트 분리 권장.
|
|
||||||
|
|
||||||
```
|
|
||||||
src/
|
|
||||||
├── routes/
|
|
||||||
│ ├── index.jsx # 라우트 통합
|
|
||||||
│ ├── pc.jsx # PC 라우트
|
|
||||||
│ ├── mobile.jsx # Mobile 라우트
|
|
||||||
│ └── admin.jsx # Admin 라우트
|
|
||||||
└── App.jsx # 간소화
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 4.2 레거시 export 정리
|
|
||||||
**파일**: `api/client.js:147-155`
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
// 삭제 대상 (마이그레이션 완료 후)
|
|
||||||
export const get = api.get;
|
|
||||||
export const post = api.post;
|
|
||||||
export const put = api.put;
|
|
||||||
export const del = api.del;
|
|
||||||
export const authGet = authApi.get;
|
|
||||||
export const authPost = authApi.post;
|
|
||||||
export const authPut = authApi.put;
|
|
||||||
export const authDel = authApi.del;
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 4.3 개발 도구 미설정
|
|
||||||
**파일**: `frontend/package.json`
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"scripts": {
|
|
||||||
"lint": "eslint src --ext .js,.jsx",
|
|
||||||
"lint:fix": "eslint src --ext .js,.jsx --fix",
|
|
||||||
"test": "vitest",
|
|
||||||
"test:coverage": "vitest --coverage"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"eslint": "^8.57.0",
|
|
||||||
"eslint-plugin-react": "^7.34.0",
|
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
|
||||||
"vitest": "^1.6.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 5. 문서 (우선순위: 낮음)
|
|
||||||
|
|
||||||
#### 5.1 migration.md 파일 누락
|
|
||||||
`CLAUDE.md`와 `README.md`에서 `docs/migration.md`를 참조하지만 실제 파일이 없음.
|
|
||||||
|
|
||||||
#### 5.2 환경별 설정 문서화
|
|
||||||
개발/스테이징/프로덕션 환경별 설정 가이드 필요.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 개선 우선순위 요약
|
|
||||||
|
|
||||||
| 순위 | 항목 | 파일 | 상태 |
|
|
||||||
|:----:|------|------|:------:|
|
|
||||||
| 1 | ~~JWT Secret 기본값 제거~~ | `config/index.js` | ✅ 완료 |
|
|
||||||
| 2 | ~~앨범 삭제 시 관련 테이블 정리~~ | `services/album.js` | ✅ 완료 |
|
|
||||||
| 3 | ~~에러 유틸리티 통일~~ | 라우트 파일들 | ✅ 완료 |
|
|
||||||
| 4 | ~~App.jsx 라우트 분리~~ | `App.jsx` | ✅ 완료 |
|
|
||||||
| 5 | ~~레거시 export 정리~~ | `api/client.js` | ✅ 완료 |
|
|
||||||
| 6 | ~~Meilisearch 버전 업데이트~~ | `docker-compose.yml` | ✅ 완료 |
|
|
||||||
| 7 | 테스트 코드 작성 | 전체 | 미완료 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 참고
|
|
||||||
|
|
||||||
- 이 문서는 app 폴더를 제외한 코드 리뷰 결과입니다.
|
|
||||||
- 보안 관련 항목은 가능한 빨리 적용을 권장합니다.
|
|
||||||
|
|
@ -171,7 +171,7 @@ docker exec caddy caddy reload --config /etc/caddy/Caddyfile
|
||||||
```
|
```
|
||||||
src/api/
|
src/api/
|
||||||
├── index.js # 전체 export
|
├── index.js # 전체 export
|
||||||
├── client.js # fetchApi, fetchAuthApi (에러 처리, 토큰 주입)
|
├── client.js # api, authApi 헬퍼 (에러 처리, 토큰 주입)
|
||||||
├── public/ # 공개 API (인증 불필요)
|
├── public/ # 공개 API (인증 불필요)
|
||||||
│ ├── albums.js # getAlbums, getAlbumByName, getTrack
|
│ ├── albums.js # getAlbums, getAlbumByName, getTrack
|
||||||
│ ├── members.js # getMembers
|
│ ├── members.js # getMembers
|
||||||
|
|
@ -187,6 +187,23 @@ src/api/
|
||||||
└── suggestions.js # getDict, saveDict
|
└── suggestions.js # getDict, saveDict
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**client.js 헬퍼:**
|
||||||
|
```jsx
|
||||||
|
// 공개 API 헬퍼 (인증 불필요)
|
||||||
|
import { api } from '@/api/client';
|
||||||
|
|
||||||
|
api.get('/albums');
|
||||||
|
api.post('/schedules/suggestions/save', { query: '검색어' });
|
||||||
|
|
||||||
|
// 인증 API 헬퍼 (토큰 자동 주입)
|
||||||
|
import { authApi } from '@/api/client';
|
||||||
|
|
||||||
|
authApi.get('/admin/stats');
|
||||||
|
authApi.post('/admin/schedules', data);
|
||||||
|
authApi.put('/admin/albums/1', data);
|
||||||
|
authApi.del('/admin/schedules/1');
|
||||||
|
```
|
||||||
|
|
||||||
**사용 예시:**
|
**사용 예시:**
|
||||||
```jsx
|
```jsx
|
||||||
// 공개 API
|
// 공개 API
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue