# Kord - YouTube 음악 재생 기능 기획안 (YouTube Music Playback)

## 체인지로그 (Changelog)
- **2026-03-30**: 최초 기획안 작성

---

## 1. 개요

YouTube 음악 재생 기능은 사용자가 텍스트 기반 명령으로 음악을 검색하거나 YouTube 링크를 입력하면,
현재 참여 중인 음성 채팅방에 봇이 입장하여 재생 목록(플레이리스트)을 관리하고 오디오를 재생하는 기능입니다.

이 기능은 서버 유틸리티를 넘어서 실시간 상호작용 기능으로 확장되는 첫 사례이며,
음성 연결, 큐 관리, UI 컨트롤, 외부 미디어 소스 처리까지 포함하는 비교적 큰 범위의 기능입니다.

### 목표

- 문자열 검색으로 YouTube 영상을 찾아 재생 목록에 추가할 수 있어야 함
- YouTube 링크를 입력해 직접 재생 목록에 추가할 수 있어야 함
- 현재 재생 목록을 조회할 수 있어야 함
- 인덱스 기반으로 재생 목록 항목을 삭제할 수 있어야 함
- 재생 중지 / 스킵 / 일시정지 / 재개 등 기본 컨트롤을 버튼 또는 이모지 기반 UI로 제공해야 함
- 음악 추가 요청 시, 요청자가 있는 음성 채팅방에 봇이 자동 입장하고 재생을 시작해야 함
- 마지막에 봇을 음성 채팅방에서 내보내는 기능이 있어야 함

---

## 2. 지원 범위 (MVP)

### 포함

- `/music add query:<문자열>`
- `/music add url:<YouTube 링크>`
- `/music queue`
- `/music remove index:<번호>`
- `/music skip`
- `/music stop`
- `/music leave`
- 재생 컨트롤 메시지 (버튼 또는 이모지 라벨 기반)
- 음성 채널 자동 입장 및 큐 기반 연속 재생

### 제외 (초기 범위 외)

- Spotify, SoundCloud 등 타 플랫폼 연동
- 반복 재생 / 셔플 / 볼륨 조절
- 길드별 DJ 역할 분리
- 재생 이력 저장
- 노래 가사 표시

---

## 3. 사용자 시나리오

### 시나리오 A: 검색어로 곡 추가

1. 사용자가 음성 채널에 입장한 상태에서 `/music add query:아이유 좋은날` 실행
2. 봇이 검색 결과 1위를 선택하거나 선택 UI를 제공
3. 재생 목록에 곡을 추가
4. 봇이 음성 채널에 자동 입장
5. 현재 재생 중이 없다면 즉시 재생 시작

### 시나리오 B: 링크로 곡 추가

1. 사용자가 `/music add url:https://www.youtube.com/watch?v=...` 실행
2. 봇이 링크 메타데이터를 파싱
3. 재생 목록에 항목 추가
4. 이미 재생 중이면 큐 뒤에 대기

### 시나리오 C: 큐 조회 및 삭제

1. 사용자가 `/music queue` 실행
2. 봇이 현재 재생곡과 대기열을 인덱스와 함께 Embed로 표시
3. 사용자가 `/music remove index:3` 실행
4. 3번 항목이 큐에서 제거됨

### 시나리오 D: 컨트롤 UI 사용

1. 재생 시작 시 봇이 "지금 재생 중" 메시지를 게시
2. 메시지에는 ⏸️, ▶️, ⏭️, ⏹️ 같은 버튼이 포함됨
3. 사용자가 버튼을 눌러 재생 상태를 제어

---

## 4. 명령 구조 제안

### `/music add`

입력 방식:

- `query`: YouTube 검색 문자열
- `url`: YouTube 링크

규칙:

- 두 옵션 중 하나만 입력
- 사용자는 반드시 음성 채널에 있어야 함

### `/music queue`

출력:

- 현재 재생 중 항목
- 대기열 목록
- 각 곡의 인덱스, 제목, 길이, 요청자

### `/music remove`

입력:

- `index`: 큐에서 제거할 번호

### `/music skip`

- 현재 곡을 스킵하고 다음 곡 재생

### `/music stop`

- 재생 중지
- 현재 곡 정지 및 대기열 비움 여부는 정책 선택 필요

### `/music leave`

- 봇을 음성 채널에서 퇴장시킴
- 기본 정책은 큐도 함께 정리

---

## 5. 재생 컨트롤 UI

### 컨트롤 메시지 구성

재생 시작 시 텍스트 채널에 Embed + 버튼 메시지 생성

권장 버튼:

- `⏸️` 일시정지
- `▶️` 재개
- `⏭️` 스킵
- `⏹️` 정지
- `📜` 큐 보기

### 정책

- 한 길드당 활성 컨트롤 메시지 1개 유지
- 곡이 바뀔 때 동일 메시지를 업데이트하거나 새 메시지를 생성할지 결정 필요
- MVP에서는 새 메시지 생성보다 기존 메시지 업데이트가 로그 노이즈를 줄이는 데 유리

---

## 6. 큐 및 재생 상태 설계

### 핵심 개념

- 재생 상태는 길드 단위로 분리
- 각 길드는 하나의 음성 연결과 하나의 큐를 가짐
- 큐는 메모리 기반으로 시작하고, 필요 시 DB 영속화 확장 가능

### 추천 구조

```ts
interface MusicQueueItem {
  id: string;
  title: string;
  url: string;
  durationSec?: number;
  requestedByUserId: string;
}

interface GuildMusicSession {
  guildId: string;
  voiceChannelId: string;
  textChannelId: string;
  nowPlaying: MusicQueueItem | null;
  queue: MusicQueueItem[];
  paused: boolean;
  controlMessageId?: string;
}
```

### 초기 전략

- 메모리 기반 세션 관리
- 봇 재시작 시 큐는 초기화됨
- 안정화 이후 DB 저장 여부 검토

---

## 7. 음성 입장 및 재생 흐름

### 자동 입장

- `/music add` 실행 시 사용자의 음성 채널을 확인
- 봇이 해당 채널에 없으면 자동 입장
- 이미 다른 채널에 있으면 정책 필요

### 기본 정책 제안

- 같은 길드 내에서 봇이 이미 재생 중이면 다른 채널 요청은 거부
- "현재 다른 음성 채널에서 사용 중" 메시지 제공

### 자동 퇴장

- `/music leave`로 수동 퇴장 가능
- 추가 정책 후보:
  - 큐가 끝나고 1분 뒤 자동 퇴장
  - 음성 채널에 봇만 남으면 자동 퇴장

---

## 8. YouTube 검색 및 스트리밍 전략

> [!IMPORTANT]
> YouTube 관련 기능은 라이브러리 안정성, 차단 이슈, 서비스 정책을 반드시 검토해야 합니다.

### 검색

가능한 접근:

- YouTube 공식 API 사용
- 서드파티 검색 라이브러리 사용

### 오디오 스트리밍

가능한 접근:

- `@discordjs/voice` 기반 음성 재생
- YouTube 스트림 추출 라이브러리 사용

### 기술 리스크

- YouTube 구조 변경 시 스트림 추출 라이브러리 고장 가능
- 지역 제한 / 연령 제한 / 라이브 영상 처리 문제
- 긴 재생 목록에서 메모리 및 연결 안정성 문제

---

## 9. 권한 및 운영 정책

### 봇 권한

- `Connect`
- `Speak`
- `View Channel`
- 텍스트 채널의 `Send Messages`, `Embed Links`

### 사용자 권한

- 기본적으로 일반 사용자도 곡 추가 가능
- `skip`, `stop`, `leave`, `remove`는 다음 중 하나로 제한 가능
  - 관리자 전용
  - 요청자 또는 관리자
  - 같은 음성 채널 참여자 전원 허용

### 추천 MVP 정책

- `add`, `queue`: 같은 음성 채널 참여자 누구나 가능
- `skip`, `stop`, `remove`, `leave`: 관리자 또는 같은 음성 채널 참여자 허용

---

## 10. 에러 처리

필수 안내 케이스:

- 사용자가 음성 채널에 없음
- 유효하지 않은 YouTube 링크
- 검색 결과 없음
- 재생 목록 인덱스 범위 오류
- 봇 음성 권한 부족
- 스트림 로드 실패

에러 메시지는 기존 Error Guidance 체계와 연결하는 것이 좋습니다.

---

## 11. 구현 단계 (Phased Implementation)

| 단계 | 내용 |
|------|------|
| **Phase 1** | `@discordjs/voice` 기반 음성 연결, 메모리 큐, `/music add`, `/music queue`, `/music skip`, `/music leave` |
| **Phase 2** | 링크 기반 추가 + 검색 기반 추가 분리, `/music remove`, `/music stop` |
| **Phase 3** | 컨트롤 메시지(⏸️ ▶️ ⏭️ ⏹️) 및 상호작용 처리 |
| **Phase 4** | 자동 퇴장, 권한 정책 세분화, 예외 처리 고도화 |
| **Phase 5** | 반복 재생, 셔플, DJ 역할, 재생 이력 등 확장 기능 |

---

## 12. 검증 계획

### 수동 테스트

1. 음성 채널 입장 후 검색어로 곡 추가
2. 링크로 곡 추가
3. 큐 조회 및 인덱스 삭제
4. 스킵 / 정지 / 퇴장 동작 확인
5. 곡 종료 후 다음 곡 자동 재생 확인
6. 권한 부족 환경에서 적절한 에러 표시 확인

### 자동 테스트

- 큐 삽입 / 삭제 / 스킵 로직 단위 테스트
- 길드별 세션 분리 테스트
- 인덱스 유효성 검사 테스트
- 컨트롤 인터랙션 핸들러 테스트

---

## 13. 관련 문서

| 문서 | 링크 |
|------|------|
| 기능 로드맵 | [`Feature_Roadmap.md`](./Feature_Roadmap.md) |
| 임시 음성 채널 기획 | [`Temp_Voice_Channel_Plan.md`](./Temp_Voice_Channel_Plan.md) |
| 에러 안내 기획 | [`Error_Guidance_Plan.md`](./Error_Guidance_Plan.md) |
