Artune은 사용자가 입력한 일기나 짧은 텍스트를 분석하여, 현재 감정 상태에 가장 적합한 음악 플레이리스트와 시각적 즐거움을 주는 픽셀 아트 디저트를 제공하는 웹 서비스입니다.
단순 음악 추천이 아닌 감정을 더 깊이 느끼고 싶을 때(Immerse) 와 전환하고 싶을 때(Soothe) 두 가지 선택지를 제공합니다.
- AI 감정 분석 & 큐레이션: OpenAI GPT 4.1 mini 모델이 텍스트의 미묘한 감정선을 분석하고, 감정·모드별로 어울리는 아티스트 풀(25명/모드)을 직접 큐레이션합니다.
- Dual Mode Playlist:
- 🎶 감정 심취 (Immerse): 슬플 땐 더 슬픈 음악으로, 기쁠 땐 더 신나는 음악으로 감정을 극대화합니다.
- 🌿 감정 완화 (Soothe): 격한 감정을 차분하게, 혹은 우울한 기분을 산뜻하게 전환합니다.
- 인터랙티브 음악 청취:
- iTunes Search API 기반으로 아티스트별 인기 트랙과 30초 미리듣기를 제공합니다.
- CD 바이닐 인터랙션: 음악 재생 시 CD가 플레이어에 들어가고, 정지 시 **DJ 스크래치 효과(Fade-out & Pitch down)**와 함께 멈추는 디테일한 UX를 구현했습니다.
- 감정 맞춤 Pixel Art: 감정 키워드와 장르를 조합하여 DALL-E 프롬프트를 생성, 매번 다른 '오늘의 디저트' 픽셀 아트를 제공합니다. (해당 기능은 잠시 정지시켰습니다.)
- 실시간 분석 경험: Server-Sent Events (SSE)를 도입하여 감정 분석 → 음악 탐색 → 이미지 생성의 진행 상황을 실시간 프로그레스 바로 시각화했습니다.
사용자의 텍스트가 어떻게 음악과 이미지로 변환되는지 보여주는 데이터 흐름도입니다.
Server-Sent Events (SSE) 를 도입하여, 각 단계가 완료될 때마다 클라이언트에게 실시간으로 피드백을 제공합니다.
- Monorepo: Turborepo (Frontend/Backend 패키지 통합 관리)
- Package Manager: npm Workspaces
- Core: React 19, Vite 7
- State Management: Zustand 5 (전역 상태 및 비동기 액션 관리)
- Styling: Emotion (CSS-in-JS), Framer Motion (고성능 애니메이션)
- Testing: Vitest, React Testing Library
- Core: NestJS 11 (Module 기반 아키텍처)
- Language: TypeScript (strictNullChecks 활성화)
- External APIs:
- OpenAI Chat Completions API: 감정 분석 및 아티스트 큐레이션
- iTunes Search API: 아티스트 기반 트랙 검색 및 미리듣기 음원 확보
- DALL-E API: 이미지 생성 (현재 정적 매핑으로 대체)
- Caching: NestJS CacheModule (아티스트 단위 6시간 버킷 캐시)
- Testing: Jest (서비스 레이어 단위 테스트)
- Protocol: HTTP, SSE (Server-Sent Events)
| 감정 입력 및 로딩 (SSE) | 결과 페이지 (PC View) | 모바일/태블릿 반응형 |
|---|---|---|
![]() |
![]() |
![]() |
| 실시간 분석 진행률 표시 | 아트워크와 플레이리스트 분할 뷰 | 토글형 뷰 전환 & 터치 인터랙션 |
이 프로젝트는 Turborepo를 사용하고 있습니다. 루트 디렉토리에서 한 번의 명령어로 전체 프로젝트를 실행할 수 있습니다.
PORT=3000
OPENAI_API_KEY=your_openai_key
FRONTEND_URL=http://localhost:5173VITE_API_BASE_URL=http://localhost:3000/apinpm installnpm run dev
# Frontend: http://localhost:5173
# Backend: http://localhost:3000artune/
├── apps/
│ ├── backend/ # NestJS Server
│ │ └── src/
│ │ ├── emotion/ # 감정 분석 및 오케스트레이션 (Core)
│ │ ├── music/ # 음악 추천 로직 (Diversity 알고리즘 등)
│ │ ├── itunes/ # iTunes Search API (캐시·rate limit 처리)
│ │ ├── openai/ # GPT 프롬프트 제어
│ │ └── dalle/ # 이미지 생성
│ └── frontend/ # React Client
│ └── src/
│ ├── components/ # LP Card, Toggle, Visualizer 등
│ ├── hooks/ # useAudioScratch, useMediaQuery
│ ├── stores/ # Zustand Store
│ └── pages/
├── package.json
└── turbo.json
Spotify API 정책 변경(Developer Mode 유저 제한, Premium 강제)에 대응해 음악 추천 파이프라인을 iTunes Search API로 완전 이전했습니다.
- LLM 큐레이션 전환: 오디오 피쳐(valence/energy/tempo) 기반 필터링 대신, GPT가 감정·모드별 아티스트 풀을 직접 큐레이션하는 구조로 재설계. 추천 요청당 Spotify API 호출 65회 전부 제거.
- Rate Limit 방어: 429/403을 상태별로 판별해 국가 폴백의 호출 증폭(최대 3배)을 차단하고, 일시적 차단이 6시간 캐시에 오염되는 문제를 수정. throttle 상황에서도 트랙 수율 20/20 유지.
단계별 타이밍 계측을 심어 병목을 실측으로 식별한 뒤 최적화했습니다. (원본 로그)
| 단계 | 응답시간 | 조치 |
|---|---|---|
| Baseline | 17.9s | LLM 52% + iTunes 순차 호출 48%로 병목 분해 |
| SSE 병렬화 | ~13.8s | iTunes 구간 8.6s → 4.5s. 완료 카운트 기반 마일스톤으로 진행률 단조 증가 보장 |
| LLM 출력 축소 | 11.6s | 아티스트 40→25명/모드로 출력 토큰 절감 (수율 20/20 유지 검증) |
- 단순한 play/pause가 아닌, 실제 LP판을 멈추는 듯한 경험을 주기 위해 커스텀 훅(
useAudioScratch)을 구현했습니다. - 재생 속도(
playbackRate)와 볼륨을 프레임 단위로 조절하여 Pitch Down & Fade Out 효과를 구현했습니다. - 탭 전환 시 자동 정지, 메모리 누수 방지를 위한 Cleanup 로직을 철저히 적용했습니다.
- Emotion을 활용해 세련된 Dark Glassmorphism 테마를 구축했습니다.
- PC에서는 한 화면에 아트워크와 리스트를, 모바일에서는 토글 방식을 적용하여 디바이스별 최적화된 레이아웃을 제공합니다.
- 이세민 (@smnm1998)




