Commit graph

315 commits

Author SHA1 Message Date
0a91d04992 refactor(backend): 순차 쿼리 → 병렬 처리
- getAlbumDetails: tracks/teasers/photos 쿼리 Promise.all로 병렬 실행
- photos.js: 멤버 INSERT for loop → VALUES 배치 처리

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 14:12:27 +09:00
c3e504d1e3 refactor(backend): 매직 넘버 config 이동
- 이미지 크기/품질 설정 (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>
2026-01-21 14:11:35 +09:00
46469fd324 fix(frontend): YouTube 수정 페이지 API 대응 및 사전 페이지 중복 요청 수정
- 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>
2026-01-21 13:52:46 +09:00
7593004bd6 refactor(backend): 중복 코드 제거
- scheduler.js: handleSyncResult 함수 추출로 동기화 결과 처리 로직 통합
- youtube/index.js: 하드코딩된 카테고리 ID를 CATEGORY_IDS 상수로 변경
- 리팩토링 문서 업데이트

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 13:45:08 +09:00
2f30c67b93 refactor(backend): 에러 처리 통일
- src/utils/error.js 생성: 에러 응답 유틸리티 함수들
- reply.status() → reply.code() 통일 (auth, members, stats)
- Fastify 표준 에러 응답 패턴 적용

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 13:43:26 +09:00
430bf38c91 refactor(backend): 서비스 레이어 분리
- src/services/album.js 생성: getAlbumDetails, getAlbumsWithTracks
- src/services/schedule.js 생성: getMonthlySchedules, getUpcomingSchedules
- albums/index.js, schedules/index.js에서 서비스 사용으로 변경
- schedules/index.js에서 중복 함수 제거 (240줄 감소)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 13:42:01 +09:00
b61bfe93b4 refactor(backend): 설정 통합 및 N+1 쿼리 최적화
- 카테고리 ID 상수를 config/index.js에 CATEGORY_IDS로 통합
- youtube.js, x.js, schedules/index.js에서 하드코딩된 ID를 상수로 교체
- 앨범 목록 조회 시 N+1 쿼리 문제 해결 (트랙 한 번에 조회)
- 리팩토링 작업 문서 추가

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 13:38:25 +09:00
2b24bfe0a7 일정 상세 페이지에서 콘서트 섹션 제거
- PC: ConcertSection.jsx, KakaoMap.jsx 삭제
- 모바일: ConcertSection, KakaoMap 컴포넌트 제거
- CATEGORY_ID에서 콘서트 관련 상수 제거

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 13:02:22 +09:00
9eb49929c7 YouTube 섹션 스타일 개선 및 문서 업데이트
- PC/모바일 YouTube 상세 페이지 그림자 감소, 배경색 조정
- 모바일 YouTube 섹션을 카드에서 배경 스타일로 변경
- 문서 업데이트: 완료된 마이그레이션 작업 반영, 누락된 API 추가

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 12:57:25 +09:00
bdd5b90870 YouTube 상세 페이지 API 응답 구조 변경 대응
- schedule.source.url → schedule.videoUrl
- schedule.source.name → schedule.channelName
- schedule.date/time → schedule.datetime
- videoId를 URL에서 추출 대신 API에서 직접 사용
- formatXDateTime 유틸리티 사용

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 12:24:14 +09:00
beabcc094f 라이트박스 닫기 시 이전 페이지로 이동하는 버그 수정
- ref를 사용해 히스토리 push 상태 추적
- X 버튼 클릭 시 히스토리가 push된 경우에만 history.back() 호출
- 하드웨어 백버튼과 X 버튼 닫기 동작 분리

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 12:17:24 +09:00
a1090e56c0 문서 업데이트: 프론트엔드 구조에 컴포넌트 및 유틸리티 추가
- components/common/ (Lightbox, LightboxIndicator)
- utils/date.js (dayjs 기반 날짜 유틸리티)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 12:11:36 +09:00
e1a07f4849 X 날짜 포맷팅을 dayjs 기반 유틸리티로 통합
- formatXDateTime 함수를 utils/date.js로 이동
- PC/모바일 XSection에서 공통 유틸리티 사용
- 사용하지 않는 closeLightbox 변수 제거

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 12:10:08 +09:00
67e9992cf1 라이트박스 뒤로가기 버튼 처리 추가
- PC/모바일 앨범 상세, 갤러리 페이지에 뒤로가기 처리
- PC/모바일 X 일정 상세 페이지에 뒤로가기 처리
- 라이트박스 열릴 때 history.pushState 호출
- popstate 이벤트로 라이트박스 닫기

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 12:05:36 +09:00
d8055c00e5 X 일정 상세 페이지에 이미지 라이트박스 추가
- PC/모바일 XSection에 라이트박스 기능 추가
- 이미지 클릭 시 전체 화면으로 보기
- 좌우 화살표로 이미지 탐색
- 인디케이터로 현재 이미지 위치 표시

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 11:59:23 +09:00
f797736f8e Revert "달력에서 카테고리 필터 적용"
This reverts commit 0c278597c0.
2026-01-21 11:54:12 +09:00
0c278597c0 달력에서 카테고리 필터 적용
- PC/모바일 일정 페이지 달력의 점에 카테고리 필터 적용
- 선택된 카테고리의 일정만 달력에 점으로 표시

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 11:50:13 +09:00
d1250124a7 X 봇 URL 추출 개선 및 기존 데이터 수정
- 트윗 파싱 시 축약된 URL 대신 href의 원본 URL 사용
- extractTextFromHtml 함수 추가
- 기존 트윗 content 업데이트 스크립트 추가

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 11:46:38 +09:00
1d17c83568 X 일정 상세 페이지 개선
- API 응답 형식 변경 (category_id → category.id)
- X 일정에 content, imageUrls, postUrl, profile 필드 추가
- 본문 내 URL 자동 하이퍼링크 추가 (react-linkify)
- PC/모바일 ScheduleDetail에서 새 API 형식 사용

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 11:41:39 +09:00
8bcd3e881d docs: API 문서 업데이트
- GET /schedules에 startDate 파라미터 추가
- 다가오는 일정 조회 응답 형식 문서화
- PUT /admin/youtube/schedule/:id 문서 추가

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 17:28:50 +09:00
f780e91f14 feat: 메인 페이지 일정 API 및 디자인 개선
- 백엔드에 startDate 파라미터 지원 추가 (다가오는 일정 조회)
- handleUpcomingSchedules 함수 구현
- 메인 페이지 일정 카드 디자인을 일정 페이지와 동일하게 변경
- 멤버 표시 로직 API 응답에 맞게 수정 (PC/모바일)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 17:27:31 +09:00
8e15cd6d2c refactor: UI 개선 및 날짜 제한 수정
- 멤버 페이지에서 포지션 영역 제거 (PC/모바일)
- 모바일 일정 페이지 멤버 표시 로직 API 응답에 맞게 수정
- 데이트픽커 연도 제한 2025 → 2017로 변경
- 2017년 1월에서 이전 달 버튼 비활성화

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 16:17:54 +09:00
4a4a163abe feat: YouTube 일정 수정 폼 구현
- YouTube 일정 수정 API (PUT /api/admin/youtube/schedule/:id)
- 멤버 선택, 영상 유형(video/shorts) 수정 기능
- 일정 API에 멤버 배열 추가 (5명 이상 시 "프로미스나인")
- 관리 페이지 React Query 캐싱 적용
- Shorts/Video 별 UI 레이아웃 분리
- React Query 사용 가이드 문서화

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 14:06:02 +09:00
2d469739b7 fix: 봇 상태 표시 및 일정 추가 애니메이션 개선
- 봇 lastAddedCount를 실제 추가시에만 업데이트 (0으로 덮어쓰지 않음)
- 일정 추가 폼 애니메이션 타이밍 개선 (첫 로딩: 딜레이, 카테고리 변경: 즉시)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 21:31:43 +09:00
1a9fa54981 fix: 생일 표시 버그 수정 및 데이트픽커 개선
- 생일이 생년 이전 년도에 표시되는 버그 수정
- 페이지 진입 애니메이션 추가 (사전 관리, 일정 추가)
- 데이트픽커 12년 단위 이동으로 변경
- 년도 선택 시 월 선택 화면 전환 제거
- 시작 년도 2025년 고정, 이전 이동 비활성화
- PC/모바일 일정 페이지, 관리자 페이지 모두 적용

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 16:41:34 +09:00
2576a244c0 feat: 사전 관리, 일정 추가 페이지에 애니메이션 추가
- framer-motion을 사용한 페이지 진입 애니메이션
- 섹션별 stagger 애니메이션으로 순차적 등장 효과
- 카테고리 전환 시 폼 fade 애니메이션

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 16:01:54 +09:00
84ed48fa78 fix: X 폼 Nitter 파싱 수정 및 아이콘 변경
- scraper.js: main-tweet 파싱 정규식 수정 (id 선택자 사용)
- XForm.jsx: Twitter 아이콘을 X 로고로 변경

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 15:59:26 +09:00
bc3f536ec7 feat: X 카테고리 일정 추가 폼 구현
- 백엔드: /api/admin/x/post-info, /api/admin/x/schedule API 추가
- scraper.js에 fetchSingleTweet 함수 추가 (Nitter로 단일 트윗 조회)
- 프론트엔드: XForm 컴포넌트 생성 (게시글 ID 입력 → 미리보기 → 저장)
- 일정 추가 폼에서 X 카테고리 분기 추가
- API 문서 업데이트

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 12:57:06 +09:00
0a73149849 feat: 일정 추가 페이지 카테고리별 폼 분리 (YouTube)
- 카테고리 선택 UI를 최상단으로 이동
- YouTube 카테고리 전용 폼 추가 (URL 입력 → 자동 정보 조회)
- 폴더 구조 분리: pages/pc/admin/schedule/form/
- API 추가:
  - GET /schedules/categories (카테고리 목록)
  - DELETE /schedules/:id (일정 삭제)
  - GET /admin/youtube/video-info (영상 정보 조회)
  - POST /admin/youtube/schedule (YouTube 일정 저장)
- fetchApi에서 body 없는 요청 시 Content-Type 미설정

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 12:49:29 +09:00
c7b0a51924 feat: YouTube API 할당량 절감을 위한 playlist ID 캐싱
- uploads playlist ID를 Redis에 영구 캐싱 (불변값)
- 일일 API 사용량 6,480 → 4,320 units (33% 절감)
- 문서 업데이트 (컨테이너 분리 구조, X source.name 빈 문자열)
- CLAUDE.md에 문서 업데이트 필수 안내 추가

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 12:32:04 +09:00
149e85ebd9 feat: X 봇 프로필 정보 DB 저장 기능 추가
- x_profiles 테이블 생성 (username, display_name, avatar_url)
- saveProfile 함수로 DB + Redis 캐시 동시 저장
- getProfile 함수 Redis → DB 폴백 지원

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 10:19:32 +09:00
c5f5639b11 fix: 모바일 일정 페이지 카테고리 API 형식 수정 및 X source.name 비움
- 모바일 Schedule.jsx: category 객체 형식 지원 (category.id, category.name 등)
- 백엔드 API: X 일정의 source.name을 빈 문자열로 변경
- Meilisearch: 검색 결과도 source 객체 형식으로 통일

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 10:16:24 +09:00
d7d0506b83 docs: named volume 제거 반영
- node_modules 호스트 설치 설명 추가
- 완전 재시작 명령어에서 -v 플래그 제거

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 09:59:51 +09:00
e0f328803e chore: 불필요한 named volume 제거
- frontend_modules, backend_modules 볼륨 제거
- 컨테이너에서 npm install 시 호스트 node_modules에 직접 설치

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 09:58:46 +09:00
a9bdbd1ec2 chore: docker-compose.yml 불필요한 주석 제거
- 배포 모드 관련 주석 제거 (Dockerfile에서 처리)
- VITE_API_URL 환경변수 제거 (Vite 프록시 사용)
- 문서 업데이트

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 09:56:20 +09:00
7e9e51666a fix: 컨테이너 분리 후 프록시 설정 수정
- vite.config.js: localhost:3000 → fromis9-backend:80
- docker-compose.yml: depends_on, VITE_API_URL 수정

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 09:54:07 +09:00
8a8af275a9 docs: 컨테이너 분리 반영하여 개발 가이드 업데이트
- 컨테이너 구성 표 추가
- 개별 컨테이너 로그/재시작 명령어 추가
- 배포 모드 Dockerfile 예시 분리
- 네트워크 구조 다이어그램 수정

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 09:51:26 +09:00
b824c38815 refactor: 프론트엔드/백엔드 컨테이너 분리
- backend/Dockerfile 생성
- frontend/Dockerfile 생성
- docker-compose.yml에 별도 서비스로 분리
- 기존 루트 Dockerfile 삭제

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 09:49:27 +09:00
72db9dcdc1 fix: 추천 검색어 동적 임계값 필터링 복원
- SQL GREATEST()로 동적 임계값 적용
- MAX(count) * 1% 또는 최소 10회 중 더 큰 값 사용
- Prefix, 초성, 인기 검색어 모두 필터링 적용
- 데이터가 적을 때도 오타 필터링 가능

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 09:46:44 +09:00
108265b1fd docs: 봇 관리 API 문서 추가
- GET /admin/bots: 봇 목록 조회
- POST /admin/bots/:id/start: 봇 시작
- POST /admin/bots/:id/stop: 봇 정지
- POST /admin/bots/:id/sync-all: 전체 동기화
- GET/DELETE /admin/bots/quota-warning: 할당량 경고

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 23:48:21 +09:00
841c3c8626 feat: 봇 관리 API 추가 및 타임존 수정
- 봇 관리 API 엔드포인트 추가 (routes/admin/bots.js)
  - GET /api/admin/bots: 봇 목록 조회
  - POST /api/admin/bots/:id/start: 봇 시작
  - POST /api/admin/bots/:id/stop: 봇 정지
  - POST /api/admin/bots/:id/sync-all: 전체 동기화
  - GET/DELETE /api/admin/bots/quota-warning: 할당량 경고
- 프론트엔드 API 엔드포인트 경로 수정
- 봇 업데이트 시간 UTC → 로컬 시간 변환 수정

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 23:45:54 +09:00
cd70fb18c9 chore: NODE_ENV를 development로 변경
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 22:12:16 +09:00
d4697ad996 refactor: 일정 API source 객체 구조 변경
- source_name, source_url → source: { name, url } 형태로 변경
- YouTube: schedule_youtube에서 video_id로 URL 생성
- X: schedule_x에서 post_id로 URL 생성
- 프론트엔드 전체 파일 source 객체 형태로 수정
- 문서 업데이트 (api.md, architecture.md, migration.md 등)
- tracks → album_tracks 테이블명 변경 반영

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 21:50:04 +09:00
f762302689 docs: 프로젝트 개발환경 문서 추가
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 19:01:27 +09:00
abe9687cc8 feat: Meilisearch 검색 기능 및 개발환경 통합
- Meilisearch 기반 일정 검색 API 구현
- 멤버 별명으로 검색 지원 (하냥 → 송하영)
- 영문 자판 → 한글 변환 검색 지원
- 검색 응답 구조 개선 (category 객체, datetime 통합, members 배열)
- 개발/배포 환경 Dockerfile 통합 (주석 전환 방식)
- docker-compose.yml 단일 파일로 통합

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 18:53:57 +09:00
5521c44fa9 feat: 어드민 사전 관리 기능 추가
- 형태소 분석기 사용자 사전 관리 페이지 추가
- 단어 추가/삭제/수정 시 즉시 저장 및 형태소 분석기 리로드
- 품사별 통계 및 필터링 기능
- 검색 기능 추가

백엔드:
- GET/PUT /api/schedules/suggestions/dict API 추가
- morpheme.js에 reloadMorpheme(), getUserDictPath() 함수 추가

프론트엔드:
- AdminScheduleDict.jsx 페이지 추가
- AdminSchedule.jsx에 사전 관리 버튼 추가
- 라우트 추가 (/admin/schedule/dict)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-18 13:53:51 +09:00
c201de203e feat: 추천 검색어 시스템 구현 (kiwi-nlp 형태소 분석)
- kiwi-nlp 기반 한국어 형태소 분석기 추가
- 추천 검색어 API 구현 (/api/schedules/suggestions)
  - Prefix 매칭, Bi-gram 다음 단어 예측
  - 초성 검색 지원, 영문→한글 자동 변환 (Inko)
- 사용자 사전 추가 (멤버/그룹명, 프로그램명 등)
- DB 테이블: suggestion_queries, suggestion_word_pairs, suggestion_chosung

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 13:01:29 +09:00
b89255780e refactor: 일정 API 응답 형식에 맞게 프론트엔드 수정
- API 응답(날짜별 그룹화)을 플랫 배열로 변환하는 로직 추가
- 별도 카테고리 API 호출 제거, 일정 데이터에서 카테고리 추출
- PC/모바일 Schedule.jsx, AdminSchedule.jsx 수정

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 17:52:15 +09:00
a5ed04e9af feat: 일정 API 추가
- GET /api/schedules?year=&month= 월별 일정 조회
- 날짜별 그룹화 + 카테고리 목록/개수 포함
- 유튜브 카테고리의 경우 source_name(채널명) 반환

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 16:50:16 +09:00
8b65f61e47 refactor: members, stats 라우트 폴더 구조로 변경
- members.js → members/index.js
- stats.js → stats/index.js
- 일관된 폴더 구조로 통일

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 13:02:40 +09:00