14 KiB
14 KiB
PRD: 콘텐츠 전체보기
1. Overview
콘텐츠 추천 탭의 일부 섹션에서 전체보기 진입을 제공하고, New&Hot은 신규 콘텐츠 전체보기 화면에서 GET /api/v2/contents API로 페이징 목록을 표시한다.
작성일: 2026-06-27
2. Problem
- 콘텐츠 추천 탭의 섹션 타이틀 우측 chevron이 현재 전체보기 이동 정책과 연결되어 있지 않다.
New&Hot은 기존 콘텐츠 탭 내부전체탭의 카테고리/정렬 조합으로 표현하지 않고, 별도 API 기반 전체보기 화면이 필요하다.- 그 외 콘텐츠 추천 섹션은 신규 화면을 만들지 않고 기존
콘텐츠 탭 - 전체의 특정 카테고리/정렬 상태로 이동해야 한다. - 동일한 오디오 카드, 태그, 페이징 목록 UI가 이미 V2 패키지 하위에 있으므로 신규 UI를 중복 작성하지 않도록 재사용 후보를 먼저 정리해야 한다.
3. Goals
- 콘텐츠 추천 탭에서 전체보기가 필요한 섹션 제목 우측에 chevron을 표시한다.
- 콘텐츠 추천 탭의
New&Hot섹션은 신규 콘텐츠 전체보기 화면으로 이동한다. - 콘텐츠 추천 탭의
오직 보이스온에서만!,새로 올라온 오디오,무료 오디오,포인트 오디오는 기존콘텐츠 탭 - 전체의 지정 상태로 이동한다. - 신규 콘텐츠 전체보기 화면은
type = NEW_AND_HOT_AUDIO로GET /api/v2/contents를 호출한다. - 신규 콘텐츠 전체보기 화면은 Figma node
482:15105의detail_ado_001구조를 기준으로 검은 배경, title bar, 2열 오디오 카드 그리드, 스크롤 페이징을 제공한다. - V2 패키지 하위 기존 위젯 중 재사용 가능한 후보를 문서에 기록한다.
4. Non-Goals
- 이번 PRD 작성 단계에서는 코드, 리소스, 레이아웃 파일을 구현하지 않는다.
- 콘텐츠 상세, 시리즈 상세, 결제, 보관함 기능은 변경하지 않는다.
- 레거시 화면 또는 레거시 API 파일을 직접 수정하지 않는다.
GET /api/v2/audio/contentsAPI 계약은 변경하지 않는다.- 신규 콘텐츠 전체보기 화면에 별도 정렬, 필터, 검색, pull-to-refresh, skeleton loading을 추가하지 않는다.
New&Hot외 섹션을 신규 전체보기 API로 조회하지 않는다.- Figma localhost asset URL을 앱 코드에 직접 의존하지 않는다.
5. Target Users
- 콘텐츠 추천 탭에서
New&Hot, 최신 오디오, 무료/포인트 오디오, 오리지널 콘텐츠를 섹션별로 더 보고 싶은 사용자. - V2 메인 홈/콘텐츠 화면과 신규 전체보기 화면을 구현/유지보수하는 Android 개발자.
6. User Stories
- 사용자는 콘텐츠 추천 탭의
New&Hot섹션 제목 우측 chevron을 눌러New&Hot전체 목록을 보고 싶다. - 사용자는 콘텐츠 추천 탭의
오직 보이스온에서만!을 누르면 콘텐츠 탭의전체내부에서 오리지널 카테고리가 선택된 화면으로 이동하길 기대한다. - 사용자는 콘텐츠 추천 탭의
새로 올라온 오디오를 누르면 콘텐츠 탭의전체내부에서 오디오 카테고리가 선택된 화면으로 이동하길 기대한다. - 사용자는 콘텐츠 추천 탭의
무료 오디오또는포인트 오디오를 누르면 콘텐츠 탭의전체내부에서 해당 카테고리와 인기순 정렬이 선택된 화면으로 이동하길 기대한다. - 사용자는 신규 전체보기 화면에서 콘텐츠를 2열 그리드로 탐색하고, 목록 하단에 도달하면 다음 페이지가 이어서 로드되길 기대한다.
7. Core Features
Feature A. 전체보기 섹션 chevron 표시
Requirements
- 전체보기 진입이 필요한 섹션 제목 우측에는
view_section_title.xml의iv_section_title_chevron을 표시한다. - 콘텐츠 추천 탭에서는 아래 섹션에 chevron을 표시한다.
오직 보이스온에서만!새로 올라온 오디오New&Hot무료 오디오포인트 오디오
- 콘텐츠 추천 탭의
댓글 많은 오디오,추천 오디오는 이번 요구사항에 전체보기 목적지가 없으므로 chevron을 표시하지 않는다. - 섹션 데이터가 비어 섹션 자체가 숨겨지는 경우 chevron도 함께 노출되지 않는다.
Edge Cases
- 빠르게 chevron을 중복 탭해도 동일 화면이 중복으로 여러 개 쌓이지 않도록 기존 navigation guard 패턴을 우선 따른다.
- 전체보기 목적지에 필요한 enum 또는 tab 상태가 유효하지 않으면 이동하지 않는다.
Feature B. 콘텐츠 추천 탭 전체보기 라우팅
Requirements
- 콘텐츠 추천 탭의 전체보기 이동 규칙은 아래와 같다.
| 섹션 | 이동 목적지 |
|---|---|
오직 보이스온에서만! |
콘텐츠 탭 - 전체 -> 오리지널 카테고리 선택 |
새로 올라온 오디오 |
콘텐츠 탭 - 전체 -> 오디오 카테고리 선택 |
New&Hot |
신규 콘텐츠 전체보기 화면 -> type = NEW_AND_HOT_AUDIO |
무료 오디오 |
콘텐츠 탭 - 전체 -> 무료 카테고리 선택 -> 인기순 정렬 |
포인트 오디오 |
콘텐츠 탭 - 전체 -> 포인트 카테고리 선택 -> 인기순 정렬 |
- 기존
콘텐츠 탭 - 전체로 이동하는 경우ContentMainFragment내부 탭은전체가 선택되어야 한다. 무료 오디오,포인트 오디오는ContentSort.POPULAR에 해당하는 정렬 상태로 진입한다.오직 보이스온에서만!은오리지널카테고리로 진입한다.
Edge Cases
- 이미 콘텐츠 탭에 있는 상태에서 전체보기 이동을 누르면 새 메인 화면을 중복 생성하지 않고 현재
ContentMainFragment의 내부 상태 전환을 우선 검토한다. - 홈 탭에서 콘텐츠 탭 내부
전체로 이동해야 하는 후속 요구가 생기면MainActivity/MainV2탭 전환 계약을 별도 계획에서 확인한다.
Feature C. 신규 콘텐츠 전체보기 화면
Requirements
- 신규 화면은 기존 로직 수정이 아닌 신규
Activity,ViewModel, API, Repository, DTO, adapter/helper로 구현한다면kr.co.vividnext.sodalive.v2패키지 하위에 작성한다. - 화면 title bar 제목은 진입 type에 따라 아래처럼 표시한다.
NEW_AND_HOT_AUDIO:New&Hot
- title bar는 검은 배경, 좌측 back chevron, 22sp bold 제목 구조를 따른다.
- 콘텐츠 목록은 Figma node
482:15105기준으로 2열 오디오 카드 그리드로 표시한다. - 카드에는 썸네일, 제목, 크리에이터 닉네임, 무료/포인트/FIRST/오리지널/성인 태그를 응답 값에 따라 표시한다.
- 카드 터치 시 기존 오디오 콘텐츠 상세 화면으로 이동한다.
- 목록은 첫 페이지 로딩, 빈 목록, 에러, 추가 페이지 로딩 상태를 구분한다.
hasNext = true이고 사용자가 목록 하단에 접근하면 다음page를 요청한다.
Figma Reference
- URL:
https://www.figma.com/design/HmN1yNdJ3EIpqknFL0Hkab/-공유용-보이스온-UI-UX-기획문서?node-id=482-15105&m=dev - node:
482:15105 - frame name:
detail_ado_001 - 확인된 구조:
- 화면 배경: black
- title bar height: 60
- title:
New&Hot - content start: title bar 하단 이후
- grid: 2열, 카드 폭 약 185, 카드 간격 약 4
- thumbnail: 정사각형, radius 14
- label: 제목 18sp bold, 크리에이터명 14sp medium, 한 줄 말줄임
- tags: FIRST, point, free, original audio, adult badge 조합
Edge Cases
contentId <= 0인 item은 상세 이동을 무시한다.coverImage가 null 또는 blank이면 기존 이미지 로딩 placeholder/null 처리 정책을 따른다.- 제목 또는 크리에이터명이 길면 한 줄 말줄임 처리한다.
- 첫 페이지 응답의
items가 비어 있으면 빈 목록 상태를 표시한다. - 추가 페이지 실패 시 기존 목록은 유지하고 재시도 가능한 상태를 제공한다.
Feature D. 신규 콘텐츠 전체보기 API
API Contract
GET /api/v2/contents
Query Parameters
page: Int = 0
size: Int = 20
type: ContentOverviewType = ContentOverviewType.NEW_AND_HOT_AUDIO
Response Data Class
data class ContentOverviewPageResponse(
val type: ContentOverviewType,
val items: List<ContentOverviewItemResponse>,
val page: Int,
val size: Int,
@SerializedName("hasNext")
val hasNext: Boolean
)
enum class ContentOverviewType {
NEW_AND_HOT_AUDIO
}
data class ContentOverviewItemResponse(
val contentId: Long,
val title: String,
val coverImage: String?,
val price: Int,
@SerializedName("isPointAvailable")
val isPointAvailable: Boolean,
val creatorNickname: String,
@SerializedName("isAdult")
val isAdult: Boolean,
@SerializedName("isFirstContent")
val isFirstContent: Boolean,
@SerializedName("isOriginalSeries")
val isOriginalSeries: Boolean
)
Requirements
- API 기본값은
page = 0,size = 20,type = NEW_AND_HOT_AUDIO로 취급한다. - query parameter key는 모두 소문자
page,size,type을 사용한다. - 앱에서는 진입 목적에 맞게
type을 명시적으로 전달한다. - 응답 DTO는 서버 계약을 변경하지 않는다.
- 서버 예시 class에 Jackson
@JsonProperty가 포함되어 있더라도 앱 구현에서는 기존 Gson 관례에 맞춰@SerializedName을 사용한다. - UI model에서는
price == 0이면 무료 태그,isPointAvailable == true이면 포인트 태그,isFirstContent == true이면 FIRST 태그,isOriginalSeries == true이면 오리지널 태그,isAdult == true이면 성인 배지로 매핑한다.
Edge Cases
- 응답
type이 요청type과 다르면 현재 요청 type 기준으로 화면 제목을 유지하고, 데이터 혼입 방지 정책은 구현 계획에서 확정한다. hasNext = false이면 다음 페이지를 요청하지 않는다.- 동일 type에서 추가 페이지 요청 중 중복 요청을 방지한다.
- 다른 type의 신규 전체보기 화면을 열 때는 이전 화면의 page/items 상태를 공유하지 않는다.
8. UX / UI Expectations
- 신규 전체보기 화면은 V2의 검은 배경과 콘텐츠 카드 스타일을 유지한다.
- 상단 title bar는 스크롤되지 않고, 목록만 세로 스크롤된다.
- 2열 그리드는 화면 폭에 맞춰 item width를 계산하되, Figma의 185px 카드와 4px 간격 비율을 Android 화면에서 자연스럽게 유지한다.
- 오디오 카드는 기존
AudioContentCardView의 태그 표현과 최대한 일치시킨다. - 성인 배지는 썸네일 우측 상단에 표시한다.
- 무료/포인트 태그는 썸네일 하단 좌측, FIRST/오리지널 태그는 썸네일 상단 좌측의 기존 패턴을 우선 따른다.
- 홈 추천 탭과 콘텐츠 추천 탭의 섹션 chevron은 기존
view_section_title.xml의ic_chevron_right를 사용한다.
재사용 가능한 V2 위젯/코드 후보
app/src/main/res/layout/view_section_title.xml- 섹션 제목과 우측 chevron 표시/숨김에 재사용 가능하다.
kr.co.vividnext.sodalive.v2.widget.AudioContentCardView- 신규 전체보기 2열 오디오 카드의 기본 카드 UI 후보이다.
kr.co.vividnext.sodalive.v2.widget.AudioContentCardSize- 기존 카드 크기 variant를 확인해 신규 2열 grid width 적용 가능성을 검토한다.
kr.co.vividnext.sodalive.v2.widget.AudioContentTag- 무료/포인트/FIRST/오리지널 태그 매핑에 재사용 가능하다.
kr.co.vividnext.sodalive.v2.main.content.ui.ContentAllAudioCardAdapter- 기존 콘텐츠
전체탭 3열 grid adapter이며, 동적 grid item width 적용 패턴을 참고할 수 있다.
- 기존 콘텐츠
kr.co.vividnext.sodalive.v2.main.content.ui.ContentAudioCardAdapter- 추천 탭의 가로 오디오 카드 바인딩 패턴을 참고할 수 있다.
kr.co.vividnext.sodalive.v2.main.content.ui.ContentNewAndHotAdapterNew&Hot섹션의 리스트형 표현에는 이미 사용 중이지만, 신규 전체보기 2열 grid에는 직접 재사용보다 item mapping/tag binding 참고 후보이다.
kr.co.vividnext.sodalive.v2.main.content.ContentAllTabViewModel- page/size/hasNext 기반 페이징 상태 관리 패턴 참고 후보이다.
kr.co.vividnext.sodalive.v2.main.content.data.MainContentAllTabApi- V2 콘텐츠 API의 Retrofit/Rx/
ApiResponse계약 참고 후보이다.
- V2 콘텐츠 API의 Retrofit/Rx/
9. Technical Constraints
- Android Gradle 단일
:app모듈에서 작업한다. - 모든 명령은 저장소 루트에서 실행한다.
- 신규 화면/하위 코드는
kr.co.vividnext.sodalive.v2패키지 하위에 작성한다. - 레거시 파일은 직접 수정하지 않고, 필요한 기존 화면은 Intent 또는 wrapper/adapter로 호출한다.
- API 흐름은 기존 관례인
Api -> Repository -> ViewModel -> Activity/Fragment를 따른다. - DI 추가가 필요하면
AppDI.kt의 Koin 구성 관례를 따른다. - 외부 라이브러리를 추가하지 않는다.
- 공개 API 스키마와 서버 enum 값을 임의 변경하지 않는다.
BuildConfig값이나 민감정보를 로그/Toast/크래시 메시지에 노출하지 않는다.
10. Metrics
- 콘텐츠 추천 탭 섹션별 chevron 클릭 수.
- 신규 콘텐츠 전체보기 화면 진입 수.
- 신규 콘텐츠 전체보기 화면의 다음 페이지 로드 성공/실패 수.
- 신규 콘텐츠 전체보기 화면에서 콘텐츠 상세로 이동한 클릭 수.
11. Open Questions
- 기존
ContentMainFragment상태를 외부에서 특정 내부 탭/카테고리/정렬로 열기 위한 public navigation contract가 충분한지 구현 계획에서 확인해야 한다.
2026-06-29 변경: 홈 처음부터 함께 성장! 전체보기 제거
- 홈 추천 탭의
처음부터 함께 성장!섹션 제거에 따라 홈에서ContentOverviewType.FIRST_AUDIO_CONTENT로 진입하는 경로를 제거한다. - 신규 콘텐츠 전체보기 화면의 현재 진입 type은 콘텐츠 추천 탭
New&Hot의NEW_AND_HOT_AUDIO만 유지한다.