- Meilisearch: 리스트형 (BotListItem) - 한 줄에 모든 정보
- YouTube: 미니 카드형 (BotMiniCard) - 호버시 액션 버튼
- X: 테이블형 (BotTableRow) - 표 형식으로 정보 비교
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Meilisearch, YouTube, X 세 섹션으로 분리
- 각 섹션에 아이콘 및 색상 적용
- YouTube 섹션에 "봇 추가" 버튼 추가 (기능은 추후 구현)
- YouTube 봇 동적 관리 계획서 추가 (docs/youtube-bots-plan.md)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- YouTube API에서 채널 정보(배너 이미지) 조회 함수 추가
- 채널 정보 Redis 캐싱 (24시간)
- 일정 상세 API에 bannerUrl 필드 추가
- 예정 일정 placeholder에 배너 이미지 배경 표시
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- PC YoutubeSection에 예정 일정 placeholder UI 추가
- 예정 일정일 경우 "예정" 배지 표시
- 영상 준비 중 placeholder 컴포넌트 추가
- 예정 일정에도 channelName 반환하도록 API 수정
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 새 영상(쇼츠 제외) 추가 시 다음 주 같은 요일 예정 일정 자동 생성
- 실제 영상 업로드 시 예정 일정을 실제 정보로 덮어씌움
- 금요일 00시까지 영상 없으면 예정 일정 삭제 + 다음 주 예정 일정 생성
- autoScheduleNext 설정: dayOfWeek, time, title, deadlineDayOfWeek, excludeShorts
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- createConcertSchedule API 함수 추가
- handleSubmit에서 FormData 구성 및 API 호출 구현
- 유효성 검사 및 저장 성공 시 목록으로 이동
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 국내: 카카오맵 API (/api/admin/kakao/places)
- 해외: 구글 Places API (/api/admin/google/places)
- YOUTUBE_API_KEY를 GOOGLE_API_KEY로 통합
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
콘서트 폼 데이터를 저장하는 백엔드 API 추가.
multipart/form-data로 포스터, 굿즈 이미지, 회차, 세트리스트를 처리하고
트랜잭션으로 관련 테이블에 일괄 저장 후 Meilisearch 동기화.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 세트리스트 섹션: 곡명, 앨범명, 참여 멤버 선택
- 곡 검색 다이얼로그: 앨범별 트랙 검색 및 다중 선택
- 직접 입력과 곡 검색 두 가지 방식으로 곡 추가 가능
- 공연 일정/세트리스트 추가 버튼을 하단으로 이동
- ConfirmDialog에 createPortal 적용
- 콘서트 정보 → 공연 정보로 명칭 변경
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 콘서트 정보 섹션: 공연명, 포스터, 참여 멤버 선택
- 공연 일정 섹션: 다회차 지원 (날짜, 시간, 장소)
- VenueSearchDialog 컴포넌트 추가 (국내/해외 장소 검색)
- 회차 추가/삭제 애니메이션 적용
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Watchtower 제외 라벨 추가하여 자동 업데이트 방지
- 버전 체크 방식 제거, 매일 12시 전체 동기화로 변경
- 봇 관리 UI를 다른 봇들과 동일하게 통일 (버전 → 업데이트 간격)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- /birthday/:memberName/:year → /schedule/birthday-{year}-{nameEn}
- ScheduleDetail에서 특수 ID(birthday, debut, anniversary) 감지
- Birthday 컴포넌트가 props로 year, nameEn 받도록 변경
- 멤버 API가 영문명으로도 조회 가능하도록 수정
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- syncScheduleById 함수 추가: 개별 일정 동기화
- YouTube 봇: 영상 추가 시 Meilisearch 동기화
- X 봇: 트윗/유튜브 링크 추가 시 Meilisearch 동기화
- description 컬럼 제거 (schedules 테이블에 없음)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- DebutCard 컴포넌트 추가 (PC/모바일)
- DebutCelebrationDialog 축하 다이얼로그 추가
- Fromis9Logo SVG 컴포넌트 추가
- 기념일 카테고리 추가 (ID: 9)
- 데뷔일(2018.01.24) 및 주년 일정 자동 생성
- 폭죽 효과 추가 (fireDebutConfetti)
- 카테고리 정보 DB에서 동적 조회하도록 개선
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- ScrollToTop: PC 레이아웃의 main 요소 스크롤 초기화 추가
- TrackDetail: key prop으로 트랙 변경 시 컴포넌트 리마운트
- TrackDetail: main 요소 스크롤 초기화 (PC는 main에서 스크롤)
- 수록곡 선택 시 Link 대신 button + navigate 사용
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- DB: music_video_url을 video_url로 변경, video_type 컬럼 추가
- 백엔드: insertTracks에서 video_url, video_type 처리
- 관리자: 영상 타입 선택 드롭다운 추가 (뮤직비디오/스페셜 영상)
- CustomSelect: {value, label} 객체 옵션 및 size prop 지원
- 트랙 상세: video_type에 따른 라벨 동적 표시
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 멤버 페이지: 바텀시트를 가운데 다이얼로그로 변경, 닫기 버튼 추가
- 앨범 상세: 섹션별 순차 애니메이션, 앨범 소개 다이얼로그로 변경
- 앨범 갤러리: 헤더 뒤로가기 버튼/클릭 기능 제거
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- datetime 필드를 date와 time 필드로 분리하여 00:00 시간도 정상 표시되도록 수정
- 백엔드: formatSchedule, Meilisearch 검색 결과, 스키마 업데이트
- 프론트엔드: datetime 파싱 로직 제거, date/time 직접 사용
- 문서: API 응답 예시 업데이트
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 카드 스와이프에서 2열 그리드 레이아웃으로 변경
- 현재 멤버와 전 멤버 섹션 분리
- 멤버 선택 시 드래그 가능한 바텀 시트 다이얼로그
- AnimatePresence로 열기/닫기 애니메이션 추가
- 그리드에서 image_medium, 다이얼로그에서 image_thumb 사용
- 디자인 비교용 미리보기 페이지 추가 (/members-preview)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- improvements.md: 모든 개선 작업 완료로 삭제
- api.md:
- 로그인 Rate Limit 정보 추가
- 봇 API에 last_sync_duration, version 필드 추가
- 타임스탬프 KST 형식으로 업데이트
- architecture.md: backend/utils 폴더 구조 추가
- development.md: Redis KEYS → SCAN 반영
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- date.js: nowKST() 함수 추가
- 모든 타임스탬프를 UTC에서 KST(+09:00)로 변경
- scheduler.js, bots.js, x/index.js, logger.js, app.js
- Meilisearch 봇에 동기화 소요 시간(ms) 추적 추가
- BotCard.jsx: 중복된 마지막 동기화 대신 소요 시간 표시
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- scheduler.js: cron.schedule에 timezone: 'Asia/Seoul' 옵션 추가
- bots.js: Meilisearch 봇 API에 버전 정보 추가
- BotCard.jsx: Meilisearch 봇 카드에 마지막 동기화 시간, 동기화 수, 버전 표시
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 4시~4시 5분간 1분 간격으로 Meilisearch 버전 체크
- watchtower 업데이트로 버전 변경 감지 시 즉시 동기화
- 동기화 오류 시 인덱스 삭제 후 재생성하여 재시도
- 기존 고정 시간(4:05) cron 방식에서 버전 감지 방식으로 변경
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Nitter 요청에 10초 타임아웃 및 HTTP 상태 코드 검증 추가
- Meilisearch syncAllSchedules에서 불필요한 deleteAllDocuments 제거
- addDocuments는 같은 ID면 자동 업데이트(upsert)
- 일정 삭제 시 Meilisearch 동기화 코드 정리 (동적 import 제거)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 로그인 Rate Limit 추가 (5회/분, 마지막 시도 기준 리셋)
- Multipart JSON 파싱 에러 처리 추가
- 로그아웃 시 무한 리다이렉트 버그 수정
- 인증 라우트 가드(RequireAuth) 추가로 비로그인 접근 차단
- Zustand hydration 대기로 페이지 깜빡임 해결
- admin/public 라우트 조건부 렌더링으로 경로 매칭 경고 해결
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- youtube/index.js: saveVideo에 withTransaction 적용
- x/index.js: saveTweet, saveYoutubeFromTweet에 withTransaction 적용
- schedules/index.js: DELETE 핸들러에 withTransaction 적용
- 중간 실패 시 자동 롤백으로 데이터 무결성 보장
- docs/improvements.md 문서 추가
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- architecture.md: routes/ 폴더 구조 추가
- development.md: API 클라이언트 헬퍼 사용법 추가
- code-review.md: 모든 작업 완료로 삭제
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
마이그레이션 완료로 더 이상 사용되지 않는 개별 export 제거
- get, post, put, del
- authGet, authPost, authPut, authDel
현재 방식: api.get(), authApi.post() 등
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>