한눈에
- 음악·가사·추천·뮤직비디오가 서비스마다 흩어져 있는 걸 하나의 데스크톱 앱으로 묶은 팀 프로젝트다. 나는 팀장으로 구현 대부분을 직접 맡았고, 특히 여러 외부 서비스를 엮는 백엔드 — 통합 검색·AI 추천·가사·재생 엔진과, 앱과 DB를 잇는 소켓 서버를 책임졌다.
- 학생이 쓸 수 있는 합법 스트리밍 API가 없어서, 유튜브에서 곡을 검색해 ‘진짜 원곡 오디오’를 점수로 골라내는 엔진을 만들었다(90여 개 제외 키워드 + 가중치 점수). 곡 검색·정보는 Spotify, 실제 음원은 이 엔진이 맡아 둘을 이어 붙였다.
- AI 추천은 “후보는 LLM, 정답은 Spotify”로 나눠 없는 곡(환각)을 거르고, 가사는 싱크 가사(LRCLIB)를 먼저, 없으면 Genius에서 긁어오며, 듣는 곡에 감정 이모지를 남길 수 있다.
내가 맡은 범위
음악 스트리밍이 서비스마다 흩어져 있어, 곡·가사·추천·뮤직비디오를 한 앱에 묶는 팀 프로젝트다. 5명이 함께 했고 나는 팀장으로 구현 대부분을 직접 맡았다. 특히 여러 외부 서비스를 하나처럼 엮는 백엔드를 책임졌다.
- 백엔드·API 대부분 — 통합 검색, AI 추천, 가사 수집, 재생(스트리밍) 엔진, 그리고 앱과 MySQL을 잇는 소켓 서버.
- UI도 대부분 — 홈·차트·검색·상세·추천·가사·재생목록·플레이어 화면을 직접 만들고 백엔드에 연결했다.
- DB 설계 — 사용자·곡·앨범·플레이리스트·좋아요 등 전체 스키마를 직접 설계했다.
로그인(시작하기) 화면의 UI와 플레이리스트의 DB 연동(백엔드)은 다른 팀원이 맡았다.
내가 내린 설계 결정
공식 음원 API가 없어서, 유튜브에서 진짜 원곡을 찾아내는 재생 엔진
학생이 합법적으로 쓸 수 있는 직접 스트리밍 API가 없었다. 그래서 곡을 재생할 때 유튜브에서 검색해 가장 ‘진짜 원곡 오디오’에 가까운 영상을 골라 음원으로 쓰게 했다. 그냥 검색하면 커버·노래방·리믹스·직캠·리액션·1시간 반복이 섞여 나오기 때문에, (1) 90여 개 제외 키워드로 걸러내고, (2) 제목이 곡명과 충분히 겹치는지 확인하고, (3) 공식 MV·공식 오디오·VEVO·자동 생성(Topic) 채널엔 가산점, 커버·피아노·번역엔 감점을 주는 점수 규칙으로 후보를 추렸다. 그 뒤 점수가 높은 것부터 음원 변환을 시도해 첫 성공을 재생에 쓴다.
메타데이터 먼저, 오디오는 비동기 + 다음 곡 미리 준비
곡을 누르면 제목·앨범아트는 즉시 보여주고, 실제 오디오(유튜브→음원) 해석은 뒤에서 처리해 화면이 멈추지 않게 했다. 또 재생이 80%쯤 지나면 다음 곡의 음원을 미리 해석해 캐시해, 곡이 넘어갈 때 끊김을 줄였다.
LLM은 후보, Spotify가 정답 — 환각을 거른 AI 추천
“신나는 노래 추천해줘” 같은 자연어를 그대로 Perplexity에 보내 추천을 받되, LLM이 지어낸(없는) 곡을 그대로 믿지 않게 했다. LLM에게는 가수·제목만 받고, 각 곡을 다시 Spotify에서 검색해 실제 재생 가능한 트랙으로 바꿔 붙인다. 매칭이 잘 되도록 LLM 출력 형식도 프롬프트로 강제했다(소개문과 곡 목록을 정해진 표시로 구분, ‘Artist - Title’ 한 줄, 공식 표기 사용, 온도 0.3). 플레이리스트나 재생 기록을 넣어 “이 취향과 비슷한 곡”도 받을 수 있다.
싱크 가사 우선, 없으면 평문 — 2단 가사 수집
가사는 시간이 찍힌 싱크 가사(LRCLIB)를 먼저 찾아 재생에 맞춰 한 줄씩 따라가게 하고, 없으면 Genius에서 평문 가사를 긁어 보여준다. 싱크 정보를 평문 가사의 줄 구조에 다시 맞춰, 빈 줄·후렴 구조가 깨지지 않게 정렬한다.
가사 한 줄로 곡 찾기
기억나는 가사 한 구절로 곡을 검색할 수 있다. 가사 전문 검색(Genius)으로 곡을 특정한 뒤, 그 곡을 다시 Spotify에서 찾아 실제 재생 가능한 트랙으로 이어 준다.
갖춘 기능
내가 만든 기능을 정리했다. 모든 데이터는 로그인 후 자체 소켓 서버를 거쳐 MySQL과 연결돼 동작한다.
- 회원 / 로그인 — 이메일 가입(중복 검사)·로그인·세션 유지 (시작하기 화면의 UI는 팀원 담당)
- 네비게이션 바 — 로고(홈)·검색창·검색 모드 전환(통합/가사/AI 추천)·사용자 메뉴
- 라이브러리 바 — 내 플레이리스트(커버는 첫 곡 앨범아트)·팔로우한 아티스트 목록
- 메인 영역 — 홈(멜론·빌보드·Spotify·뮤직비디오 차트 미리보기), 통합 검색(곡·앨범·아티스트·유튜브), 가사 검색, 아티스트/앨범 상세(인기·최신 정렬), AI 추천 결과, 가사, 뮤직비디오
- 재생목록 바 — 현재 재생목록 표시, 셔플/반복에 따른 순서 반영
- 플레이어 바 — 재생/일시정지·이전·다음·진행바·음량·셔플·3단계 반복, 곡/앨범 좋아요·아티스트 팔로우, 감정 이모지
- 플레이리스트 — 생성·곡 추가·곡 목록 (화면은 내가, DB 연동은 팀원 담당)
차트(좌) — 멜론·빌보드·Spotify·뮤직비디오 차트의 곡 순위. 통합 검색(우) — 한 검색어로 곡·앨범·아티스트·유튜브를 탭으로 나눠 본다.
아티스트 상세(좌) — 프로필과 발매 곡·앨범 전체(인기순/최신순 정렬). 앨범 상세(우) — 수록곡과 앨범 정보.
플레이어(좌) — 재생·셔플·3단계 반복·음량과 좋아요·가사·이모지 토글. 뮤직비디오(우) — 유튜브에서 찾은 MV를 앱 안에서 재생.
전체 기능 펼쳐 보기
회원 / 로그인
- 이메일·이름·비밀번호로 가입(이메일 중복 검사), 로그인 시 사용자 번호를 연결에 기억해 세션 유지
- 로그인 창이 연 소켓을 메인 앱에 넘겨 한 연결로 세션 전체를 쓴다 (시작하기 화면 UI는 팀원)
네비게이션 바
- 로고(홈 이동), 검색창, 사용자 메뉴
- 검색 모드 전환 — 통합 검색 · 가사 검색 · AI 추천(자연어 기반 · 플레이리스트 기반 · 재생기록 기반)
라이브러리 바
- 내 플레이리스트 목록(커버는 첫 곡의 앨범아트, 없으면 기본 이미지)
- 팔로우한 아티스트 목록(원형), 클릭 시 아티스트 상세로 이동
메인 영역
- 홈: 멜론 실시간/주간·빌보드·Spotify·뮤직비디오 차트 미리보기와 전체 보기
- 통합 검색: 한 검색어로 곡·앨범·아티스트·유튜브를 탭으로 분리(Spotify·YouTube API)
- 가사 검색: 기억나는 가사 한 구절로 곡 찾기(Genius→Spotify)
- 아티스트 상세: 프로필·발매 곡 전체·발매 앨범 전체, 인기순/최신순 정렬
- 앨범 상세: 수록곡·앨범 정보·참여 아티스트
- AI 추천 결과: 자연어·플레이리스트·재생기록 기반 추천 — 소개 문장 + 재생 가능한 곡 목록(Perplexity→Spotify)
- 가사: 싱크 가사(LRCLIB)는 재생에 맞춰 강조, 없으면 Genius 평문
- 뮤직비디오: 유튜브에서 찾은 MV를 앱 안에서 재생
재생목록 바
- 현재 재생 중인 곡 목록(현재 곡 강조, 클릭 시 점프)
- 셔플/반복 상태에 따라 순서 갱신(한 곡 반복이면 현재 곡만)
플레이어 바
- 재생/일시정지·이전·다음(2초 이후면 처음으로)·진행바 드래그·시간 표시
- 음량 슬라이더·음소거, 셔플, 3단계 반복(없음/전체/한 곡)
- 곡 좋아요·앨범 좋아요·아티스트 팔로우, 가사·뮤직비디오·감정 이모지 토글
- 재생 시작 시 재생 기록 자동 저장
플레이리스트
- 생성·곡 추가·곡 목록 보기 (화면은 내가, DB 연동은 팀원)
정직하게 — 내가 한 일
이 앱의 코드는 AI를 페어로 구현했다. 그리고 일부는 외부의 힘을 빌렸다 — 실제 오디오 변환은 외부 서비스(RapidAPI)가 하고, 추천의 ‘지능’은 Perplexity, 가사 출처는 Genius·LRCLIB, 오디오 재생은 JavaFX, JSON 처리·가사 크롤링·DB 커넥션 풀 같은 공통 부분은 기존 라이브러리(커넥션 풀은 공개 보일러플레이트)를 가져다 썼다. 로그인 화면 UI와 플레이리스트의 DB 연동은 팀원이 맡았다.
내가 책임진 핵심은 흩어진 외부 서비스들을 어떤 규칙으로 하나처럼 엮을지 정하고 만든 것이다 — 유튜브에서 진짜 원곡을 골라내는 재생 엔진, 없는 곡을 거르는 AI 추천, 싱크/평문 2단 가사, 그리고 앱과 DB를 잇는 소켓 서버. 화려한 화면보다, 여러 서비스를 하나처럼 움직이게 만드는 백엔드를 맡았다.