fromis_9/docs/migration.md
caadiq 0ce67d57e8 docs: 코드 품질 개선 사항 문서 추가
- code-improvements.md 생성: 전체 코드 검토 결과 정리
- Critical/High/Medium/Low 우선순위별 개선 사항 분류
- 구체적인 문제점과 해결방법 코드 예시 포함
- migration.md에서 useToast를 관리자 영역으로 이동

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 12:22:08 +09:00

13 KiB

Express → Fastify 마이그레이션

개요

backend-backup/ (Express) → backend/ (Fastify)로 마이그레이션 완료

완료된 작업

서버 기반

  • Fastify 앱 구조 (src/app.js, src/server.js)
  • 플러그인 시스템 (src/plugins/)
    • db.js (MariaDB)
    • redis.js
    • auth.js (JWT)
    • meilisearch.js
    • scheduler.js (봇 스케줄러)

API 라우트 (src/routes/)

  • 인증 (/api/auth)
    • POST /login - 로그인
    • GET /verify - 토큰 검증
  • 멤버 (/api/members)
    • GET / - 목록 조회
    • GET /:name - 상세 조회
    • PUT /:name - 수정 (이미지 업로드 포함)
  • 앨범 (/api/albums)
    • GET / - 목록 조회
    • GET /:id - ID로 조회
    • GET /by-name/:name - 이름으로 조회
    • GET /by-name/:albumName/track/:trackTitle - 트랙 조회
    • POST / - 생성
    • PUT /:id - 수정
    • DELETE /:id - 삭제
    • 사진 관리 (/api/albums/:id/photos)
      • GET / - 목록
      • POST / - 업로드
      • PUT /:photoId - 수정
      • DELETE /:photoId - 삭제
    • 티저 관리 (/api/albums/:id/teasers)
      • GET / - 목록
      • POST / - 업로드
      • DELETE /:teaserId - 삭제
  • 일정 (/api/schedules)
    • GET / - 월별 조회 (생일 포함)
    • GET /?search= - Meilisearch 검색
    • GET /:id - 상세 조회
    • DELETE /:id - 삭제
    • POST /sync-search - Meilisearch 동기화
  • 추천 검색어 (/api/schedules/suggestions)
    • GET / - 추천 검색어 조회
    • GET /popular - 인기 검색어 조회
    • POST /save - 검색어 저장
    • GET /dict - 사용자 사전 조회 (관리자)
    • PUT /dict - 사용자 사전 저장 (관리자)
  • 통계 (/api/stats)
    • GET / - 대시보드 통계

관리자 API (src/routes/admin/)

  • 봇 관리 (/api/admin/bots)
    • GET / - 봇 목록
    • POST /:id/start - 봇 시작
    • POST /:id/stop - 봇 정지
    • POST /:id/sync-all - 전체 동기화
    • GET /quota-warning - 할당량 경고 조회
    • DELETE /quota-warning - 할당량 경고 해제
  • YouTube 관리 (/api/admin/youtube)
    • GET /video-info - 영상 정보 조회
    • POST /schedule - 일정 저장
    • PUT /schedule/:id - 일정 수정
  • X 관리 (/api/admin/x)
    • GET /post-info - 게시글 정보 조회
    • POST /schedule - 일정 저장

서비스 (src/services/)

  • YouTube 봇 (services/youtube/)
    • 영상 자동 수집
    • 채널별 필터링 (제목 필터, 멤버 추출)
  • X(Twitter) 봇 (services/x/)
    • Nitter 스크래핑
    • 이미지 URL 추출
  • Meilisearch 검색 (services/meilisearch/)
    • 일정 검색
    • 전체 동기화
  • 추천 검색어 (services/suggestions/)
    • 형태소 분석 (kiwi-nlp)
    • bi-gram 빈도
    • 초성 검색
    • 사용자 사전 관리
  • 이미지 업로드 (services/image.js)
    • 앨범 커버
    • 멤버 이미지
    • 앨범 사진/티저

남은 작업 (미구현)

일반 일정 CRUD

  • POST /api/schedules - 일정 생성 (일반)
  • PUT /api/schedules/:id - 일정 수정 (일반)

※ 현재는 YouTube/X 전용 일정 생성 API만 구현됨

카테고리 관리

  • POST /api/schedule-categories - 생성
  • PUT /api/schedule-categories/:id - 수정
  • DELETE /api/schedule-categories/:id - 삭제
  • PUT /api/schedule-categories-order - 순서 변경

※ GET은 구현됨 (목록 조회)

기타

  • GET /api/kakao/places - 카카오 장소 검색 프록시

파일 비교표

Express (backend-backup) Fastify (backend) 상태
routes/admin.js (로그인) routes/auth.js 완료
routes/admin.js (앨범 CRUD) routes/albums/index.js 완료
routes/admin.js (사진/티저) routes/albums/photos.js, teasers.js 완료
routes/admin.js (멤버 수정) routes/members/index.js 완료
routes/admin.js (일정 삭제) routes/schedules/index.js 완료
routes/admin.js (일정 생성/수정) - 미완료
routes/admin.js (카테고리 CUD) - 미완료
routes/admin.js (봇 관리) routes/admin/bots.js 완료
routes/admin.js (할당량) routes/admin/bots.js 완료
routes/admin.js (카카오) - 미완료
- routes/admin/youtube.js 신규
- routes/admin/x.js 신규
routes/albums.js routes/albums/index.js 완료
routes/members.js routes/members/index.js 완료
routes/schedules.js routes/schedules/index.js 완료
routes/stats.js routes/stats/index.js 완료
services/youtube-bot.js services/youtube/ 완료
services/youtube-scheduler.js plugins/scheduler.js 완료
services/x-bot.js services/x/ 완료
services/meilisearch.js services/meilisearch/ 완료
services/meilisearch-bot.js services/meilisearch/ 완료
services/suggestions.js services/suggestions/ 완료

참고 사항

  • 기존 Express 코드는 backend-backup/ 폴더에 보존
  • 마이그레이션 시 기존 코드 참조하여 동일 기능 구현
  • DB 스키마 변경 사항:
    • tracksalbum_tracks (이름 변경)
    • venuesconcert_venues (이름 변경)

프론트엔드 마이그레이션 (Strangler Fig)

개요

frontend/ (레거시) → frontend-temp/ (신규)로 점진적 마이그레이션

설계 원칙

  1. react-device-detect 사용

    • App.jsx에서 BrowserView/MobileView로 PC/Mobile 완전 분리
    • User Agent 기반 디바이스 감지
  2. 기능별 폴더 + pc/mobile 하위 폴더

    • 각 페이지 폴더 내에 pc/, mobile/ 서브폴더
    • 비즈니스 로직(api, hooks, stores)은 최상위에서 공유
  3. React Query 사용

    • useQuery로 데이터 패칭 및 캐싱
  4. 관리자 페이지는 PC 전용

    • mobile 폴더 없이 단일 구조

App.jsx 라우팅 구조

import { BrowserView, MobileView } from 'react-device-detect';

function App() {
  return (
    <BrowserRouter>
      <BrowserView>
        <Routes>
          {/* Admin routes */}
          <Route path="/admin" element={<AdminLogin />} />
          <Route path="/admin/*" element={<AdminRoutes />} />

          {/* Public routes with PC Layout */}
          <Route element={<PCLayout />}>
            <Route path="/" element={<PCHome />} />
            <Route path="/members" element={<PCMembers />} />
            <Route path="/album" element={<PCAlbum />} />
            <Route path="/album/:name" element={<PCAlbumDetail />} />
            ...
          </Route>
        </Routes>
      </BrowserView>

      <MobileView>
        <Routes>
          <Route element={<MobileLayout />}>
            <Route path="/" element={<MobileHome />} />
            <Route path="/members" element={<MobileMembers />} />
            ...
          </Route>
        </Routes>
      </MobileView>
    </BrowserRouter>
  );
}

전체 마이그레이션 체크리스트

API 계층

공개 API

  • client.js (fetchApi, fetchAuthApi)
  • albums.js
  • members.js
  • schedules.js
  • auth.js

관리자 API (api/admin/)

  • albums.js
  • members.js
  • schedules.js
  • categories.js
  • stats.js
  • bots.js
  • suggestions.js

훅 (hooks/)

  • useAlbumData.js
  • useMemberData.js
  • useScheduleData.js
  • useScheduleSearch.js
  • useScheduleFiltering.js
  • useCalendar.js
  • useMediaQuery.js
  • useAdminAuth.js

관리자 훅 (hooks/) - 관리자 영역 마이그레이션 시 진행

  • useToast.js (관리자 페이지 전용)

스토어 (stores/)

  • useScheduleStore.js
  • useAuthStore.js
  • useUIStore.js

상수 (constants/)

  • index.js (CATEGORY_ID, MIN_YEAR, SEARCH_LIMIT 등)

유틸리티 (utils/)

  • index.js
  • date.js
  • format.js
  • cn.js (className 유틸)
  • schedule.js (일정 관련 유틸)

공통 컴포넌트 (components/common/)

  • Loading.jsx
  • ErrorBoundary.jsx
  • Toast.jsx
  • Lightbox.jsx
  • LightboxIndicator.jsx
  • Tooltip.jsx
  • ScrollToTop.jsx

PC 컴포넌트 (components/pc/)

  • Layout.jsx
  • Header.jsx
  • Footer.jsx
  • Calendar.jsx
  • ScheduleCard.jsx
  • BirthdayCard.jsx
  • CategoryFilter.jsx

Mobile 컴포넌트 (components/mobile/)

  • Layout.jsx
  • Calendar.jsx
  • ScheduleCard.jsx
  • ScheduleListCard.jsx
  • ScheduleSearchCard.jsx
  • BirthdayCard.jsx

공용 일정 컴포넌트 (components/schedule/)

  • confetti.js (fireBirthdayConfetti)
  • AdminScheduleCard.jsx

관리자 컴포넌트 (components/admin/)

  • AdminLayout.jsx
  • AdminHeader.jsx
  • ConfirmDialog.jsx
  • CustomDatePicker.jsx
  • CustomTimePicker.jsx
  • NumberPicker.jsx

페이지 - Home (pages/home/)

  • pc/Home.jsx
  • mobile/Home.jsx

페이지 - Members (pages/members/)

  • pc/Members.jsx
  • mobile/Members.jsx

페이지 - Album (pages/album/)

  • pc/Album.jsx
  • pc/AlbumDetail.jsx
  • pc/AlbumGallery.jsx
  • pc/TrackDetail.jsx
  • mobile/Album.jsx
  • mobile/AlbumDetail.jsx
  • mobile/AlbumGallery.jsx
  • mobile/TrackDetail.jsx

페이지 - Schedule (pages/schedule/)

  • sections/DefaultSection.jsx
  • sections/XSection.jsx
  • sections/YoutubeSection.jsx
  • sections/utils.js
  • sections/index.js
  • pc/Schedule.jsx
  • pc/ScheduleDetail.jsx
  • pc/Birthday.jsx
  • mobile/Schedule.jsx
  • mobile/ScheduleDetail.jsx
  • mobile/Birthday.jsx

페이지 - Common (pages/common/)

  • pc/NotFound.jsx
  • mobile/NotFound.jsx

페이지 - Admin (pages/admin/) - PC 전용

  • Login.jsx
  • Dashboard.jsx
  • members/List.jsx
  • members/Edit.jsx
  • albums/List.jsx
  • albums/Form.jsx
  • albums/Photos.jsx
  • schedules/List.jsx
  • schedules/Form.jsx
  • schedules/YouTubeForm.jsx
  • schedules/XForm.jsx
  • schedules/YouTubeEditForm.jsx
  • categories/List.jsx
  • bots/Manager.jsx
  • dict/Manager.jsx

기타

  • App.jsx (BrowserView/MobileView 라우팅)
  • main.jsx

CSS 파일

  • index.css
  • mobile.css (모바일 전용 스타일, 달력 등)
  • pc.css (PC 전용 스타일)

기타 파일

  • data/dummy.js (개발용 더미 데이터, 필요 시 추가)
  • .env (VITE_KAKAO_JS_KEY - 콘서트 장소 검색용, 관리자 기능에서 사용)
  • public/favicon.ico (필요 시 추가)

사용 라이브러리 (package.json)

라이브러리 용도 사용 위치
react-device-detect PC/Mobile 분기 App.jsx
@tanstack/react-query 데이터 패칭 모든 페이지
@tanstack/react-virtual 가상화 리스트 관리자 일정 목록
react-calendar 캘린더 일정 페이지
react-colorful 색상 선택 카테고리 관리
react-photo-album 앨범 갤러리 앨범 갤러리
react-infinite-scroll-component 무한 스크롤 일정 검색
react-intersection-observer 뷰포트 감지 애니메이션
react-ios-time-picker 시간 선택 일정 폼
react-linkify URL 자동 링크 일정 상세
react-window 가상화 리스트 긴 목록
swiper 슬라이더 앨범 상세
canvas-confetti 축하 효과 생일 페이지
framer-motion 애니메이션 전체
dayjs 날짜 처리 전체
zustand 상태 관리 전체

특수 패턴 및 주의사항

React Query 고급 사용

  • useInfiniteQuery - 일정 검색 무한 스크롤 (mobile/Schedule)
  • useQuery - 일반 데이터 패칭

Swiper 사용 시

import { Swiper, SwiperSlide } from 'swiper/react';
import { Virtual } from 'swiper/modules';
import 'swiper/css';
  • 사용 위치: mobile/Members, mobile/AlbumDetail, mobile/AlbumGallery

가상화 리스트

  • useVirtualizer from @tanstack/react-virtual
  • 사용 위치: mobile/Schedule, admin/AdminSchedule

교차 관찰자

  • useInView from react-intersection-observer
  • 사용 위치: mobile/Schedule (무한 스크롤 트리거)

축하 효과

  • canvas-confetti - 생일 페이지 폭죽 효과
  • 사용 위치: pc/Birthday, mobile/Schedule (생일 일정)

색상 선택기

  • HexColorPicker from react-colorful
  • 사용 위치: admin/AdminScheduleCategory

앨범 갤러리

  • RowsPhotoAlbum from react-photo-album
  • 사용 위치: pc/AlbumGallery, mobile/AlbumGallery

Kakao API (미구현)

  • 콘서트 장소 검색: /api/admin/kakao/places
  • 환경변수: VITE_KAKAO_JS_KEY
  • 사용 예정: 콘서트 일정 추가 시 장소 검색

마이그레이션 진행 상황

완료된 작업

  • Phase 1: 프로젝트 셋업
  • Phase 2: 유틸리티 및 상수
  • Phase 3: Zustand 스토어
  • Phase 4: API 계층 (공개 API)
  • Phase 5: 커스텀 훅
  • Phase 6: 공통 컴포넌트
  • Phase 7: PC/Mobile 레이아웃 컴포넌트
  • Phase 8: App.jsx (BrowserView/MobileView 라우팅)
  • Phase 9: 공개 페이지 전체
    • Home, Members, Album, AlbumDetail, AlbumGallery, TrackDetail
    • Schedule, ScheduleDetail, Birthday

미완료 작업

공개 영역

  • 모두 완료

관리자 영역 (별도 요청 시 진행)

  • 관리자 API 전체 (api/admin/)
  • 관리자 컴포넌트 전체 (components/admin/)
  • 관리자 페이지 전체 (pages/admin/)
  • useToast 훅 (관리자 전용)

최종 검증

  • 모든 라우트 동작 확인
  • PC/Mobile 전환 테스트
  • 관리자 기능 테스트
  • frontend-temp → frontend 교체