시스템 구성

  1. 저장소
  2. 노래방 한 판의 흐름
  3. 데이터
  4. 실행 환경

저장소

하나의 모노레포에 세 개의 앱이 있다.

폴더 역할 기술
woojeongai/ 백엔드 API FastAPI · SQLModel · Alembic · PostgreSQL(pgvector) · Redis · librosa
alexview/ 웹 프론트엔드 Next.js 16 (App Router) · React 19 · Tailwind 4 · shadcn/ui
alexthegreat/ 모바일 앱 Flutter
woojeongai/tools/song_prep/ 곡 준비 도구 (관리자 PC 에서 실행) Demucs · faster-whisper · Docker

백엔드는 앱마다 클린 아키텍처로 나눈다 — domain(엔티티·값 객체·규칙) → app(유스케이스·포트) → adapter(API·DB·S3·librosa·Gemini). 노래방 채점 규칙은 librosa 와 무관한 순수 규칙이라 domain/services 에 두고, 음높이 측정만 어댑터에 둔다.

노래방 한 판의 흐름

[관리자 PC]  완성곡 ─ Demucs ─▶ 보컬 스템 + 반주 스템
                                   │
                                   ▼ 업로드
[백엔드]     보컬 스템 ─ pyin(16kHz, 20ms) ─ 음표로 묶기 ─ 보컬 후처리 ─▶ 정답 음표 (challenge_charts)
             가사 텍스트 + faster-whisper 두 번 ─ 곡 전체 경로 선택 ─▶ 가사 줄 시작 시각

[브라우저]   반주 재생 + 마이크
              ├─ 20ms 마다: YIN 음높이 → 정답 음표와 비교 → 점수·콤보·판정
              ├─ 화면 갱신마다: 캔버스에 음표 흐름과 내 음정 선
              └─ 녹음 (webm) ─ 16kHz WAV 로 변환 ─▶ 제출

[백엔드]     녹음 ─ pyin ─ 같은 규칙으로 다시 채점 ─▶ 최종 점수 (랭킹은 이 값만)
                    └─ Gemini 가 채점 수치를 근거로 코칭 한 줄

데이터

테이블 내용
music_challenges 곡(제목·설명·원곡 S3 키·유형)
challenge_charts 곡 하나의 악보 — 정답 음표(JSON), 가사 줄과 시작 시각, 멜로디·반주 스템 위치, 추출 상태
challenge_submissions 제출(녹음 S3 키, 로그인했으면 사용자)
submission_evaluations 평가 — 점수, AI 코칭, 다음 추천 곡, 노래방 서버 채점(음정·박자·종합)

랭킹은 별도 테이블 없이 평가에서 사람마다 최고 기록 하나를 골라 순위를 매긴다(DISTINCT ON + RANK()). 같은 점수면 먼저 달성한 사람이 위에 보이고 순위 숫자는 같이 나눈다.

실행 환경

  로컬 개발 운영
프론트 WSL Ubuntu 에서 next dev (포트 3100) Vercel (woojeongalex.cloud)
백엔드 · DB · Redis Docker Desktop (docker-compose.local.yml) AWS EC2 — Docker Compose, 메모리 1GB + 스왑 2GB
이 기록 사이트 Docker 로 jekyll serve (포트 4000) EC2 nginx 정적 파일 (demo.woojeongalex.cloud)
파일 S3 (같은 버킷) S3
곡 준비 관리자 PC 의 Docker (CPU) — (EC2 메모리 1GB 로는 못 돌린다)

노래방 모드(마이그레이션 0011~0013 과 곡 준비 도구)는 아직 EC2 에 배포하지 않았다. 배포 전에 nginx 업로드 크기 제한(스템 40MB 이상)과 제출 처리 시간(60초 제한)을 점검해야 한다.