# 관리자 페이지 마이그레이션 계획서 ## 개요 - **목표**: `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단계: 폴더 구조 재편 - [ ] api/ 구조 변경 (common/, pc/common/, pc/public/, pc/admin/) - [ ] components/ 구조 변경 (common/, pc/public/, pc/admin/, mobile/) - [ ] hooks/ 구조 변경 (common/, pc/admin/) - [ ] pages/ 구조 변경 (pc/public/, pc/admin/, mobile/) - [ ] 모든 import 경로 업데이트 - [ ] 각 폴더에 index.js 생성 (re-export) - [ ] 빌드 및 동작 확인 ### 2단계: 관리자 기반 설정 - [ ] 관리자 API 마이그레이션 (api/pc/admin/) - [ ] AdminLayout 마이그레이션 (components/pc/admin/) - [ ] AdminHeader 마이그레이션 (components/pc/admin/) - [ ] useAdminAuth 훅 이동 (hooks/pc/admin/) - [ ] 관리자 라우트 설정 (App.jsx) ### 3단계: 간단한 페이지 - [ ] AdminLogin 마이그레이션 - [ ] AdminDashboard 마이그레이션 - [ ] AdminMembers 마이그레이션 - [ ] AdminMemberEdit 마이그레이션 ### 4단계: 앨범 관리 - [ ] AdminAlbums 마이그레이션 - [ ] AdminAlbumForm 마이그레이션 - [ ] AdminAlbumPhotos 마이그레이션 (SSE 처리 포함) ### 5단계: 일정 관리 - [ ] AdminSchedule 마이그레이션 - [ ] AdminScheduleForm 마이그레이션 - [ ] AdminScheduleCategory 마이그레이션 - [ ] AdminScheduleDict 마이그레이션 - [ ] 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)