- getUpcomingSchedules가 getMonthlySchedules와 동일한 날짜별 그룹화 형식 반환 - routes/schedules 응답 스키마에 oneOf 추가 (객체/배열 둘 다 허용) - docs/architecture.md, migration.md 업데이트 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
13 KiB
13 KiB
프로젝트 구조
디렉토리 구조
fromis_9/
├── backend/ # Fastify 백엔드 (현재 사용)
│ ├── src/
│ │ ├── config/
│ │ │ ├── index.js # 환경변수 통합 관리
│ │ │ └── bots.js # 봇 설정 (YouTube, X)
│ │ ├── plugins/ # Fastify 플러그인
│ │ │ ├── db.js # MariaDB 연결
│ │ │ ├── redis.js # Redis 연결
│ │ │ ├── auth.js # JWT 인증
│ │ │ ├── meilisearch.js # 검색 엔진
│ │ │ └── scheduler.js # 봇 스케줄러
│ │ ├── routes/ # API 라우트
│ │ │ ├── admin/ # 관리자 API
│ │ │ │ ├── bots.js # 봇 관리
│ │ │ │ ├── youtube.js # YouTube 일정 관리
│ │ │ │ └── x.js # X 일정 관리
│ │ │ ├── albums/
│ │ │ │ ├── index.js # 앨범 CRUD
│ │ │ │ ├── photos.js # 앨범 사진 관리
│ │ │ │ └── teasers.js # 앨범 티저 관리
│ │ │ ├── auth.js # 인증 (로그인, 토큰 검증)
│ │ │ ├── members/
│ │ │ │ └── index.js # 멤버 조회/수정
│ │ │ ├── schedules/
│ │ │ │ ├── index.js # 일정 조회/검색/삭제
│ │ │ │ └── suggestions.js # 추천 검색어
│ │ │ ├── stats/
│ │ │ │ └── index.js # 통계 조회
│ │ │ └── index.js # 라우트 등록
│ │ ├── services/ # 비즈니스 로직
│ │ │ ├── youtube/ # YouTube 봇
│ │ │ ├── x/ # X(Twitter) 봇
│ │ │ ├── meilisearch/ # 검색 서비스
│ │ │ └── suggestions/ # 추천 검색어
│ │ ├── app.js # Fastify 앱 설정
│ │ └── server.js # 진입점
│ ├── Dockerfile # 백엔드 컨테이너
│ └── package.json
│
├── backend-backup/ # Express 백엔드 (참조용, 마이그레이션 원본)
│
├── frontend/ # React 프론트엔드 (레거시, frontend-temp로 대체 예정)
│ ├── src/
│ │ ├── api/
│ │ │ ├── public/ # 공개 API
│ │ │ └── admin/ # 어드민 API
│ │ ├── pages/
│ │ │ ├── pc/ # PC 페이지
│ │ │ └── mobile/ # 모바일 페이지
│ │ └── ...
│ └── package.json
│
├── frontend-temp/ # React 프론트엔드 (신규, Strangler Fig 마이그레이션)
│ ├── src/
│ │ ├── api/ # API 클라이언트 (공유)
│ │ │ ├── index.js
│ │ │ ├── client.js # fetchApi, fetchAuthApi
│ │ │ ├── albums.js
│ │ │ ├── members.js
│ │ │ ├── schedules.js
│ │ │ ├── auth.js
│ │ │ └── admin/ # 관리자 API
│ │ │ ├── albums.js
│ │ │ ├── members.js
│ │ │ ├── schedules.js
│ │ │ ├── categories.js
│ │ │ ├── stats.js
│ │ │ ├── bots.js
│ │ │ └── suggestions.js
│ │ │
│ │ ├── hooks/ # 커스텀 훅 (공유)
│ │ │ ├── index.js
│ │ │ ├── useAlbumData.js
│ │ │ ├── useMemberData.js
│ │ │ ├── useScheduleData.js
│ │ │ ├── useScheduleSearch.js
│ │ │ ├── useCalendar.js
│ │ │ ├── useToast.js
│ │ │ └── useAdminAuth.js
│ │ │
│ │ ├── stores/ # Zustand 스토어 (공유)
│ │ │ ├── index.js
│ │ │ ├── useScheduleStore.js
│ │ │ └── useAuthStore.js
│ │ │
│ │ ├── utils/ # 유틸리티 (공유)
│ │ │ ├── index.js
│ │ │ ├── date.js
│ │ │ └── format.js
│ │ │
│ │ ├── constants/
│ │ │ └── index.js
│ │ │
│ │ ├── components/
│ │ │ ├── index.js
│ │ │ ├── common/ # 디바이스 무관 공통 컴포넌트
│ │ │ │ ├── Loading.jsx
│ │ │ │ ├── ErrorBoundary.jsx
│ │ │ │ ├── Toast.jsx
│ │ │ │ ├── Lightbox.jsx
│ │ │ │ ├── LightboxIndicator.jsx
│ │ │ │ ├── Tooltip.jsx
│ │ │ │ └── ScrollToTop.jsx
│ │ │ ├── pc/ # PC 레이아웃 컴포넌트
│ │ │ │ ├── Layout.jsx
│ │ │ │ ├── Header.jsx
│ │ │ │ └── Footer.jsx
│ │ │ ├── mobile/ # Mobile 레이아웃 컴포넌트
│ │ │ │ ├── Layout.jsx
│ │ │ │ └── MobileNav.jsx
│ │ │ └── admin/ # 관리자 컴포넌트
│ │ │ ├── AdminLayout.jsx
│ │ │ ├── AdminHeader.jsx
│ │ │ ├── ConfirmDialog.jsx
│ │ │ ├── CustomDatePicker.jsx
│ │ │ ├── CustomTimePicker.jsx
│ │ │ └── NumberPicker.jsx
│ │ │
│ │ ├── pages/
│ │ │ ├── index.js
│ │ │ │
│ │ │ ├── home/
│ │ │ │ ├── index.js # export { PCHome, MobileHome }
│ │ │ │ ├── pc/
│ │ │ │ │ └── Home.jsx
│ │ │ │ └── mobile/
│ │ │ │ └── Home.jsx
│ │ │ │
│ │ │ ├── members/
│ │ │ │ ├── index.js
│ │ │ │ ├── pc/
│ │ │ │ │ └── Members.jsx
│ │ │ │ └── mobile/
│ │ │ │ └── Members.jsx
│ │ │ │
│ │ │ ├── album/
│ │ │ │ ├── index.js
│ │ │ │ ├── pc/
│ │ │ │ │ ├── Album.jsx
│ │ │ │ │ ├── AlbumDetail.jsx
│ │ │ │ │ ├── AlbumGallery.jsx
│ │ │ │ │ └── TrackDetail.jsx
│ │ │ │ └── mobile/
│ │ │ │ ├── Album.jsx
│ │ │ │ ├── AlbumDetail.jsx
│ │ │ │ ├── AlbumGallery.jsx
│ │ │ │ └── TrackDetail.jsx
│ │ │ │
│ │ │ ├── schedule/
│ │ │ │ ├── index.js
│ │ │ │ ├── sections/ # 일정 상세 섹션 (PC 전용)
│ │ │ │ │ ├── DefaultSection.jsx
│ │ │ │ │ ├── XSection.jsx
│ │ │ │ │ └── YoutubeSection.jsx
│ │ │ │ ├── pc/
│ │ │ │ │ ├── Schedule.jsx
│ │ │ │ │ ├── ScheduleDetail.jsx
│ │ │ │ │ └── Birthday.jsx
│ │ │ │ └── mobile/
│ │ │ │ ├── Schedule.jsx
│ │ │ │ └── ScheduleDetail.jsx
│ │ │ │
│ │ │ ├── common/
│ │ │ │ ├── pc/
│ │ │ │ │ └── NotFound.jsx
│ │ │ │ └── mobile/
│ │ │ │ └── NotFound.jsx
│ │ │ │
│ │ │ └── admin/ # 관리자 페이지 (PC 전용)
│ │ │ ├── index.js
│ │ │ ├── Login.jsx
│ │ │ ├── Dashboard.jsx
│ │ │ ├── members/
│ │ │ │ ├── List.jsx
│ │ │ │ └── Edit.jsx
│ │ │ ├── albums/
│ │ │ │ ├── List.jsx
│ │ │ │ ├── Form.jsx
│ │ │ │ └── Photos.jsx
│ │ │ ├── schedules/
│ │ │ │ ├── List.jsx
│ │ │ │ ├── Form.jsx
│ │ │ │ ├── YouTubeForm.jsx
│ │ │ │ ├── XForm.jsx
│ │ │ │ └── YouTubeEditForm.jsx
│ │ │ ├── categories/
│ │ │ │ └── List.jsx
│ │ │ ├── bots/
│ │ │ │ └── Manager.jsx
│ │ │ └── dict/
│ │ │ └── Manager.jsx
│ │ │
│ │ ├── App.jsx # BrowserView/MobileView 라우팅
│ │ └── main.jsx
│ │
│ ├── vite.config.js
│ ├── tailwind.config.js
│ ├── Dockerfile
│ └── package.json
│
├── docker-compose.yml
└── .env
서비스 구성
┌─────────────────────────────────────────────────────────┐
│ Caddy │
│ (리버스 프록시) │
└─────────────────────┬───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ fromis9-frontend (:80) │
│ Vite 개발서버 │
│ (프록시: /api → backend) │
└─────────────────────┬───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ fromis9-backend (:80) │
│ Fastify API │
└─────────────────────┬───────────────────────────────────┘
│
┌────────────┼────────────┬────────────┐
│ │ │ │
▼ ▼ ▼ ▼
┌───────────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐
│ MariaDB │ │Meilisearch│ │ Redis │ │ Nitter │
│ (외부 DB망) │ │ (검색엔진) │ │ (캐시) │ │ (X 스크랩) │
└───────────────┘ └───────────┘ └───────────┘ └───────────┘
데이터베이스
테이블 목록 (25개)
사용자/인증
admin_users- 관리자 계정
멤버
members- 멤버 정보 (이름, 생년월일, 인스타그램 등)member_nicknames- 멤버 별명 (검색용)
앨범
albums- 앨범 정보 (제목, 발매일, 커버 이미지 등)album_tracks- 앨범 트랙 (곡명, 작사/작곡, 가사 등)album_photos- 앨범 컨셉 포토album_photo_members- 컨셉 포토-멤버 연결album_teasers- 앨범 티저 이미지/영상
일정
schedules- 일정 (제목, 날짜, 시간 등)schedule_categories- 일정 카테고리 (유튜브, X, 콘서트 등)schedule_members- 일정-멤버 연결schedule_images- 일정 첨부 이미지schedule_youtube- YouTube 영상 연결 정보schedule_x- X(Twitter) 게시물 연결 정보schedule_concert- 콘서트 일정 추가 정보
콘서트
concert_venues- 콘서트 장소 정보concert_series- 콘서트 시리즈 (투어 등)concert_series_md- 콘서트 MD 상품concert_setlists- 콘서트 셋리스트concert_setlist_members- 셋리스트-멤버 연결
X(Twitter) 프로필
x_profiles- X 프로필 캐시 (프로필 이미지, 이름 등)
이미지
images- 이미지 메타데이터 (3개 해상도 URL)
추천 검색어
suggestion_queries- 검색 쿼리 로그suggestion_word_pairs- 단어 bi-gram 빈도suggestion_chosung- 초성 검색 매핑
검색 인덱스 (Meilisearch)
schedules- 일정 검색용 인덱스- 검색 필드: title, member_names, description, source_name, category_name
- 필터: category_id, date
- 정렬: date, time