Fivefy 프로젝트/설계

Playback 도메인 설계 고도화 (행동 중심 enum을 상태 중심으로 재정의한 이유)

sudaruuu 2026. 4. 15. 12:29

문제 상황

Playback 기능을 구현하기 전, 처음에는 재생 상태를 아래와 같이 정의하였다.

public enum PlaybackStatus {
    START,
    PAUSE,
    COMPLETE,
    STOP,
    SKIP
}

 

또한 엔티티 역시 하나의 시각 필드(playedAt)만 두고,

재생 시간(playedDuration)을 단순 저장값처럼 관리하려고 하였다.

private PlaybackStatus status;
private Integer playedDuration;
private LocalDateTime playedAt;

 

처음에는 단순해 보여서 괜찮다고 생각했지만,

실제로 재생 / 일시정지 / 재개 / 건너뛰기 흐름을 기준으로 설계를 다시 보니 도메인 의미가 모호하다는 문제가 있었다.

 

특히 다음과 같은 지점이 애매했다.

  • START, PAUSE, SKIP 사용자 행동인지 상태인지 구분이 모호함
  • playedAt 하나만으로는 시작 / 재개 / 종료 시점을 구분할 수 없음
  • playedDuration을 언제, 어떤 기준으로 누적할지 정의되어 있지 않음
  • Playback을 한 번의 재생 흐름으로 볼지, 이벤트 로그로 볼지 기준이 없음
  • 재생이 어떤 playlist 맥락에서 발생했는지 알 수 없음

원인 분석

Playback 도메인은 단순 CRUD가 아니라, 상태 변화 흐름을 가지는 도메인이다.

사용자는 다음과 같은 흐름을 수행할 수 있다.

  • 재생 시작 → 일시정지 → 재개 → 건너뛰기

이 과정에서 기존 구조는 다음과 같은 문제를 가지고 있었다.

1. enum이 행동과 상태를 혼합하고 있었다

START, PAUSE, SKIP 같은 값은 사용자 행동처럼 보이지만, 엔티티의 status는 현재 상태를 표현해야 한다.

 

즉,

  • “버튼을 눌렀다” → 이벤트
  • “지금 어떤 상태인가” → 상태

이 둘이 분리되지 않아 설계가 모호해졌다.

2. 재생 시간 누적 기준이 없었다

playedDuration은 단순 저장값이 아니라 누적 값이다.

 

하지만 기존 설계에서는 다음과 같은 명확한 기준이 없었다.

  • 언제 시간을 더해야 하는지
  • 어떤 구간을 계산해야 하는지

3. 시간 필드가 하나로는 부족했다

playedAt 하나로 다음을 모두 표현하려 했다.

  • 최초 재생 시작 시각
  • 마지막 재생/재개 시각
  • 재생 종료 시각

이로 인해 시간 기준이 모호해졌다.

4. playlistId가 없어 재생 맥락이 사라졌다

Playback은 단순히 “어떤 트랙을 재생했는지”뿐 아니라,

어떤 플레이리스트에서 재생되었는지도 중요하다.

 

하지만 초기 설계에는 playlistId가 없어 다음과 같은 문제가 발생했다.

  • skip 시 다음 곡 판단 불가
  • 재생 흐름의 맥락 손실

해결 방향

현재 프로젝트에서는 Playback을 한 곡의 한 번 재생 흐름으로 정의하고, 다음 기준을 명확히 정리하였다.

1. 상태 enum을 상태 중심으로 재정의

기존

START, PAUSE, COMPLETE, STOP, SKIP

 

변경

PLAYING, PAUSED, STOPPED, SKIPPED, COMPLETED

 

이를 통해 status는 사용자 행동이 아닌,현재 상태를 표현하는 값으로 정리하였다.


stop vs skip 명확화

  • stop
    → 현재 곡 재생 종료 (흐름 종료)
  • skip
    → 현재 곡을 SKIPPED로 종료
    → 같은 playlist의 다음 곡 Playback 생성
    → 새로운 Playback이 PLAYING 상태로 시작

즉, skip은 “현재 곡 종료 + 다음 재생”까지 포함된 흐름이다.


2. 상태 전이 규칙 명시

Playback은 다음과 같은 상태 흐름을 가진다.

현재 상태 요청 다음 상태 설명
없음 start PLAYING 재생 시작 시 새 Playback 생성
PLAYING pause PAUSED 재생 중일 때만 일시정지 가능
PAUSED resume PLAYING 일시정지 상태에서만 재개 가능
PLAYING stop STOPPED 사용자가 재생을 중단한 경우
PAUSED stop STOPPED 일시정지 상태에서 종료 가능
PLAYING skip PLAYING 현재 곡을 SKIPPED로 종료 후 다음 곡 자동 재생
PAUSED skip PLAYING 일시정지 상태에서도 다음 곡으로 이동 후 자동 재생
PLAYING complete COMPLETED 곡이 끝까지 재생된 경우
STOPPED resume 불가 종료된 Playback은 재개하지 않음
COMPLETED resume 불가 종료된 Playback은 재개하지 않음


3. 시간 필드를 역할별로 분리

하나의 playedAt 필드로는 재생 흐름을 표현하기 어렵기 때문에 다음과 같이 시간 필드를 분리하였다.

private LocalDateTime startedAt;
private LocalDateTime lastPlayedAt;
private LocalDateTime endedAt;
  • startedAt : 최초 재생 시작 시각
  • lastPlayedAt : 마지막 재생/재개 시각
  • endedAt : 재생 종료 시각

이를 통해 재생 흐름의 각 시점을 명확하게 구분할 수 있게 되었다.


4. 재생 시간 누적 기준 명확화

playedDuration은 누적값이기 때문에 다음 시점에서만 재생 시간을 누적하도록 기준을 정의하였다.

  • pause
  •  stop
  •  skip
  • complete
누적 방식 : 현재 시간 - lastPlayedAt

 

또한 PAUSED 상태의 시간은 재생 시간에서 제외하여 실제 재생된 시간만 반영되도록 설계하였다.


5. sessionId 생성 주체 및 관리 기준 검토

sessionId를 통해 하나의 재생 흐름을 식별하도록 설계하였다.

 

sessionId는 단순 요청 단위가 아닌, 사용자의 연속된 재생 흐름을 하나로 묶기 위한 식별자이다.


현재 단계에서는 클라이언트가 sessionId를 생성하고,

서버는 이를 전달받아 저장하는 방식으로 관리하였다.
이를 통해 세션 관리에 대한 서버 측 복잡도를 줄일 수 있었다.


또한 다음과 같은 기준을 정의하였다.

  • pause / resume → 동일 세션 유지
  • skip → 같은 흐름으로 판단하여 세션 유지
  • complete → 재생 흐름 종료로 간주하여 세션 종료

이를 통해 여러 요청이 이어지더라도 하나의 재생 흐름 단위로 데이털르 해석할 수 있게 되었다.


6. playlistId를 Playback에 포함

Playback에 playlistId를 포함시켜, 재생이 어떤 맥락에서 발생했는지를 함께 관리하도록 변경하였다.

private Long playlistId;
private Long trackId;

 

이를 통해

  • skip 시 다음 곡 판단 가능
  • 재생 흐름의 연결성 유지

가 가능해졌다.


결과

이번 설계를 통해 Playback은 단순 재생 기록 저장이 아니라,
상태 전이와 재생 시간 누적 규칙을 함께 관리하는 도메인으로 정리할 수 있었다.

 

또한 현재는 단일 엔티티 기반으로 재생 흐름 관리에 집중하되,
추후에는 분석 목적의 이벤트 로그 구조로도 확장할 수 있는 방향을 확보하였다.


느낀 점

처음에는 enum 값 몇 개만 바꾸는 정도로 생각했지만, 실제로는 “Playback 한 건이 무엇을 의미하는가”부터 다시 정의해야 하는 문제였다. 이번 작업을 통해 도메인 설계에서는 단순히 컬럼을 저장하는 것보다 상태의 의미와 전이 규칙을 먼저 정의하는 것이 훨씬 중요하다는 점을 느꼈다. 결국 Playback은 단순 기록이 아니라 상태와 흐름을 함께 정의해야 하는 도메인이라는 점을 확인할 수 있었다.


위 내용을 반영하여 Playback 도메인 설계 블로그를 보완하였습니다.

[블로그 링크] 2026.04.08 - [CH6 fivefy 프로젝트/설계] - 데이터 흐름 중심으로 설계한 음악 서비스 아키텍처 (도메인·ERD·API)

 

데이터 흐름 중심으로 설계한 음악 서비스 아키텍처 (도메인·ERD·API)

Miro (전체 흐름)프로젝트 초기 단계에서 도메인 구조와 데이터 흐름을 시각적으로 정리하기 위해 Miro를 활용했다.Aggregate, 이벤트 흐름, 사용자 행동 기반 시나리오 등을 함께 정리하여단순 기능

sudaruuu.tistory.com