- AdminDashboard 페이지 추가 - AdminMembers 페이지 추가 - AdminMemberEdit 페이지 추가 - useToast 훅 추가 - App.jsx에 관리자 라우트 추가 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
544 lines
16 KiB
Markdown
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단계: 앨범 관리
|
|
- [ ] 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)
|