fromis_9/docs/admin-migration.md
caadiq ff5c168529 docs: admin-migration.md 5단계 일정 관리 완료 체크
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 20:36:16 +09:00

544 lines
16 KiB
Markdown

# 관리자 페이지 마이그레이션 계획서
## 개요
- **목표**: `frontend/src/pages/pc/admin/``frontend-temp/src/pages/admin/`
- **현재 규모**: 12개 파일, 약 7,535 LOC
- **방식**: 일반 페이지와 동일한 Strangler Fig Pattern 적용
- **특이사항**: PC 전용 (모바일 관리자 페이지 없음)
---
## 현재 구조 분석
### 관리자 페이지 (12개)
| 파일 | LOC | 설명 | 복잡도 |
|------|-----|------|--------|
| AdminLogin.jsx | 168 | 로그인 폼 | 낮음 |
| AdminDashboard.jsx | 167 | 대시보드 (통계) | 낮음 |
| AdminMembers.jsx | 180 | 멤버 목록 | 낮음 |
| AdminMemberEdit.jsx | 382 | 멤버 수정 폼 | 중간 |
| AdminAlbums.jsx | 222 | 앨범 목록 | 낮음 |
| AdminAlbumForm.jsx | 666 | 앨범 생성/수정 폼 | 높음 |
| AdminAlbumPhotos.jsx | 1,538 | 사진 업로드 (SSE) | 매우 높음 |
| AdminSchedule.jsx | 1,465 | 일정 목록/검색 | 매우 높음 |
| AdminScheduleForm.jsx | 1,173 | 일정 생성/수정 폼 | 높음 |
| AdminScheduleCategory.jsx | 463 | 카테고리 관리 | 중간 |
| AdminScheduleDict.jsx | 664 | 일정 사전 관리 | 중간 |
| AdminScheduleBots.jsx | 447 | 봇 관리 | 중간 |
### 관리자 컴포넌트 (3개)
| 파일 | 설명 |
|------|------|
| AdminLayout.jsx | 관리자 레이아웃 (헤더 + 본문) |
| AdminHeader.jsx | 관리자 헤더 (네비게이션) |
| NumberPicker.jsx | 숫자 입력 컴포넌트 |
### 관리자 API (8개)
| 파일 | 설명 |
|------|------|
| auth.js | 로그인/인증 |
| albums.js | 앨범 CRUD |
| members.js | 멤버 CRUD |
| schedules.js | 일정 CRUD |
| categories.js | 카테고리 CRUD |
| suggestions.js | 검색어 추천 관리 |
| bots.js | 봇 관리 |
| stats.js | 통계 조회 |
---
## 마이그레이션 전략
### 우선순위
복잡도와 의존성을 고려하여 순차적으로 진행:
1. **1단계**: 폴더 구조 재편 (기존 파일을 새 구조로 이동)
2. **2단계**: 관리자 기반 설정 (레이아웃, API, 인증)
3. **3단계**: 간단한 페이지 (로그인, 대시보드, 멤버)
4. **4단계**: 앨범 관리
5. **5단계**: 일정 관리 (가장 복잡)
### 코딩 가이드라인
공개 영역과 동일한 패턴 적용:
- `useQuery` / `useMutation` 사용
- 서비스 레이어 분리
- 공통 컴포넌트 재사용
- TypeScript JSDoc 타입 정의
---
## 1단계: 폴더 구조 재편
기존 frontend-temp 파일들을 새로운 구조로 이동합니다.
### 1.1 현재 구조 → 새 구조
```
현재 → 새 구조
─────────────────────────────────────────────────────────
api/
├── client.js → api/common/client.js
├── index.js → (삭제, 각 폴더별 index.js로 대체)
├── auth.js → api/pc/admin/auth.js
├── schedules.js → api/pc/public/schedules.js
├── albums.js → api/pc/public/albums.js
└── members.js → api/pc/common/members.js
components/
├── common/ → components/common/
│ ├── Loading.jsx
│ ├── ErrorBoundary.jsx
│ ├── ErrorMessage.jsx
│ ├── Toast.jsx
│ ├── Lightbox.jsx
│ └── ...
├── pc/ → components/pc/public/
│ ├── Layout.jsx
│ ├── Header.jsx
│ ├── Footer.jsx
│ ├── Calendar.jsx
│ └── ScheduleCard.jsx
└── mobile/ → components/mobile/
├── Layout.jsx
├── Header.jsx
├── BottomNav.jsx
└── ...
hooks/
├── useMediaQuery.js → hooks/common/useMediaQuery.js
├── useLightbox.js → hooks/common/useLightbox.js
├── useCalendar.js → hooks/common/useCalendar.js
├── useAdminAuth.js → hooks/pc/admin/useAdminAuth.js
└── ...
pages/
├── home/pc/ → pages/pc/public/home/
├── home/mobile/ → pages/mobile/home/
├── schedule/pc/ → pages/pc/public/schedule/
├── schedule/mobile/ → pages/mobile/schedule/
├── album/pc/ → pages/pc/public/album/
├── album/mobile/ → pages/mobile/album/
├── members/pc/ → pages/pc/public/members/
└── members/mobile/ → pages/mobile/members/
```
### 1.2 import 경로 업데이트
파일 이동 후 모든 import 경로를 새 구조에 맞게 수정합니다.
```javascript
// Before
import { fetchApi } from '@/api/client';
import Loading from '@/components/common/Loading';
import Calendar from '@/components/pc/Calendar';
// After
import { fetchApi } from '@/api/common/client';
import Loading from '@/components/common/Loading';
import Calendar from '@/components/pc/public/Calendar';
```
### 1.3 index.js 파일 생성
각 폴더에 re-export용 index.js 생성:
```javascript
// api/pc/public/index.js
export * from './schedules';
export * from './albums';
// api/pc/admin/index.js
export * from './auth';
export * from './schedules';
// ...
```
---
## 2단계: 관리자 기반 설정
### 2.1 관리자 API 추가
**원칙**: 조회(GET)는 공개 API 재사용, CUD(Create/Update/Delete)는 관리자 API
```
api/
├── common/ # PC, Mobile 공통
│ └── client.js # fetch 래퍼 (fetchApi, fetchAuthApi)
├── pc/
│ ├── common/ # PC 내 공통 (public + admin 공유)
│ │ └── members.js # 멤버 조회 (일정 폼에서도 사용)
│ ├── public/ # PC 공개 API
│ │ ├── schedules.js
│ │ └── albums.js
│ └── admin/ # PC 관리자 API
│ ├── auth.js
│ ├── schedules.js
│ ├── albums.js
│ ├── members.js
│ ├── categories.js
│ ├── suggestions.js
│ ├── bots.js
│ └── stats.js
└── mobile/ # 모바일 (pc/public과 동일 API 사용 가능)
```
**사용 예시**:
```javascript
// PC 공개 페이지
import { fetchSchedules } from '@/api/pc/public';
// PC 관리자 페이지 - 조회는 pc/common 또는 pc/public 재사용
import { fetchMembers } from '@/api/pc/common';
import { createSchedule } from '@/api/pc/admin';
// 모바일 페이지
import { fetchSchedules } from '@/api/pc/public'; // 동일 API 재사용
```
### 2.2 관리자 레이아웃
`components/pc/admin/` 폴더 구조:
```
components/pc/admin/
├── Layout.jsx # AdminLayout
├── Header.jsx # AdminHeader (네비게이션)
└── NumberPicker.jsx
```
### 2.3 인증 훅 수정
현재 `useAdminAuth.js`를 관리자 전용으로 확장:
- 토큰 검증
- 자동 로그아웃
- 권한 체크
---
## 3단계: 간단한 페이지
### 3.1 AdminLogin
- 로그인 폼 컴포넌트화
- `useMutation`으로 로그인 처리
- 에러 처리 표준화
### 3.2 AdminDashboard
- 통계 API 호출 (`useQuery`)
- 차트/카드 컴포넌트화
- 로딩/에러 상태 처리
### 3.3 AdminMembers / AdminMemberEdit
- 멤버 목록 테이블
- 멤버 수정 폼
- 이미지 업로드 처리
---
## 4단계: 앨범 관리
### 4.1 AdminAlbums
- 앨범 목록 테이블
- 삭제 확인 모달
- 정렬/필터링
### 4.2 AdminAlbumForm
폼 필드:
- 기본 정보 (이름, 발매일, 타입)
- 트랙 목록 (동적 추가/삭제)
- 티저 목록 (동적 추가/삭제)
- 앨범 커버 업로드
컴포넌트 분리:
```
components/pc/admin/album/
├── AlbumBasicForm.jsx # 기본 정보
├── TrackListForm.jsx # 트랙 관리
├── TeaserListForm.jsx # 티저 관리
└── CoverUploader.jsx # 커버 업로드
```
### 4.3 AdminAlbumPhotos
가장 복잡한 페이지:
- SSE 스트리밍 업로드
- 진행률 표시
- 멤버 태깅
- 드래그 앤 드롭
훅 분리:
```
hooks/pc/admin/
├── usePhotoUpload.js # SSE 업로드 로직
├── usePhotoList.js # 사진 목록 관리
└── useMemberTag.js # 멤버 태깅
```
---
## 5단계: 일정 관리
### 5.1 AdminSchedule
기능:
- 일정 목록 (가상 스크롤)
- 검색/필터링
- 일괄 삭제
훅 재사용:
- `useScheduleSearch` (공개 영역과 동일)
- `useScheduleFiltering` (공개 영역과 동일)
### 5.2 AdminScheduleForm
폼 필드:
- 기본 정보 (제목, 날짜, 시간)
- 카테고리 선택
- 멤버 선택
- 출처 정보
- 카테고리별 추가 필드 (YouTube, X)
컴포넌트 분리:
```
components/pc/admin/schedule/
├── ScheduleBasicForm.jsx # 기본 정보
├── CategorySelect.jsx # 카테고리 선택
├── MemberSelect.jsx # 멤버 다중 선택
├── SourceInput.jsx # 출처 입력
├── YouTubeForm.jsx # YouTube 영상 정보
└── XForm.jsx # X 게시글 정보
```
### 5.3 AdminScheduleCategory
- 카테고리 CRUD
- 색상 선택기
- 순서 변경 (드래그)
### 5.4 AdminScheduleDict
- 일정 사전 관리
- 자동완성 데이터
### 5.5 AdminScheduleBots
- 봇 목록/상태
- 동기화 실행
- 로그 확인
---
## 목표 구조
```
frontend-temp/src/
├── api/
│ ├── common/ # PC, Mobile 공통
│ │ └── client.js # fetch 래퍼
│ ├── pc/
│ │ ├── common/ # PC 내 공통 (public + admin 공유)
│ │ │ └── members.js # 멤버 조회 (폼에서 공유)
│ │ ├── public/ # PC 공개 API
│ │ │ ├── schedules.js
│ │ │ └── albums.js
│ │ └── admin/ # PC 관리자 API
│ │ ├── auth.js
│ │ ├── schedules.js
│ │ ├── albums.js
│ │ ├── members.js
│ │ ├── categories.js
│ │ ├── suggestions.js
│ │ ├── bots.js
│ │ └── stats.js
│ └── mobile/ # 모바일 API
│ └── (public과 동일하게 사용)
├── components/
│ ├── common/ # PC, Mobile 공통
│ │ ├── Loading.jsx
│ │ ├── ErrorBoundary.jsx
│ │ ├── ErrorMessage.jsx
│ │ ├── Toast.jsx
│ │ └── Lightbox/
│ ├── pc/
│ │ ├── common/ # PC 내 공통
│ │ │ └── (필요시)
│ │ ├── public/ # PC 공개 컴포넌트
│ │ │ ├── Layout.jsx
│ │ │ ├── Header.jsx
│ │ │ ├── Footer.jsx
│ │ │ ├── Calendar.jsx
│ │ │ └── ScheduleCard.jsx
│ │ └── admin/ # PC 관리자 컴포넌트
│ │ ├── Layout.jsx
│ │ ├── Header.jsx
│ │ ├── NumberPicker.jsx
│ │ ├── ConfirmDialog.jsx
│ │ ├── album/
│ │ │ ├── AlbumBasicForm.jsx
│ │ │ ├── TrackListForm.jsx
│ │ │ ├── TeaserListForm.jsx
│ │ │ └── CoverUploader.jsx
│ │ └── schedule/
│ │ ├── ScheduleBasicForm.jsx
│ │ ├── CategorySelect.jsx
│ │ ├── MemberSelect.jsx
│ │ ├── SourceInput.jsx
│ │ ├── YouTubeForm.jsx
│ │ └── XForm.jsx
│ └── mobile/ # 모바일 컴포넌트
│ ├── Layout.jsx
│ ├── Header.jsx
│ ├── BottomNav.jsx
│ ├── Calendar.jsx
│ └── ScheduleCard.jsx
├── hooks/
│ ├── common/ # PC, Mobile 공통
│ │ ├── useMediaQuery.js
│ │ ├── useLightbox.js
│ │ └── useCalendar.js
│ ├── pc/
│ │ ├── common/ # PC 내 공통
│ │ │ └── (필요시)
│ │ ├── public/ # PC 공개 훅
│ │ │ └── (필요시)
│ │ └── admin/ # PC 관리자 훅
│ │ ├── useAdminAuth.js
│ │ ├── usePhotoUpload.js
│ │ ├── usePhotoList.js
│ │ └── useMemberTag.js
│ └── mobile/ # 모바일 훅
│ └── (필요시)
├── pages/
│ ├── pc/
│ │ ├── public/ # PC 공개 페이지
│ │ │ ├── Home.jsx
│ │ │ ├── Schedule.jsx
│ │ │ ├── Album.jsx
│ │ │ └── Members.jsx
│ │ └── admin/ # PC 관리자 페이지
│ │ ├── Login.jsx
│ │ ├── Dashboard.jsx
│ │ ├── Members.jsx
│ │ ├── MemberEdit.jsx
│ │ ├── Albums.jsx
│ │ ├── AlbumForm.jsx
│ │ ├── AlbumPhotos.jsx
│ │ ├── Schedule.jsx
│ │ ├── ScheduleForm.jsx
│ │ ├── ScheduleCategory.jsx
│ │ ├── ScheduleDict.jsx
│ │ └── ScheduleBots.jsx
│ └── mobile/ # 모바일 페이지
│ ├── Home.jsx
│ ├── Schedule.jsx
│ ├── Album.jsx
│ └── Members.jsx
├── stores/ # 전역 상태 (플랫)
│ ├── useAuthStore.js
│ ├── useScheduleStore.js
│ └── useUIStore.js
├── utils/ # 유틸리티 (플랫)
│ ├── date.js
│ ├── format.js
│ └── schedule.js
└── constants/ # 상수 (플랫)
└── index.js
```
---
## 작업 체크리스트
### 1단계: 폴더 구조 재편 ✅
- [x] api/ 구조 변경 (common/, pc/common/, pc/public/, pc/admin/)
- [x] components/ 구조 변경 (common/, pc/public/, pc/admin/, mobile/)
- [x] hooks/ 구조 변경 (common/, pc/admin/)
- [x] pages/ 구조 변경 (pc/public/, mobile/)
- [x] 모든 import 경로 업데이트
- [x] 각 폴더에 index.js 생성 (re-export)
- [x] 개발 서버 동작 확인
### 2단계: 관리자 기반 설정 ✅
- [x] 관리자 API 마이그레이션 (api/pc/admin/)
- [x] AdminLayout 마이그레이션 (components/pc/admin/)
- [x] AdminHeader 마이그레이션 (components/pc/admin/)
- [x] useAdminAuth 훅 이동 (hooks/pc/admin/)
- [x] 관리자 라우트 설정 (App.jsx)
- [x] AdminLogin 페이지 마이그레이션
### 3단계: 간단한 페이지 ✅
- [x] AdminLogin 마이그레이션 (2단계에서 완료)
- [x] AdminDashboard 마이그레이션
- [x] AdminMembers 마이그레이션
- [x] AdminMemberEdit 마이그레이션
- [x] useToast 훅 추가
### 4단계: 앨범 관리 ✅
- [x] AdminAlbums 마이그레이션
- [x] AdminAlbumForm 마이그레이션
- [x] AdminAlbumPhotos 마이그레이션 (SSE 처리 포함)
### 5단계: 일정 관리 ✅
- [x] AdminSchedule 마이그레이션
- [x] AdminScheduleForm 마이그레이션
- [x] AdminScheduleCategory 마이그레이션
- [x] AdminScheduleDict 마이그레이션
- [x] AdminScheduleBots 마이그레이션
### 6단계: 검증
- [ ] 공개 페이지 동작 확인 (PC/Mobile)
- [ ] 로그인/로그아웃 테스트
- [ ] 멤버 CRUD 테스트
- [ ] 앨범 CRUD 테스트
- [ ] 앨범 사진 업로드 테스트
- [ ] 일정 CRUD 테스트
- [ ] YouTube/X 일정 등록 테스트
- [ ] 카테고리 관리 테스트
- [ ] 봇 관리 테스트
---
## 예상 효과
| 항목 | Before | After | 개선 |
|------|--------|-------|------|
| 총 LOC | ~7,535 | ~5,500 | -27% |
| 중복 코드 | 30%+ | <10% | 공통 /컴포넌트 활용 |
| 컴포넌트 분리 | 12개 대형 파일 | 30개+ 작은 파일 | 유지보수성 향상 |
---
## 주의사항
1. **SSE 스트리밍**: AdminAlbumPhotos의 SSE 업로드는 별도 훅으로 분리하여 처리
2. **인증 처리**: 모든 관리자 API 호출에 토큰 자동 첨부
3. **에러 처리**: 401 에러 자동 로그아웃 리다이렉트
4. **폼 검증**: React Hook Form 또는 자체 검증 로직 사용
5. **낙관적 업데이트**: 목록 삭제 등에 useMutation의 onMutate 활용
---
## 참고
- 기존 문서: [frontend-refactoring.md](./frontend-refactoring.md)
- API 명세: [api.md](./api.md)
- 개발 가이드: [development.md](./development.md)