PC 앨범 페이지:
- 앨범 목록 그리드 (4열)
- 앨범 타입별 통계 (정규/미니/싱글/총)
- 호버 시 트랙 수 표시
- 타이틀곡 및 발매일 표시
Mobile 앨범 페이지:
- 앨범 목록 그리드 (2열)
- 앨범 타입 및 발매년도 표시
Note: 앨범 상세 페이지(AlbumDetail, AlbumGallery)는 추후 구현 예정
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
PC 스케줄 페이지:
- Calendar 컴포넌트 (년/월 선택, 날짜 선택, 일정 점 표시)
- CategoryFilter 컴포넌트 (카테고리별 필터링)
- 검색 기능 (무한 스크롤 + 가상 스크롤 + 자동완성)
- 생일 폭죽 애니메이션
Mobile 스케줄 페이지:
- 달력 뷰 / 리스트 뷰 전환
- 월 선택 드롭다운
- 검색 기능 (무한 스크롤)
- 날짜별 그룹화된 일정 목록
공통 컴포넌트:
- BirthdayCard (PC/Mobile)
- fireBirthdayConfetti 함수
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- flattenScheduleResponse → transformSchedule 함수로 변경
- 새 API 형식(schedules 배열, datetime, category 객체) 지원
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- admin/schedules.js에 transformSchedule 함수 추가
- AdminSchedule.jsx의 검색 로직을 schedulesApi.searchSchedules 사용으로 변경
- 직접 fetch 호출 제거
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- schedules.js에 transformSchedule 함수 추가
- datetime → date, time 분리
- category 객체 → category_id, category_name, category_color 플랫화
- members 배열 → member_names 문자열 변환
- PC Schedule.jsx의 검색 로직을 searchSchedules 함수 사용으로 변경
- 중복 변환 로직 제거로 코드 간소화
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
변경 사항:
- 검색 API 응답에서 _rankingScore 필드 제거
- @fastify/cors 패키지 추가
- docs.caadiq.co.kr에서 API 테스트 요청 허용
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
공통 함수 추가:
- normalizeDate(): 날짜 문자열 정규화
- buildDatetime(): datetime 문자열 생성
- buildSource(): source 객체 생성
- formatSchedule(): 단일 일정 포맷팅
- formatSchedules(): 일정 목록 포맷팅
- buildMemberMap(): 멤버 맵 조회
변경:
- getMonthlySchedules: 공통 함수 사용
- getUpcomingSchedules: 공통 함수 사용
- meilisearch/formatScheduleResponse: buildDatetime 공통 함수 사용
SQL 쿼리도 SCHEDULE_LIST_SQL 상수로 통합
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
PC 카드 (2종):
- ScheduleCard: 일반 일정 카드 (홈, 스케줄 페이지)
- AdminScheduleCard: 관리자 일정 카드 (편집/삭제 버튼 포함)
Mobile 카드 (3종):
- MobileScheduleCard: 홈 페이지용 (간결한 레이아웃)
- MobileScheduleListCard: 스케줄 타임라인용 (날짜 없이 시간/카테고리)
- MobileScheduleSearchCard: 검색 결과용 (왼쪽에 날짜 표시)
공통 변경:
- decodeHtmlEntities를 사용하여 HTML 엔티티 디코딩
- getDisplayMembers 유틸 추가 (5명 이상일 때 프로미스나인 표시)
- getMemberList가 member_names 문자열 처리하도록 개선
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- ScheduleCard (PC): 카테고리와 source name 분리, Link2 아이콘 사용
- MobileScheduleCard (Mobile): 동일한 구조로 분리
- Home 페이지에서 컴포넌트 사용하도록 변경
- 멤버 5명 이상이면 '프로미스나인'으로 표시
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- PC 멤버 페이지: 5열 그리드, 전 멤버 섹션 (grayscale)
- Mobile 멤버 페이지: Swiper 카드 스타일, 썸네일 인디케이터
- App.jsx에 멤버 라우트 추가
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- PC/Mobile 홈 페이지 분리 구현
- App.jsx: react-device-detect (BrowserView/MobileView) 사용
- PCWrapper: body.is-pc 클래스 추가
- 커스텀 훅 사용 (useMembers, useAlbums, useUpcomingSchedules)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 6-9에서 추가된 파일 제거
- react-device-detect 미사용 문제로 인한 구조 재설계
- 올바른 폴더 구조로 재시작 예정:
- pages/{feature}/pc/, pages/{feature}/mobile/ 구조
- react-device-detect BrowserView/MobileView 사용
- components/pc/, components/mobile/ 레이아웃 분리
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- getUpcomingSchedules가 getMonthlySchedules와 동일한 날짜별 그룹화 형식 반환
- routes/schedules 응답 스키마에 oneOf 추가 (객체/배열 둘 다 허용)
- docs/architecture.md, migration.md 업데이트
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
페이지 추가:
- Home: PC/Mobile 통합 홈 페이지
- 히어로 섹션, 그룹 통계, 멤버/앨범/일정 미리보기
- Members: PC/Mobile 통합 멤버 페이지
- 현재 멤버, 전 멤버 그리드
- NotFound: 404 페이지
훅 추가:
- useMembers: 멤버 목록 조회
- useMemberDetail: 멤버 상세 조회
라우팅:
- 모든 공개 라우트 완성 (/, /members, /album, /schedule)
- 404 라우트 추가 (*)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
앨범 페이지:
- Album.jsx: PC/Mobile 통합 (useIsMobile 분기)
- PC: 통계 + 4열 그리드 + 호버 오버레이
- Mobile: 2열 그리드 간소화
훅 추가:
- useAlbums: 앨범 목록 조회
- useAlbumDetail: 앨범 상세 조회
- useAlbumGallery: 앨범 갤러리 조회
라우팅:
- /album 라우트 추가
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- useCalendar: initialDate가 문자열일 경우 Date 객체로 변환
- useCalendar: days 배열 추가 (캘린더 날짜 목록)
- useCalendar: canGoPrev 별칭 추가
- Schedule: currentDate가 Date 객체가 아닐 경우 안전하게 변환
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
레이아웃 컴포넌트:
- Header: PC용 헤더 (네비게이션 + SNS 링크)
- MobileNav: 모바일 하단 네비게이션
- Footer: PC용 푸터
- Layout: PC/Mobile 통합 레이아웃 (useIsMobile 기반 분기)
스케줄 페이지 (기본 구조):
- PC: 좌측 캘린더 + 우측 일정 목록
- Mobile: 상단 네비게이션 + 일정 목록
- 월 변경, 날짜 선택, 일정 표시 기능
App.jsx 업데이트:
- 라우팅 설정 (/, /schedule, /members, /album)
- Layout 컴포넌트 적용
상수 추가:
- NAV_ITEMS: 네비게이션 메뉴 항목
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- api/client.js: fetch 래퍼, ApiError, 헬퍼 함수 (get/post/put/del)
- api/auth.js: 로그인, 토큰 검증
- api/schedules.js: 스케줄/카테고리 API (공개 + 어드민)
- api/albums.js: 앨범 API (공개 + 어드민)
- api/members.js: 멤버 API (공개 + 어드민)
- docs: useQuery 사용 가이드라인 추가
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- useAuthStore: 인증 상태 관리 (localStorage persist)
- useScheduleStore: 스케줄 페이지 상태 (검색, 필터, 날짜, 뷰)
- useUIStore: UI 상태 (토스트, 모달, 라이트박스, 확인 다이얼로그)
- stores/index.js: 통합 export
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- frontend-temp/ 폴더 생성 (Strangler Fig Pattern)
- package.json: clsx 추가, 버전 2.0.0
- vite.config.js: @ path alias 추가
- 기본 폴더 구조 생성 (api, components, hooks, pages, stores, utils, constants)
- docker-compose.yml: fromis9-frontend-dev 서비스 추가
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
수정:
- AdminSchedule.jsx 1306번 라인 멤버 처리 오류 수정
- getMemberList 헬퍼 함수 사용으로 통일
생일 우선 정렬:
- PC 공개 일정 페이지: filteredSchedules에 생일 우선 정렬 추가
- PC 관리 페이지: filteredSchedules에 생일 우선 정렬 추가
- 모바일 공개 페이지: groupedSchedules, selectedDateSchedules에 생일 우선 정렬 추가
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- getMemberList 헬퍼 함수 추가 (검색 결과/일반 데이터 모두 처리)
- 검색 결과의 members가 문자열 배열인 경우 처리
- AdminSchedule.jsx trim() 오류 수정
수정 파일:
- pc/public/Schedule.jsx
- pc/admin/AdminSchedule.jsx
- mobile/public/Schedule.jsx
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
캐시 적용:
- 카테고리 목록: 1시간 TTL
- 앨범 목록: 10분 TTL
- 앨범 상세: 10분 TTL
캐시 무효화:
- 앨범 생성/수정/삭제 시 자동 무효화
- invalidateAlbumCache 함수 추가
utils/cache.js:
- TTL 상수 추가 (SHORT, MEDIUM, LONG, VERY_LONG)
- 앨범 관련 캐시 키 추가
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- services/meilisearch: 내부 SEARCH_LIMIT(1000)과 페이징 파라미터 분리
- services/meilisearch: 기본 limit을 100으로 변경
- routes/schedules: handleSearch에서 중복 slice 제거, 직접 offset/limit 전달
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- services/schedule.js: getCategories, getScheduleDetail 함수 추가
- routes/schedules/index.js: 서비스 호출로 변경 (약 70줄 감소)
- 일관된 서비스 패턴 적용
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- utils/cache.js 생성: getOrSet, invalidate, invalidatePattern, cacheKeys
- services/member.js: getAllMembers에 Redis 캐시 적용 (10분 TTL)
- services/member.js: invalidateMemberCache 함수 추가
- routes/members: 캐시 사용 및 수정 시 캐시 무효화
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- services/member.js 생성: getAllMembers, getMemberByName, getMemberBasicByName
- services/album.js에 getAlbumByName, getAlbumById 추가
- routes/members/index.js 서비스 호출로 변경 (약 50줄 감소)
- routes/albums/index.js 서비스 호출로 변경
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
모든 핸들러에 try/catch 블록 적용:
- GET /categories
- GET / (검색/월별/다가오는 일정)
- POST /sync-search
- GET /:id
- DELETE /:id
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- src/utils/transaction.js: withTransaction 헬퍼 함수 추가
- src/schemas/: 도메인별 스키마 파일 분리 (common, album, schedule, admin, member, auth)
- 라우트에 JSON Schema 검증 및 Swagger 문서화 적용
- 트랜잭션 패턴을 withTransaction 헬퍼로 추상화
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- React 18 Strict Mode 중복 요청 방지
- members, categories를 useQuery로 전환
- 수정 모드 일정 로드는 useEffect 유지 (폼 상태 초기화 필요)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- React 18 Strict Mode 중복 요청 방지
- getBots, getQuotaWarning을 useQuery로 전환
- toggleBot에서 queryClient.setQueryData 사용
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- createAlbum, updateAlbum, deleteAlbum 서비스 함수 추가
- insertTracks 배치 삽입 헬퍼 함수
- albums/index.js POST/PUT/DELETE → 서비스 호출로 변경
- routes 파일 80줄 감소
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- utils/logger.js 생성 (createLogger)
- 서비스 레이어: logger 유틸리티 사용
- 라우트 레이어: fastify.log 사용
- console.error/log → 구조화된 로깅으로 변경
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- getAlbumDetails: tracks/teasers/photos 쿼리 Promise.all로 병렬 실행
- photos.js: 멤버 INSERT for loop → VALUES 배치 처리
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 이미지 크기/품질 설정 (800x85, 400x80) → config.image
- X 기본 사용자명 'realfromis_9' → config.x.defaultUsername
- Meilisearch 최소 점수 0.5 → config.meilisearch.minScore
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- YouTubeEditForm: 변경된 API 응답 구조에 맞게 수정
- schedule.youtube?.videoId → schedule.videoId
- schedule.youtube?.channelName → schedule.channelName
- schedule.date/time → schedule.datetime 파싱
- AdminScheduleDict: useEffect → useQuery 변경으로 중복 요청 방지
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>