프로젝트/디깅 - 종합음악플랫폼

[디깅 뮤직 25편] UI, UX, DB개선

하러어어러 2025. 6. 30. 20:20

1. 메인 화면 개선

기존의 메인화면

 

바뀐 메인화면

 

공지사항을 상단에 추가하고,
네비게이션은 드롭다운 없이 바로 페이지에 접근할 수 있도록 단순화했다.

리뷰와 가사 콘텐츠는 큐레이션된 형태로 메인에 노출되며,
가로 스크롤을 도입해 탐색성을 높였다.

무엇을 메인에 보여줄지에 대해 고민이 많았는데,
특히 위키 기능을 중심에 두고,
읽을 거리 → 클릭 → 탐색 흐름이 자연스럽게 이어지도록 설계했다.

또한, 기존에 차트 페이지에서만 가능했던 날짜 선택 기능을 메인으로 옮기고,
클릭 시 반응형으로 로딩되도록 최적화해 사용자 부담도 줄였다.

 

2. 커뮤니티 개선

카테고리 세분화

제한적인 장르 기반으로 구성돼 있었고,
이에 대해 장르 구분이 모호하다, 더 다양한 씬을 다뤄야 한다는 피드백이 많았다.

 

이번 업데이트에서는 기존 카테고리를 전면 개편해,
힙합, 락, 인디, K-POP, J-POP, 재즈, 팝, 일렉트로닉, 클래식 
다양한 음악 씬 중심으로 재구성했고,
게시글 작성 시 다중 선택도 가능하게 했다.

또한 “장르”라는 용어 대신, 보다 유연한 음악 문화 개념인 “씬”이라는 표현을 사이트 전반에서 사용하기로 했다.

 

 

 

3. 헤더 개선

 

기존에는 커뮤니티가 드롭다운 형식으로 숨겨져 있어,
원하는 장르에 접근하려면 선택 과정을 거쳐야 했다.

이번 업데이트에서는 커뮤니티를 탭 페이지로 분리하고,
장르는 그 안에서 선택하도록 구조를 변경했다.
또한 위키와 리뷰도 헤더에서 바로 이동 가능하게 바뀌어
전체적인 탐색 흐름이 더 직관적이고 빠르게 개선되었다.

 

4. 위키 편집 UX 개선, DB개선

처음 설계한 구조는 가사 한 줄(line)을 하나의 엔티티로 보고,
그 객체에 번역과 해설(주석)을 속성으로 붙이는 형태였다.

이 구조는 아주 직관적이긴 하지만, 몇 가지 치명적인 단점이 있었다.

 

🔸 해설이 여러 줄에 걸칠 수 없다

예를 들어, 반복되는 후렴구나 훅처럼 여러 줄에 걸친 의미 단위에 해설을 달고 싶을 때,
한 줄씩 해설을 복사해서 붙이는 노가다 방식밖에 없었다.

 

🔸 반복 가사에 같은 번역을 또 입력해야 한다

"Hook"이나 "Chorus"처럼 같은 가사가 반복될 경우에도
각 줄마다 개별 번역을 입력해야 했고, 변경이 생기면 모든 줄을 일일이 수정해야 했다.

 

🔸 실제로는 의미 없는 줄 객체들이 대량 생성

Bubble에서는 가사를 로컬에 저장하기 위해 각 줄을 객체로 만들어야 했는데,
대부분은 단순히 API에서 받아온 내용을 저장하는 것이어서
수정 가능성도 없고, 추가 정보도 없는 "죽은 데이터"가 DB에 잔뜩 쌓이게 됐다.

 

🔸 서버 자원 사용량

줄마다 객체를 생성하거나 수정하려면 Bubble의 schedule API on a list 기능을 사용해야 했는데,
이건 Bubble에서 가장 서버 사용량이 큰 기능 중 하나다.
가사 한 곡에 보통 30~60줄이 있고, 여기에 해설/번역을 추가하면
곡 하나의 가사들 객체 생성만으로도 서버비가 눈에 띄게 올라가는 수준이었다.

 


🔄 새 구조 설계의 핵심 아이디어

1. 가사 원문은 저장하지 않는다

  • 원문 가사는 Spotify API 등에서 실시간으로 불러오고,
  • API에서 가사를 불러올 수 없을 경우에만 예외적으로 저장하도록 설계했다.
  • 저장할 때에도 여러줄의 텍스트 속성 하나로 전체 가사를 저장하도록 설계했다.
  • 이를 통해 DB가 쓸데없는 가사 객체로 오염되는 것을 방지.

2. 가사 단위가 아닌 트랙 단위 중심으로 구조 재편

  • 각 트랙(곡)은 고유한 Spotify Track ID를 갖는다.
  • 가사 데이터는 track_lyrics라는 객체로 하나로 관리되며,
  • 여러 트랙이 동일한 가사를 공유할 수 있게 track_lyrics ↔️ track (list) 관계로 설계했다.
  • (이건 은근 짜증나는 부분인데, 같은 곡인데 싱글 선공개 앨범인지, 정규인지에 따라 객체가 다르다.)

3. 번역은 객체 리스트 ❌, 단일 텍스트 필드로

  • 번역은 전체 가사를 줄바꿈으로 구분한 단일 텍스트로 저장.
  • 표시할 때는 클라이언트에서 split해 각 줄로 나누고 배치.
  • 이 구조의 장점:
    • 객체 수를 줄여서 저장 공간 절약
    • 수정 시에도 단일 텍스트만 바꾸면 됨 → 연산량/시간 압도적 감소

✅ 성능 개선 수치 대략 추산:

  • Bubble에서 객체 생성은 속성 수정보다 약 2~4배 더 느림
  • 가사 한 곡 = 평균 30~60줄
  • → 기존 구조 대비 연산량 60배 ~ 240배 이상 개선
  • 실제로 서버 로드가 눈에 띄게 줄었고, 로딩 시간도 개선됨

 

4. 해설은 여러 줄 대상 가능하게 설계

  • Annotation이라는 독립 객체를 만들고, 해당 객체는 여러 줄(line_indexes)을 참조할 수 있게 설정.
  • 반복되는 훅이나 후렴에도 해설을 하나만 달아두면 됨.
  • 해설 본문은 Annotation Revision을 통해 수정/이력 관리 → 위키 스타일

 

5. 백엔드 중심 설계로 전환

  • 데이터 처리의 대부분을 백엔드 워크플로우에서 수행하도록 변경
  • 사용자 인터페이스가 느려지는 문제 해결

 


기존 데이터 전면 정리 — 25,000줄의 마이그레이션

구조를 바꾼다고 해서 끝나는 게 아니다.
기존 데이터도 새 구조에 맞게 전부 옮겨야 했다.

 2만 5천 개가 넘는 가사 줄(line) 객체가 Bubble DB에 저장돼 있었다.
곡 수로는 약 1,800곡 분량이었다.

설계 자체는 크게 어렵지 않았다.

동시에 돌릴 수 있는 워크플로우 개수에 제한이 있었나 그래서 보통 좀 널널하게 시간 간격을 두는 편이다.

곡당 60초, 가사 당 2초 정도로 두고 돌리니까 25,000개의 객체를 처리하는 데 약 10시간이 소요된다고 알려줬다.

그래서 마이그레이션 워크플로우를 돌려두고, 그냥 잠들었다.

 

워크플로우가 멈추지 않고 잘 돌아갔고,
아침에 확인했을 때 모든 데이터가 새로운 구조로 깔끔하게 변환돼 있었다.
Bubble 상에서 큰 오류 없이 대량 데이터를 안정적으로 처리할 수 있었던 점도 꽤 인상 깊었다.