docs(spec): music YouTube 탭 프론트엔드 설계 스펙

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-01 14:32:32 +09:00
parent be0094b83f
commit 47a4b1e231

View File

@@ -0,0 +1,208 @@
# 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
<button onClick={() => {
setTab('youtube')
setInitialTrackId(track.id)
}}>🎬 영상 만들기</button>
```
`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 바로 구현)