- 관리자 페이지 폴더 구조 재구성 (pages/pc/admin/) - login/, dashboard/, members/, albums/, schedules/ - 앨범 관리 페이지 마이그레이션 (Albums, AlbumForm, AlbumPhotos, AlbumTeasers) - 일정 관리 페이지 마이그레이션 (Schedules, ScheduleForm, ScheduleCategory, ScheduleDict, ScheduleBots) - DatePicker 컴포넌트 버그 수정 (월 이동 및 연도 선택) - 일정 관리 라우트 경로 수정 (/admin/schedule) - 마이그레이션 문서 업데이트 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
16 KiB
16 KiB
관리자 페이지 마이그레이션 계획서
개요
- 목표:
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단계: 폴더 구조 재편 (기존 파일을 새 구조로 이동)
- 2단계: 관리자 기반 설정 (레이아웃, API, 인증)
- 3단계: 간단한 페이지 (로그인, 대시보드, 멤버)
- 4단계: 앨범 관리
- 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 경로를 새 구조에 맞게 수정합니다.
// 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 생성:
// 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 사용 가능)
사용 예시:
// 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/, 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)
- AdminLogin 페이지 마이그레이션
3단계: 간단한 페이지 ✅
- AdminLogin 마이그레이션 (2단계에서 완료)
- AdminDashboard 마이그레이션
- AdminMembers 마이그레이션
- AdminMemberEdit 마이그레이션
- useToast 훅 추가
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개+ 작은 파일 | 유지보수성 향상 |
주의사항
- SSE 스트리밍: AdminAlbumPhotos의 SSE 업로드는 별도 훅으로 분리하여 처리
- 인증 처리: 모든 관리자 API 호출에 토큰 자동 첨부
- 에러 처리: 401 에러 시 자동 로그아웃 및 리다이렉트
- 폼 검증: React Hook Form 또는 자체 검증 로직 사용
- 낙관적 업데이트: 목록 삭제 등에 useMutation의 onMutate 활용
참고
- 기존 문서: frontend-refactoring.md
- API 명세: api.md
- 개발 가이드: development.md