4.6 KiB
4.6 KiB
music_bot_v2 — 웹 대시보드(page/)
디스코드 음악봇(../bot)을 브라우저에서 제어하는 웹 대시보드. 디스코드 로그인 후 내가 속한 서버를 골라
검색·재생·대기열 관리·볼륨/탐색 등을 조작하고, 현재 재생 상태를 실시간으로 본다.
- 스택: Next.js 16 (App Router) · React 19 · TypeScript · Tailwind CSS 4 · NextAuth 4(Discord OAuth) · ioredis
- 봇과의 통신: 직접 호출이 아니라 Redis Pub/Sub + Key로 봇과 주고받는다(아래 3장).
- 리포 전체 개요는
../README.md, 봇 본체는../bot/README.md참고.
1. 빠른 시작 (개발)
cd page
npm install
# .env.local 작성 (2장 참고)
npm run dev # http://localhost:3000
빌드/구동: npm run build → npm run start. 린트: npm run lint.
Redis(봇과 공유)와 디스코드 OAuth 앱이 있어야 실제 동작한다. Redis에 연결되지 않으면 부팅 시 에러를 던진다(
src/lib/Redis.ts).
2. 환경변수 (.env.local)
| 변수 | 설명 |
|---|---|
REDIS_HOST / REDIS_PORT |
봇과 공유하는 Redis. 봇 .env의 값과 동일해야 한다(미설정 시 부팅 에러). |
DISCORD_CLIENT_ID / DISCORD_CLIENT_SECRET |
디스코드 OAuth 앱 자격증명(로그인·서버목록 scope). |
NEXTAUTH_SECRET |
NextAuth 세션 서명 키. |
NEXTAUTH_URL |
배포 URL(예: https://music.example.com). 개발은 http://localhost:3000. |
- 로그인 scope는
identify email guilds(유저 정보 + 서버 목록).src/app/api/auth/[...nextauth]/route.ts. - 디스코드 개발자 포털의 OAuth2 Redirect에
<NEXTAUTH_URL>/api/auth/callback/discord를 등록해야 한다.
3. 봇과의 통신 구조 (Redis)
대시보드는 봇을 직접 호출하지 않고 Redis를 메시지 버스로 쓴다. 봇 쪽 구현은 ../bot/src/classes/RedisClient.ts.
3-1. 명령 (site → bot, 요청/응답 RPC) — src/lib/api.ts의 botRpc
site: PUBLISH "site-bot" {action, serverId, userId, requestId, …}
bot : 처리 후 SETEX "<action-key>:<requestId>" (예: player:play:<reqId>) 에 결과 저장
site: 그 키를 짧게 폴링(100ms→최대400ms 백오프, 기본 3초 타임아웃)해 결과 수신
requestId는 CSPRNG(randomUUID). 결과 키는 읽은 즉시 삭제 + TTL 보험.- action:
search,player_play,player_playlist,player_now,player_pause,player_skip,player_seek,player_volume,queue_list,queue_set,queue_remove.
3-2. 실시간 상태 (bot → site, SSE) — src/lib/sse.ts의 botEventStream
bot : PUBLISH "bot-site" {event:"player_update"|"queue_update", guildId}
site: "bot-site" 구독 → serverId 일치하는 것만 EventSource(SSE)로 브라우저에 전달(30초 keep-alive)
- 브라우저는
/api/player/events?serverId=…,/api/queue/events?serverId=…(SSE)를 구독해 상태 변경 알림을 받고now/queue/list를 다시 당겨온다.
4. API 라우트 (src/app/api)
모든 라우트는 세션 가드(requireSession)를 거치고 { success, … } 형태로 응답한다.
- player:
play,pause,skip,seek,volume,playlist,now,events(SSE) - queue:
list,set,remove,events(SSE) - servers: 로그인 유저의 디스코드 서버 목록(봇이 있는 서버로 필터링)
- search: 검색(봇의
searchaction → Spotify/YT Music/YT Video 결과) - auth:
[...nextauth](Discord OAuth)
공용 헬퍼(src/lib/api.ts): requireSession, botRpc, readJsonBody, requireString/Number/Boolean, errorResponse.
5. UI 구성 (src/)
app/layout.tsx,app/page.tsx— 루트 레이아웃/페이지.components/Providers.tsx(세션 등),ToastProvider.tsx.components/layout/—TopNav(상단/서버선택·로그인),LeftSidebar(탐색).components/player/—PlayerBar(재생바/볼륨/탐색),MainContent(검색·결과),QueueSidebar(대기열).types/music.ts—DiscordServer,Track/TrackInfo,SearchTrack,SearchResults등 공용 도메인 타입.next.config.ts— 보안 헤더(CSP: self + discord/spotify/ytimg/google 이미지 CDN만 허용,frame-ancestors 'none'등).
6. 배포 메모
- Next.js 16 standalone/
next start로 구동. 봇과 같은 Redis(.7)에 접근 가능해야 한다. NEXTAUTH_URL/디스코드 Redirect URI를 실제 도메인으로 맞춘다.- 이 디렉터리는 Next가 제공하는 에이전트 규칙 파일(
AGENTS.md,CLAUDE.md)을 둔다 — 코드 수정 전 참고.