← 전체 프로젝트

Meloji

여러 음원·가사·AI 추천을 하나로 묶은 데스크톱 음악 플레이어

기간
2025.08
구성
팀 프로젝트 — 팀장 · 구현 대부분 직접
내 역할
백엔드·API·UI 대부분 · 검색·추천·가사·재생 엔진 · 소켓 서버 · DB 설계 (구현은 AI 페어)
JavaSwing · JavaFXMySQL · JDBCTCP 소켓 서버Spotify · YouTubeGenius · LRCLIBPerplexity

한눈에

Meloji 시스템 구성도
시스템 구성 — Java 본체와 MySQL을 직접 만든 소켓 서버로 잇고, 재생·뮤직비디오는 Spotify·YouTube·RapidAPI, AI 추천은 Perplexity, 가사는 Genius·LRCLIB에서 가져온다.

내가 맡은 범위

음악 스트리밍이 서비스마다 흩어져 있어, 곡·가사·추천·뮤직비디오를 한 앱에 묶는 팀 프로젝트다. 5명이 함께 했고 나는 팀장으로 구현 대부분을 직접 맡았다. 특히 여러 외부 서비스를 하나처럼 엮는 백엔드를 책임졌다.

로그인(시작하기) 화면의 UI와 플레이리스트의 DB 연동(백엔드)은 다른 팀원이 맡았다.

내가 내린 설계 결정

공식 음원 API가 없어서, 유튜브에서 진짜 원곡을 찾아내는 재생 엔진

학생이 합법적으로 쓸 수 있는 직접 스트리밍 API가 없었다. 그래서 곡을 재생할 때 유튜브에서 검색해 가장 ‘진짜 원곡 오디오’에 가까운 영상을 골라 음원으로 쓰게 했다. 그냥 검색하면 커버·노래방·리믹스·직캠·리액션·1시간 반복이 섞여 나오기 때문에, (1) 90여 개 제외 키워드로 걸러내고, (2) 제목이 곡명과 충분히 겹치는지 확인하고, (3) 공식 MV·공식 오디오·VEVO·자동 생성(Topic) 채널엔 가산점, 커버·피아노·번역엔 감점을 주는 점수 규칙으로 후보를 추렸다. 그 뒤 점수가 높은 것부터 음원 변환을 시도해 첫 성공을 재생에 쓴다.

유튜브 검색 결과 화면
유튜브 검색 — 한 곡을 검색하면 [MV]·공식 영상 후보가 모이고, 제목·채널을 점수로 평가해 진짜 원곡 오디오를 골라 재생에 쓴다.

메타데이터 먼저, 오디오는 비동기 + 다음 곡 미리 준비

곡을 누르면 제목·앨범아트는 즉시 보여주고, 실제 오디오(유튜브→음원) 해석은 뒤에서 처리해 화면이 멈추지 않게 했다. 또 재생이 80%쯤 지나면 다음 곡의 음원을 미리 해석해 캐시해, 곡이 넘어갈 때 끊김을 줄였다.

LLM은 후보, Spotify가 정답 — 환각을 거른 AI 추천

“신나는 노래 추천해줘” 같은 자연어를 그대로 Perplexity에 보내 추천을 받되, LLM이 지어낸(없는) 곡을 그대로 믿지 않게 했다. LLM에게는 가수·제목만 받고, 각 곡을 다시 Spotify에서 검색해 실제 재생 가능한 트랙으로 바꿔 붙인다. 매칭이 잘 되도록 LLM 출력 형식도 프롬프트로 강제했다(소개문과 곡 목록을 정해진 표시로 구분, ‘Artist - Title’ 한 줄, 공식 표기 사용, 온도 0.3). 플레이리스트나 재생 기록을 넣어 “이 취향과 비슷한 곡”도 받을 수 있다.

AI 추천 결과 화면
AI 추천 — "오늘 집에 가는 길에 들을 노래 추천해줘" 같은 자연어 요청에 소개 문장과 곡 목록이 오고, 각 곡은 Spotify에서 재생 가능한 트랙으로 다시 확인해 재생·저장한다.

싱크 가사 우선, 없으면 평문 — 2단 가사 수집

가사는 시간이 찍힌 싱크 가사(LRCLIB)를 먼저 찾아 재생에 맞춰 한 줄씩 따라가게 하고, 없으면 Genius에서 평문 가사를 긁어 보여준다. 싱크 정보를 평문 가사의 줄 구조에 다시 맞춰, 빈 줄·후렴 구조가 깨지지 않게 정렬한다.

실시간 가사 화면
가사 — 재생 시간에 맞춰 현재 줄이 강조되는 싱크 가사. 싱크 가사가 없으면 Genius 평문으로 자동 폴백한다.

가사 한 줄로 곡 찾기

기억나는 가사 한 구절로 곡을 검색할 수 있다. 가사 전문 검색(Genius)으로 곡을 특정한 뒤, 그 곡을 다시 Spotify에서 찾아 실제 재생 가능한 트랙으로 이어 준다.

갖춘 기능

내가 만든 기능을 정리했다. 모든 데이터는 로그인 후 자체 소켓 서버를 거쳐 MySQL과 연결돼 동작한다.

Meloji 홈 화면
홈 — 멜론 실시간/주간 등 차트를 미리 보여주고(좌측 라이브러리, 우측 재생목록, 하단 플레이어), 검색·상세로 이어진다.
차트 화면 통합 검색 결과 화면

차트(좌) — 멜론·빌보드·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를 잇는 소켓 서버. 화려한 화면보다, 여러 서비스를 하나처럼 움직이게 만드는 백엔드를 맡았다.