# Music YouTube Tab Frontend — Design Spec **Date:** 2026-05-01 **Repo:** `web-page` (React + Vite SPA at `/Users/jaeohpark/development/web-page/`) --- ## 1. Goal MusicStudio 페이지에 **🎯 YouTube 탭**을 추가한다. 기존 4개 탭(Create / Lyrics / Library / Remix) 옆에 하나 더 붙이며, 탭 내부에 3개의 서브탭을 둔다. - **🎬 영상 제작** — 트랙 선택 → 포맷·국가 설정 → 렌더링 → 내보내기 - **💰 수익 추적** — 수동 수익 기록 입력 + 장르별 RPM 차트 + 기록 테이블 - **📊 시장 트렌드** — agent-office가 매일 수집한 YouTube/Trends/Billboard 데이터 표시 + AI 프롬프트 추천 --- ## 2. 영향 파일 ### 수정 | 파일 | 변경 내용 | |------|-----------| | `src/pages/music/MusicStudio.jsx` | tab 상태에 `'youtube'` 추가, 탭 버튼 추가, YoutubeTab 렌더링 | | `src/api.js` | 비디오 프로젝트 / 수익 / 시장 트렌드 API 함수 추가 | ### 신규 생성 | 파일 | 역할 | |------|------| | `src/pages/music/components/YoutubeTab.jsx` | YouTube 탭 루트 컴포넌트 (서브탭 상태 관리) | | `src/pages/music/components/VideoProjectsTab.jsx` | 🎬 영상 제작 서브탭 | | `src/pages/music/components/RevenueTab.jsx` | 💰 수익 추적 서브탭 | | `src/pages/music/components/TrendsTab.jsx` | 📊 시장 트렌드 서브탭 | --- ## 3. 컴포넌트 계층 ``` MusicStudio └── [tab === 'youtube'] └── YoutubeTab ├── subtab 상태: 'video' | 'revenue' | 'trends' ├── [subtab === 'video'] → VideoProjectsTab ├── [subtab === 'revenue'] → RevenueTab └── [subtab === 'trends'] → TrendsTab ``` **YoutubeTab props:** - `library: Array` — 라이브러리 트랙 목록 (MusicStudio에서 내려줌, 트랙 선택 드롭다운용) - `initialTrackId?: string` — Library 탭의 "영상 만들기" 버튼 클릭 시 pre-select용 --- ## 4. 서브탭 상세 ### 4-1. VideoProjectsTab (`subtab === 'video'`) **① 새 영상 만들기 패널** - 트랙 선택 드롭다운 (`library` prop에서 목록, `title` 표시) - 형식 선택: `비주얼라이저` | `슬라이드쇼` (toggle) - 타겟 국가 칩: BR / US / ID / MX / KR (복수 선택 가능) - "프로젝트 생성" 버튼 → `POST /api/music/video-project` **② 영상 프로젝트 목록** - `GET /api/music/video-projects` 폴링 (렌더링 중인 프로젝트 있을 때 5초 간격) - 상태별 표시: - `pending` — "대기" 배지 + "▶ 렌더" 버튼 → `POST /api/music/video-project/:id/render` - `rendering` — "처리중" 배지 + 진행 바 (시작 시각 기준 경과 시간 표시) - `done` — "✓ 완료" 배지 + "↓ 내보내기" 버튼 - `failed` — "실패" 배지 (빨간색) **③ 내보내기 패키지 (done 상태 프로젝트 선택 시)** - `GET /api/music/video-project/:id/export` → `{mp4_url, thumbnail_url, metadata}` - mp4 다운로드 링크, thumbnail 다운로드 링크, metadata.json 미리보기 (title / tags / target) **상태 관리:** ```js const [projects, setProjects] = useState([]) const [selectedTrackId, setSelectedTrackId] = useState(initialTrackId ?? '') const [format, setFormat] = useState('visualizer') const [countries, setCountries] = useState(['BR']) const [creating, setCreating] = useState(false) const [exportData, setExportData] = useState(null) // 선택된 done 프로젝트의 export ``` --- ### 4-2. RevenueTab (`subtab === 'revenue'`) **대시보드 카드 (3개)** - `GET /api/music/revenue/dashboard` → `{total_revenue_usd, total_views, avg_rpm}` - 총 수익 / 총 조회수 / 가중평균 RPM **장르별 RPM 바 차트** - `GET /api/music/revenue` → 레코드 목록에서 장르별로 RPM 집계 - 바 차트 (CSS 기반, 라이브러리 없음) — genre / rpm / color 매핑 **수익 기록 추가 폼** - 필드: `yt_video_id`, `record_month` (YYYY-MM), `revenue_usd`, `views`, `country` - "저장" → `POST /api/music/revenue` - 성공 시 목록 + 대시보드 리프레시 **수익 기록 테이블** - `GET /api/music/revenue` — 영상 제목 / 월 / 수익 / 조회수 / RPM - 행 클릭 → 수정 폼 인라인 펼침 - 삭제 버튼 → `DELETE /api/music/revenue/:id` **장르 추론:** `yt_video_id`는 자유 입력이고 장르 컬럼이 DB에 없으므로, `genre` 필드를 수익 기록 폼에 optional 셀렉트로 추가한다. DB 스키마에 이미 없으면 프론트에서만 관리하지 않고, API 명세 확인 후 처리. > **참고:** `revenue_records` 테이블에 `genre` 컬럼이 없다. 차트는 `yt_video_id`별 집계만 가능. 장르별 RPM 차트는 "영상별 RPM 비교"로 레이블을 바꿔서 구현한다. **상태 관리:** ```js const [dashboard, setDashboard] = useState(null) const [records, setRecords] = useState([]) const [form, setForm] = useState({ yt_video_id:'', record_month:'', revenue_usd:'', views:'', country:'BR' }) const [editingId, setEditingId] = useState(null) ``` --- ### 4-3. TrendsTab (`subtab === 'trends'`) **수집 상태 바** - `GET /api/music/market/report/latest` → `{report_date, created_at, top_genres, recommended_styles}` - 마지막 수집 일시 + 트렌드 수 표시 - "↻ 수동 수집" 버튼 → `POST /api/agent-office/youtube/research` (body: `{}`) **오늘의 인기 장르 Top 5** - `top_genres` 배열에서 상위 5개 렌더링 - 각 항목: 장르명 / 대상 국가 플래그 / 점수 바 **AI 추천 Suno 프롬프트** - `GET /api/music/market/suggest` → `[{genre, suno_prompt, target_countries, reason}]` - 카드 형태, 프롬프트 클릭 시 클립보드 복사 **트렌드 리포트 이력** - `GET /api/music/market/report` → 날짜 목록 - 날짜 클릭 → 해당 날짜 리포트 상세 표시 (top_genres + recommended_styles) **상태 관리:** ```js const [latestReport, setLatestReport] = useState(null) const [reports, setReports] = useState([]) const [suggestions, setSuggestions] = useState([]) const [selectedReport, setSelectedReport] = useState(null) const [researching, setResearching] = useState(false) ``` --- ## 5. API 추가 목록 (`src/api.js`) ```js // 기존 api.js 헬퍼: apiGet / apiPost / apiPut / apiDelete (plain fetch 래퍼) // Video Projects export const createVideoProject = (data) => apiPost('/api/music/video-project', data) export const getVideoProjects = () => apiGet('/api/music/video-projects') export const renderVideoProject = (id) => apiPost(`/api/music/video-project/${id}/render`) export const exportVideoProject = (id) => apiGet(`/api/music/video-project/${id}/export`) export const deleteVideoProject = (id) => apiDelete(`/api/music/video-project/${id}`) // Revenue export const getRevenueDashboard = () => apiGet('/api/music/revenue/dashboard') export const getRevenueRecords = () => apiGet('/api/music/revenue') export const addRevenueRecord = (data) => apiPost('/api/music/revenue', data) export const updateRevenueRecord = (id, data) => apiPut(`/api/music/revenue/${id}`, data) export const deleteRevenueRecord = (id) => apiDelete(`/api/music/revenue/${id}`) // Market Trends export const getLatestTrendReport = () => apiGet('/api/music/market/report/latest') export const getTrendReports = () => apiGet('/api/music/market/report') export const getMarketSuggestions = () => apiGet('/api/music/market/suggest') export const triggerYoutubeResearch = () => apiPost('/api/agent-office/youtube/research', {}) ``` --- ## 6. Library 탭 연동 `MusicStudio.jsx`의 `LibraryCard` 컴포넌트에 **"🎬 영상 만들기"** 버튼 추가: ```jsx ``` `initialTrackId` 상태를 MusicStudio 루트에 두고 YoutubeTab에 prop으로 내려준다. VideoProjectsTab이 마운트되면 해당 트랙을 드롭다운에 pre-select. --- ## 7. 스타일 가이드 기존 MusicStudio.css의 다크 테마 변수 재사용: - 배경: `#111827` / `#0d1117` / `#1f2937` - 강조색: `#22c55e` (초록, 완료·생성), `#f59e0b` (노랑, 처리중), `#3b82f6` (파랑, 수익), `#a855f7` (보라, 트렌드) - 새 CSS 클래스는 `MusicStudio.css`에 추가 (별도 파일 없음) --- ## 8. 범위 외 (Out of scope) - YouTube Analytics OAuth 자동 동기화 (나중에 확장) - 영상 업로드 자동화 (YouTube Data API write scope) - 차트 라이브러리 도입 (CSS 바로 구현)