Files
sodalive-android/docs/20260617_크리에이터_채널_라이브_탭/prd.md

18 KiB

PRD: 크리에이터 채널 라이브 탭

1. Overview

크리에이터 채널의 라이브 탭에서 현재 진행 중인 라이브와 라이브 다시듣기 목록을 표시하고, 정렬 및 스크롤 pagination을 제공한다.


2. Problem

  • 크리에이터 채널 상단/탭 구조는 이미 홈 탭 PRD에서 정의되었지만, 라이브 탭 하위 컨텐츠 조회와 표시 요구사항은 별도 정의가 필요하다.
  • 사용자는 크리에이터 채널에서 현재 진행 중인 라이브를 빠르게 확인하고, 과거 라이브 다시듣기 컨텐츠를 정렬해 탐색할 수 있어야 한다.
  • 라이브 다시듣기 item은 가격, 포인트 사용 가능 여부, 19금 콘텐츠, 소장중, 대여중 등 구매/접근 상태를 명확히 표시해야 한다.
  • 목록이 길어질 수 있으므로 CreatorChannelLiveTabResponse.hasNext == true일 때 다음 페이지를 자동 로딩해야 한다.
  • 정렬 label은 앱 다국어 정책에 맞춰 문자열 리소스로 관리해야 한다.
  • Sort-bar의 정렬 메뉴 표시 방식은 Figma 컨텍스트 메뉴와 BottomSheet 중 선택이 필요하며, 모바일 UX 흐름에 맞는 기준이 필요하다.

3. Goals

  • Figma 290:8945 기준으로 크리에이터 채널 라이브 탭 UI 요구사항을 정의한다.
  • Sort-bar에는 전체 라이브 다시듣기 수와 현재 정렬 label을 표시한다.
  • 정렬 기본값은 LATEST이며 UI label은 최신순이다.
  • 사용자가 정렬을 변경하면 선택한 ContentSort 값으로 GET /api/v2/creator-channels/{creatorId}/live를 다시 조회한다.
  • 정렬 메뉴는 Sort-bar 바로 아래에 표시되는 컨텍스트 메뉴 방식을 채택한다.
  • 현재 진행 중인 라이브가 있으면 Sort-bar 아래에 현재 라이브 카드로 표시한다.
  • 라이브 다시듣기 목록은 이미지, title, duration, 가격/포인트/무료/재생/소장중/대여중 상태, 19금 badge를 표시한다.
  • 응답의 hasNexttrue이면 현재 page + 1 페이지를 추가 로딩한다.
  • 정렬 label과 상태 문구는 다국어 문자열 리소스로 관리한다.
  • 로그인 사용자가 해당 크리에이터 본인이면 라이브 탭 하단에 고정된 라이브 시작하기 버튼을 표시한다.

4. Non-Goals

  • 크리에이터 채널 상단 header, title bar, tab-bar 구조 자체를 재설계하지 않는다.
  • , 오디오, 시리즈, 커뮤니티, 팬Talk, 후원 탭의 상세 구현은 이번 범위에서 제외한다.
  • 라이브룸 진입, 오디오 상세/결제/대여/소장 플로우 내부 동작 변경은 이번 범위에서 제외한다.
  • API schema를 임의 변경하거나 서버 응답 필드명을 클라이언트에서 새로 정의하지 않는다.
  • 정렬 옵션 외 별도 필터, 검색, pull-to-refresh, skeleton/shimmer는 이번 범위에서 제외한다.
  • BottomSheet 방식의 정렬 메뉴는 이번 범위에서 채택하지 않는다.

5. Target Users

  • 크리에이터 채널에서 현재 라이브와 라이브 다시듣기를 탐색하는 앱 사용자.
  • 구매 가능/보유/대여 상태를 확인한 뒤 라이브 다시듣기를 재생하거나 상세로 이동하려는 앱 사용자.
  • 본인 크리에이터 채널의 라이브 탭에서 라이브를 시작하려는 크리에이터.
  • kr.co.vividnext.sodalive.v2 하위 크리에이터 채널 탭을 구현/유지보수하는 Android 개발자.

6. User Stories

  • 사용자는 크리에이터 채널의 라이브 탭에서 현재 진행 중인 라이브를 바로 확인하고 싶다.
  • 사용자는 라이브 다시듣기 총 개수와 정렬 기준을 확인하고 싶다.
  • 사용자는 최신순, 인기순, 소장순, 가격 높은 순, 가격 낮은 순으로 다시듣기 목록을 정렬하고 싶다.
  • 사용자는 19금 콘텐츠, 포인트 사용 가능 콘텐츠, 무료 콘텐츠, 소장중/대여중 콘텐츠를 목록에서 구분하고 싶다.
  • 사용자는 목록 하단까지 스크롤하면 다음 페이지가 자연스럽게 이어서 로딩되길 기대한다.
  • 크리에이터 본인은 본인 채널의 라이브 탭에서 하단 고정 버튼으로 라이브 시작 화면에 진입하고 싶다.

7. Core Features

Creator Channel Live Tab API

라이브 탭 진입 및 정렬/추가 로딩 시 크리에이터별 라이브 탭 데이터를 조회한다.

Requirements

  • API endpoint는 GET /api/v2/creator-channels/{creatorId}/live이다.
  • Query parameters는 page, size, sort를 사용한다.
  • sortContentSort enum 값을 그대로 전달한다.
  • 최초 조회의 정렬 기본값은 ContentSort.LATEST이다.
  • 최초 조회의 page 시작 값은 0이다.
  • 최초 조회 실패, 정렬 변경 실패, 다음 페이지 로딩 실패는 기존 프로젝트의 에러 표시/재시도 패턴을 구현 계획 단계에서 확인해 따른다.
  • hasNext == true일 때 다음 페이지 요청은 현재 응답의 page + 1 값을 사용한다.
  • 중복 pagination 요청이 발생하지 않도록 loading 중 추가 요청을 막아야 한다.
  • 정렬 변경 시 기존 목록과 page 상태를 초기화하고 첫 페이지부터 다시 조회한다.

Response Contract

data class CreatorChannelLiveTabResponse(
    val liveReplayContentCount: Int,
    val currentLive: CreatorChannelLiveResponse?,
    val liveReplayContents: List<CreatorChannelAudioContentResponse>,
    val sort: ContentSort,
    val page: Int,
    val size: Int,
    val hasNext: Boolean
)

data class CreatorChannelAudioContentResponse(
    val audioContentId: Long,
    val title: String,
    val duration: String?,
    val imageUrl: String?,
    val price: Int,
    val isAdult: Boolean,
    val isPointAvailable: Boolean,
    val isFirstContent: Boolean,
    val seriesName: String?,
    val isOriginalSeries: Boolean?,
    val isOwned: Boolean,
    val isRented: Boolean
)

enum class ContentSort {
    LATEST,
    POPULAR,
    OWNED,
    PRICE_HIGH,
    PRICE_LOW
}

Edge Cases

  • currentLive == null이면 현재 라이브 카드 영역을 표시하지 않고 라이브 다시듣기 목록이 Sort-bar 아래에 이어진다.
  • liveReplayContents가 비어 있고 currentLive == null이면 기존 앱 패턴에 맞는 empty 상태를 표시한다.
  • duration == null이면 duration 영역은 빈 문자열 노출 대신 숨김 또는 기존 duration placeholder 정책을 따른다.
  • imageUrl == null 또는 이미지 로딩 실패 시 기존 이미지 placeholder 정책을 따른다.
  • 다음 페이지 응답의 liveReplayContents가 비어 있어도 hasNext 값 기준으로 이후 로딩 가능 여부를 갱신한다.

Sort Bar and Sort Menu

Sort-bar는 라이브 다시듣기 총 개수와 현재 정렬 상태를 표시하고, 정렬 메뉴를 연다.

Requirements

  • Sort-bar Figma 기준 노드는 290:8949이다.
  • 좌측에는 전체liveReplayContentCount를 표시한다.
  • 우측에는 현재 정렬 label과 정렬 icon을 표시한다.
  • 정렬 icon 리소스는 ic_new_sort를 사용한다.
  • 정렬 label은 ContentSort에 따라 다국어 문자열 리소스로 표시한다.
  • 정렬 기본값은 LATEST이며 label은 한국어 기준 최신순이다.
  • 정렬 옵션은 아래 순서로 표시한다.
ContentSort 한국어 label
LATEST 최신순
POPULAR 인기순
OWNED 소장순
PRICE_HIGH 높은 가격순
PRICE_LOW 낮은 가격순
  • Figma 290:9041의 컨텍스트 메뉴를 정렬 메뉴 방식으로 채택한다.
  • Sort-bar 정렬 영역을 터치하면 해당 UI 아래에 컨텍스트 메뉴를 표시한다.
  • 현재 선택된 정렬 옵션은 focused 배경으로 표시한다.
  • 메뉴 외부 영역 터치 또는 정렬 옵션 선택 시 메뉴를 닫는다.
  • 선택 중인 정렬 옵션을 다시 선택하면 API 재호출 없이 메뉴만 닫는다.

UX Decision

  • 이번 화면의 정렬 옵션은 5개이며, 사용자가 Sort-bar의 현재 정렬 위치를 기준으로 빠르게 바꾸는 보조 액션이다.
  • 2026년 모바일 UX 기준으로도 전체 화면 흐름을 끊는 BottomSheet보다, 앵커 위치를 유지하는 작은 컨텍스트 메뉴가 현재 요구에 적합하다.
  • 따라서 BottomSheet는 옵션 수가 증가하거나 긴 설명/복수 선택/필터 조합이 필요한 후속 범위에서 재검토한다.

Edge Cases

  • 작은 화면에서 메뉴가 화면 우측 또는 하단을 벗어나지 않도록 위치를 보정한다.
  • 스크롤 중 메뉴가 열린 상태에서 화면이 이동하면 메뉴 위치가 Sort-bar와 어긋나지 않도록 닫거나 재배치한다.
  • 다국어 label 길이가 길어져도 Sort-bar text와 icon이 겹치지 않아야 한다.

Current Live Card

현재 진행 중인 라이브가 있으면 Sort-bar 아래에 라이브 카드로 표시한다.

Requirements

  • 현재 라이브 Figma 기준 노드는 290:8950이다.
  • currentLive != null일 때만 표시한다.
  • 카드에는 LIVE badge, 라이브 경과/시간 텍스트, 라이브 제목, 가격을 표시한다.
  • 가격 표시는 기존 can/point/cash icon 및 가격 표시 정책을 구현 계획 단계에서 확인해 재사용한다.
  • 카드 터치 시 라이브룸 또는 라이브 상세로 이동하는 기존 크리에이터 채널 홈 탭 정책이 있으면 동일하게 따른다.

Edge Cases

  • 라이브 제목이 긴 경우 한 줄 말줄임 처리한다.
  • 가격이 0인 경우 무료 표시 정책을 기존 라이브/오디오 카드와 맞춘다.
  • currentLive의 세부 DTO는 크리에이터 채널 홈 탭에서 이미 사용하는 CreatorChannelLiveResponse와 호환되는지 구현 계획 단계에서 확인한다.

Live Replay List

라이브 다시듣기 목록은 Figma item variant를 기준으로 오디오 컨텐츠 item을 표시한다.

Requirements

  • 라이브 다시듣기 item Figma 기준 노드는 290:8954, 290:8956 및 전체 화면 내 290:8952~290:8957이다.
  • 각 item은 imageUrl, title, duration을 표시한다.
  • isAdult == true이면 이미지 우상단에 19금 badge를 표시한다.
  • 19금 badge의 방패 이미지 리소스는 ic_new_shield_small을 사용한다.
  • isPointAvailable == true이면 이미지 하단 tag 영역에 point tag를 표시한다.
  • price == 0이면 무료 tag와 우측 재생 버튼을 표시한다.
  • price > 0이고 소장/대여 상태가 아니면 가격을 표시한다.
  • isOwned == true이면 구매/가격 CTA 대신 우측 재생 버튼과 소장중 상태를 표시한다.
  • isRented == true이면 우측 재생 버튼과 대여중 상태를 표시한다.
  • isOwned == trueisRented == true가 동시에 내려오면 소장중을 우선 표시한다.
  • 무료/소장중/대여중 콘텐츠의 우측 재생 버튼 icon 리소스는 ic_new_player_play를 사용한다.
  • seriesName은 라이브 다시듣기 item에 표시하지 않는다.
  • isFirstContentisOriginalSeries는 기존 오디오 item 정책과 동일하게 매핑한다.
  • item 터치 시 오디오 컨텐츠 상세 또는 재생 진입은 기존 오디오 컨텐츠 item 정책을 재사용한다.

Edge Cases

  • isOwned == trueisRented == true가 동시에 내려오는 경우 소장중을 대여중보다 상위 상태로 본다.
  • isPointAvailable == true이면서 isAdult == true인 경우 point tag와 19금 badge가 동시에 표시되어야 한다.
  • title이 긴 경우 Figma처럼 최대 2줄까지 표시하고 이후 말줄임 처리한다.
  • duration이 긴 경우 한 줄 말줄임 처리한다.

Owner Live Start CTA

로그인 사용자가 해당 크리에이터 본인인 경우 라이브 탭 하단에 고정된 라이브 시작 버튼을 표시한다.

Requirements

  • 본인 채널 라이브 탭 Figma 기준 노드는 665:19359이다.
  • 하단 CTA Figma 기준 노드는 665:19371이다.
  • 로그인 사용자가 현재 크리에이터 채널의 본인이면 하단 고정 CTA 영역을 표시한다.
  • 로그인 사용자가 현재 크리에이터 채널의 본인이 아니면 하단 고정 CTA 영역을 표시하지 않는다.
  • CTA 영역은 화면 하단에 고정하고, 목록 스크롤과 함께 움직이지 않는다.
  • CTA 영역 배경은 black이며, 내부 버튼은 Figma 기준 cyan capsule 형태를 따른다.
  • 버튼 label은 라이브 시작하기이며 다국어 문자열 리소스로 관리한다.
  • 버튼 icon은 ic_new_create_live drawable 리소스를 사용한다.
  • 버튼 터치 시 기존 라이브 시작/생성 진입 플로우로 이동한다.
  • CTA가 표시되는 경우 목록 마지막 item이 CTA에 가려지지 않도록 하단 padding 또는 inset을 추가한다.
  • Android gesture navigation, soft navigation bar, display cutout 환경에서 CTA가 system navigation 영역과 겹치지 않도록 bottom inset을 반영한다.

Edge Cases

  • 본인 여부 판정 데이터가 아직 로딩 중이면 CTA를 먼저 노출하지 않는다.
  • 본인 여부 판정 실패 또는 API 실패 상태에서는 기존 에러 상태 정책을 따르고 CTA를 임의로 노출하지 않는다.
  • 라이브 시작 플로우 진입 중 중복 터치를 막는다.

Pagination

라이브 다시듣기 목록은 스크롤 하단 접근 시 다음 페이지를 로딩한다.

Requirements

  • CreatorChannelLiveTabResponse.hasNext == true일 때만 다음 페이지를 요청한다.
  • 다음 페이지는 마지막 성공 응답의 page + 1로 요청한다.
  • 다음 페이지 로딩 중에는 추가 page 요청을 중복으로 보내지 않는다.
  • 다음 페이지 성공 시 기존 liveReplayContents 뒤에 append한다.
  • 다음 페이지 실패 시 기존 목록은 유지하고, 기존 프로젝트 패턴에 맞는 retry UI 또는 toast/snackbar 정책을 따른다.
  • 정렬 변경 시 pagination 상태를 초기화한다.

Edge Cases

  • 빠른 스크롤로 load-more trigger가 반복 발생해도 page가 중복 append되지 않아야 한다.
  • Fragment/View 재생성 후 현재 목록, 정렬, page 상태는 ViewModel 상태 보존 정책에 따라 유지되어야 한다.

8. UX / UI Expectations

  • 전체 배경은 Figma 기준 black이다.
  • Sort-bar 높이, 좌우 여백, 텍스트 스타일은 Figma 290:8949를 따른다.
  • 현재 라이브 카드는 cyan 계열 gradient capsule 형태를 유지한다.
  • 라이브 다시듣기 item은 88dp 정사각 썸네일, title 영역, 우측 CTA/status 영역의 가로형 목록 구조를 따른다.
  • 컨텍스트 메뉴는 dark surface, 14dp radius, border, focused item 배경 차이를 유지한다.
  • 정렬 메뉴는 BottomSheet처럼 화면 하단에서 올라오지 않고 Sort-bar 정렬 영역 아래에 떠야 한다.
  • 본인 채널의 라이브 시작하기 버튼은 Figma 665:19359처럼 하단 고정 CTA로 표시하고, 목록 컨텐츠 위를 덮지 않도록 스크롤 하단 여백을 확보한다.
  • 다국어 문자열 길이 증가 시 title, 정렬 label, 상태 문구가 겹치지 않도록 말줄임 또는 최소 폭 정책을 적용한다.

9. Technical Constraints

  • Android Gradle 단일 :app 모듈에서 구현한다.
  • 신규 Fragment, ViewModel, adapter, DTO, Repository 등은 kr.co.vividnext.sodalive.v2 하위에 작성한다.
  • 크리에이터 채널 홈 탭에서 이미 정의된 공통 모델/컴포넌트가 있으면 우선 재사용한다.
  • API DTO는 서버 계약과 동일한 필드명을 사용한다.
  • ContentSort는 API 전송 값과 UI label을 분리하고, UI label은 문자열 리소스로 관리한다.
  • 구현 시 ic_new_shield_small, ic_new_player_play, ic_new_sort 리소스 존재 여부를 먼저 확인하고 기존 drawable 리소스를 재사용한다.
  • 본인 채널 판정은 크리에이터 채널 홈 탭 또는 공통 채널 컨테이너에서 사용하는 기존 본인 페이지 판정 값을 우선 재사용한다.
  • BuildConfig 값이나 토큰/URL 같은 민감값은 로그, Toast, crash message에 노출하지 않는다.
  • 구현 전 docs/20260617_크리에이터_채널_라이브_탭/plan-task.md를 작성한 뒤 해당 계획에 따라 최소 구현한다.

10. Metrics

  • 라이브 탭 최초 진입 시 첫 페이지 API가 1회 호출된다.
  • 정렬 변경 시 선택한 ContentSort 값으로 첫 페이지 API가 1회 재호출된다.
  • hasNext == true 상태에서 목록 하단 접근 시 page + 1 API가 호출된다.
  • hasNext == false 이후에는 추가 page API가 호출되지 않는다.
  • 라이브 다시듣기 item의 가격/포인트/19금/소장중/대여중 표시가 DTO 값과 일치한다.
  • 본인 크리에이터 채널에서만 하단 라이브 시작하기 CTA가 표시된다.
  • 타인 크리에이터 채널에서는 하단 라이브 시작하기 CTA가 표시되지 않는다.

11. Open Questions

  • CreatorChannelLiveResponse의 정확한 필드 계약은 홈 탭 DTO와 동일한지 구현 계획 단계에서 확인한다.
  • 라이브 시작하기 버튼 터치 시 진입할 기존 라이브 시작 플로우의 Activity/Fragment는 구현 계획 단계에서 기존 코드 기준으로 확인한다.

12. Confirmed Decisions

  • page query parameter의 시작 값은 0이다.
  • 다음 페이지는 응답의 page + 1을 사용한다.
  • isOwned == trueisRented == true가 동시에 내려오는 경우 소장중을 우선 표시한다.
  • seriesName은 라이브 다시듣기 item에 표시하지 않는다.
  • isFirstContent, isOriginalSeries는 기존 오디오 item 정책과 동일하게 매핑한다.
  • 라이브 시작하기 버튼 icon drawable 리소스명은 ic_new_create_live이다.

References

  • 전체 Figma: 290:8945
  • Sort-bar Figma: 290:8949
  • 현재 진행 중인 라이브 Figma: 290:8950
  • 라이브 다시듣기 item Figma: 290:8954, 290:8956
  • 정렬 컨텍스트 메뉴 Figma: 290:9041
  • 본인 채널 라이브 탭 및 하단 CTA Figma: 665:19359, 665:19371
  • 기존 크리에이터 채널 홈 탭 PRD: docs/20260611_크리에이터_채널_홈_탭/prd.md
  • PRD template: docs/prd/sample-prd.md
  • 문서 규칙: docs/agent-guides/work-plan-docs.md