34 KiB
34 KiB
PRD: 메인 홈 추천 UI와 API 연동
1. Overview
Figma home_001 화면(24:5514)을 기준으로 메인 홈 추천 영역을 구성하고, 홈 추천 API 응답을 기존 v2 widget 중심으로 바인딩한다.
2. Problem
- 메인 홈 추천 화면은 라이브, 배너, 최근 활동, 신규 데뷔, 첫 오디오 콘텐츠, AI 캐릭터, 장르별 크리에이터, 응원 크리에이터, 인기 커뮤니티 등 여러 데이터 섹션을 한 화면에 표시해야 한다.
- Figma에는 이미
live,banner,section-title,contents,chat-thumbnail,profile,feed등 재사용 가능한 형태가 다수 포함되어 있으므로, 기존에 생성된 widget을 최대한 활용해야 한다. HomeActiveCreatorItem.activityType은 백엔드 enum code 그대로 표시하면 사용자에게 부자연스러우므로LIVE,LIVE_REPLAY,AUDIO,COMMUNITY를 다국어 처리 가능한 표시 문자열로 변환해야 한다.- 사업자 정보 섹션은 별도 외부 라이브러리 없이 최대 3줄 말줄임과 더보기/접기 토글을 제공해야 한다.
- Figma에 포함된 일부 섹션은 이번 범위에서 제외되어야 하므로 구현 범위를 명확히 분리해야 한다.
3. Goals
- 홈 추천 API 응답
HomeRecommendationResponse를 받아 Figma24:5514의 홈 추천 섹션 순서에 맞게 표시한다. - 기존
HomeApi에 메서드를 추가하지 않고, 메인 홈 추천 전용 신규 API 인터페이스/Repository 흐름을 만든다. - 추천 탭이 선택된
HomeMainFragment에 메인 홈 추천 UI를 구현한다. - Figma에서 기존 widget으로 대응 가능한 항목은 기존 v2 widget을 우선 재사용한다.
- 재사용이 어려운 영역만 최소 범위 신규 UI 또는 adapter item으로 정의한다.
추천 필모그래피,또 다른 모습섹션은 만들지 않는다.- 최하단 사업자 정보 섹션은 표시하되, 기본 최대 3줄 말줄임과
더보기/접기토글을 제공한다. HomeActiveCreatorItem.activityType은 백엔드 code를 앱 내부 enum 또는 mapper로 변환하고, 표시 문구는 string resource 기반 다국어 처리를 적용한다.- API DTO, 화면 상태, empty/error/loading 정책, click routing은 구현 계획에서 검증 가능하도록 정리한다.
4. Non-Goals
- 이번 PRD 작성 단계에서는 코드, 리소스, 레이아웃 파일을 구현하지 않는다.
추천 필모그래피섹션은 구현하지 않는다.또 다른 모습섹션은 구현하지 않는다.- 추천 알고리즘, API 응답 정렬 기준, 서버 필드명은 변경하지 않는다.
- 외부 라이브러리를 추가하지 않는다.
- Compose 화면으로 전환하지 않는다.
ViewPager또는 swipe 기반 tab 전환은 추가하지 않는다.- 이번 범위에서
랭킹,팔로잉용 별도 Fragment 또는 숨김 View를 미리 만들지 않는다. - 기존 레거시 홈 화면 전체 리팩터링은 포함하지 않는다.
- Figma에 없는 skeleton loading, shimmer, 임의 애니메이션, 추가 badge는 만들지 않는다.
5. Target Users
- 메인 홈에서 추천 라이브, 크리에이터, 오디오 콘텐츠, AI 캐릭터, 커뮤니티를 탐색하는 앱 사용자.
- 기존 XML Views와 v2 widget을 재사용해 홈 추천 화면을 구현/유지보수하는 Android 개발자.
6. User Stories
- 사용자는 홈에서 현재 라이브 중인 크리에이터와 추천 콘텐츠를 빠르게 탐색하고 싶다.
- 사용자는 배너를 스와이프하거나 터치해 관련 이벤트, 크리에이터, 시리즈, 외부 링크 또는 앱 내부 딥링크로 이동하고 싶다.
- 사용자는 최근 활동한 크리에이터의 활동 유형을
라이브,오디오,커뮤니티처럼 이해 가능한 문구로 보고 싶다. - 사용자는 인기 커뮤니티 글을 읽다가 사업자 정보가 길어도 홈 화면 탐색이 과도하게 방해받지 않기를 기대한다.
- 개발자는 기존 v2 widget을 최대한 재사용해 화면별 UI 중복과 스타일 차이를 줄이고 싶다.
7. Core Features
홈 추천 API 연동
메인 홈 추천 화면은 다음 응답을 단일 API 결과로 받아 섹션별 UI 모델로 변환한다.
Response Contract
data class HomeRecommendationResponse(
val lives: List<HomeLiveItem>,
val banners: List<HomeBannerItem>,
val recentlyActiveCreators: List<HomeActiveCreatorItem>,
val recentDebutCreators: List<HomeCreatorItem>,
val firstAudioContents: List<HomeFirstAudioContentItem>,
val aiCharacters: List<HomeAiCharacterItem>,
val genreCreators: List<HomeGenreCreatorGroupItem>,
val cheerCreators: List<HomeCreatorItem>,
val popularCommunityPosts: List<HomePopularCommunityPostItem>
)
Requirements
- API endpoint는
GET /api/v2/home/recommendations를 사용한다. - 기존
HomeApi에 추가하지 않고 홈 추천 전용 신규 API 인터페이스를 만든다. - Repository/ViewModel 위치는 구현 계획에서
HomeMainFragment와 기존 v2 홈 구조를 확인한 뒤 결정한다. - 응답 DTO는 서버 필드명을 임의 변경하지 않고, 필요한 경우
@SerializedName만 추가한다. - 화면 UI는 DTO를 직접 노출하지 않고 섹션별 UI model 또는 adapter item으로 변환한다.
- 각 리스트가 비어 있으면 해당 섹션은 숨기는 것을 기본 정책으로 한다.
- 전체 API 실패 시 기존 홈 화면의 error/toast/loading 패턴을 따른다.
- 이미지 URL이 null이면 호출부의 기존 placeholder 정책을 따른다.
Changed Item Contracts
data class HomeFirstAudioContentItem(
val contentId: Long,
val creatorId: Long,
val creatorNickname: String,
val creatorProfileImage: String,
val title: String,
val price: Int,
val coverImage: String?,
val isPointAvailable: Boolean
)
data class HomeAiCharacterItem(
val characterId: Long,
val name: String,
val description: String,
val profileImage: String?,
val totalChatCount: Long,
val originalWorkTitle: String?
)
data class HomePopularCommunityPostItem(
val postId: Long,
val creatorId: Long,
val creatorNickname: String,
val creatorProfileImage: String?,
val imageUrl: String?,
val audioUrl: String?,
val content: String,
val price: Int,
val createdAt: String,
val likeCount: Long,
val commentCount: Long,
val existOrdered: Boolean
)
Changed Item Requirements
HomeFirstAudioContentItem.price는 첫 오디오 콘텐츠의 무료 여부 표시 정책에 사용한다.HomeFirstAudioContentItem.isPointAvailable은 첫 오디오 콘텐츠 카드 바인딩 시 포인트 사용 가능 표시 정책에 반영한다.HomeAiCharacterItem.profileImage는CharacterChatThumbnailView의 실제 이미지 URL로 사용한다.HomeAiCharacterItem.originalWorkTitle이 null이면 기존CharacterChatThumbnailView의 원작 없음 표시 정책에 맞춰 원작 영역을 유지하거나 숨기는 방식을 구현 계획에서 확정한다.HomePopularCommunityPostItem.postId는 커뮤니티 게시글 이동/식별 값으로 사용한다.HomePopularCommunityPostItem.price,existOrdered는 추천 페이지용FeedCommunityView의 유료 미구매 UI 판정에 사용한다.HomePopularCommunityPostItem.content,price,createdAt,likeCount,commentCount는 인기 커뮤니티 feed 표시 데이터로 사용한다.
Activity Type 다국어 표시
HomeActiveCreatorItem.activityType은 백엔드 enum code를 앱 표시용 enum으로 변환한다.
Backend Codes
enum class RecommendedActivityType(val code: String) {
LIVE("LIVE"),
AUDIO("AUDIO"),
COMMUNITY("COMMUNITY"),
LIVE_REPLAY("LIVE_REPLAY")
}
Requirements
LIVE,LIVE_REPLAY는 동일하게라이브로 표시한다.AUDIO는오디오로 표시한다.COMMUNITY는커뮤니티로 표시한다.- 표시 문구는
strings.xml,values-en/strings.xml등 string resource를 통해 다국어 처리한다. - 알 수 없는 code는 크래시시키지 않고 기본값 또는 미표시 정책을 구현 계획에서 확정한다.
- mapper 또는 enum 변환 로직은 local unit test로 검증한다.
사업자 정보 접기/더보기
Figma 최하단 사업자 정보 섹션(218:2058)은 외부 라이브러리 없이 TextView와 클릭 가능한 컨트롤로 구현한다.
Requirements
- 기본 상태는 최대 3줄, 끝 말줄임표로 표시한다.
- 기본 상태에서
더보기를 터치하면 전체 텍스트를 표시한다. - 펼침 상태에서
접기를 터치하면 다시 최대 3줄 말줄임 상태로 돌아간다. 더보기/접기표시 문구는 string resource로 관리한다.- 외부 라이브러리를 사용하지 않는다.
- 사업자 정보 텍스트는 하드코딩 여부를 구현 계획에서 확인하되, 다국어/운영 변경 가능성이 있으면 string resource 또는 서버/설정값 사용을 우선 검토한다.
- 텍스트가 3줄 이하인 경우
더보기를 표시하지 않는다.
상단 Bar와 추천 Tab
HomeMainFragment에서 추천 탭 선택 상태의 메인 홈 추천 페이지를 표시한다.
Requirements
- title-bar는 기존
view_title_bar_home을 사용한다. - title-bar 우측 아이콘은 왼쪽부터
ic_bar_cash,ic_bar_search,ic_bar_bell순서로 배치한다. - tab-bar는 기존
TextTabBarView를 사용한다. - tab 항목은
추천,랭킹,팔로잉순서로 구성한다. - 이 PRD의 화면은
추천tab이 선택되었을 때 표시되는 page다. - tab 표시 문구는 string resource로 관리한다.
- tab 전환은 글자 터치로만 처리하고, 좌우 swipe 또는
ViewPager기반 전환은 제공하지 않는다. TextTabBarView아래에는 이번 범위의 추천 page view만 구성한다.랭킹,팔로잉page는 이번 PRD에서 Fragment나VISIBLE/GONE대상 View로 미리 만들지 않는다.- 세로 스크롤 시 title-bar와
TextTabBarView는 화면에 유지하고,TextTabBarView아래 추천 content 영역만 스크롤되도록 구성한다.
모두 팔로우 하기
최근 응원이 많은 크리에이터, 장르별 크리에이터 섹션에는 모두 팔로우 버튼을 제공한다.
API Requirements
- API는
POST /api/v2/home/recommendations/creators/follow를 사용한다. - request body는
FollowRecommendedCreatorsRequest를 사용한다. - 기존 API에 추가하지 않고, 홈 추천 전용 신규 API 인터페이스에 포함한다.
- API 호출이 정상 완료되고 response가 success이면 버튼 상태를
모두 팔로우 완료로 변경한다. - 실패 시 기존 화면의 toast/error 표시 패턴을 따른다.
Request Contract
data class FollowRecommendedCreatorsRequest(
val creatorIds: List<Long>
)
Request Requirements
creatorIds에는 사용자가 터치한모두 팔로우 하기버튼이 속한 섹션의 크리에이터 id 목록을 전달한다.최근 응원이 많은 크리에이터섹션에서는cheerCreators.creatorId목록을 전달한다.장르별 크리에이터섹션에서는 해당 장르 그룹의creators.creatorId목록을 전달한다.creatorIds가 빈 리스트인 경우 API를 호출하지 않고 버튼 상태를 변경하지 않는다.
Button Requirements
- 기본 상태 버튼 문구는
모두 팔로우 하기다. - 기본 상태 아이콘은
ic_new_follow를 사용한다. - 완료 상태 버튼 문구는
모두 팔로우 완료다. - 완료 상태 아이콘은
ic_new_following을 사용한다. - 완료 상태 Figma reference: https://www.figma.com/design/HmN1yNdJ3EIpqknFL0Hkab/-%EA%B3%B5%EC%9C%A0%EC%9A%A9-%EB%B3%B4%EC%9D%B4%EC%8A%A4%EC%98%A8-UI-UX-%EA%B8%B0%ED%9A%8D%EB%AC%B8%EC%84%9C?node-id=24-9092&m=dev
- 완료 상태 버튼은 Figma
24:9092기준 white background, capsule radius100dp, horizontal/vertical padding12dp, icon20dp, icon/text gap6dp, Pretendard Medium16sp, black text를 기준으로 한다. - 문구는 string resource로 관리한다.
- 버튼 상태는 API success 후 중복 호출되지 않도록 disabled 또는 click 무시 상태로 전환한다.
추천 페이지 위젯 수정
추천 페이지에 표시되는 기존 widget은 화면 요구사항에 맞춰 최소 범위로 확장한다. 별도 PRD로 분리하지 않고, 메인 홈 추천 UI의 표시 계약으로 이 문서에 함께 기록한다.
FeedCommunityView Requirements
- 추천 페이지의 인기 커뮤니티는
HomePopularCommunityPostItem을FeedCommunityView또는FeedAdapter의 Community variant로 매핑한다. - 기존 keyword 영역은 추천 페이지에서는 제거한다.
HomePopularCommunityPostItem.content는 본문 영역에 표시한다.HomePopularCommunityPostItem.imageUrl이 있으면 본문 아래 이미지 영역을 표시한다.- 이미지 영역은 Figma
309:19774,309:19775기준346dp x 236dp, radius14dp, centerCrop을 기준으로 한다. imageUrl이 null이면 이미지 영역은GONE처리한다.audioUrl은 이번 추천 카드에서 별도 플레이어 UI를 만들지 않고, 게시글 상세 이동 또는 후속 오디오 정책에서 사용한다.price > 0 && existOrdered == false이면 유료 미구매 커뮤니티 포스트로 판단한다.- 유료 미구매 커뮤니티 포스트는 Figma
309:19774기준으로 이미지 위에 blur/lock overlay와 가격 capsule을 표시한다. - 가격 capsule에는
HomePopularCommunityPostItem.price를 표시한다. price > 0 && existOrdered == true이면 유료 구매 완료 포스트로 판단한다.price == 0이면 무료 포스트로 판단한다.- 유료 구매 완료 포스트 또는 무료 포스트는 Figma
309:19775의 이미지 표시 상태를 기준으로 하되, Figma에 있는구매완료버튼/태그는 표시하지 않는다. - 댓글 수와 좋아요 수는 기존 reaction row를 유지한다.
- creator profile, creator name, createdAt, body, reaction row typography와 색상은 기존
FeedCommunityView기준을 유지한다.
FeedCommunityView Figma References
- 유료이고 구매하지 않은 UI: https://www.figma.com/design/HmN1yNdJ3EIpqknFL0Hkab/-%EA%B3%B5%EC%9C%A0%EC%9A%A9-%EB%B3%B4%EC%9D%B4%EC%8A%A4%EC%98%A8-UI-UX-%EA%B8%B0%ED%9A%8D%EB%AC%B8%EC%84%9C?node-id=309-19774&m=dev
- 유료인데 구매함 또는 무료 UI: https://www.figma.com/design/HmN1yNdJ3EIpqknFL0Hkab/-%EA%B3%B5%EC%9C%A0%EC%9A%A9-%EB%B3%B4%EC%9D%B4%EC%8A%A4%EC%98%A8-UI-UX-%EA%B8%B0%ED%9A%8D%EB%AC%B8%EC%84%9C?node-id=309-19775&m=dev
AudioContentCardView Requirements
- 첫 오디오 콘텐츠는
v2.widget.AudioContentCardView를 사용한다. HomeFirstAudioContentItem.isPointAvailable == true이면ic_content_tag_point를 쓰는ImageView를 표시한다.HomeFirstAudioContentItem에서는 오리지널 여부를 판단하지 않는다.- 오리지널 판단 변수가 없으므로
ic_content_tag_original을 쓰는ImageView는 항상GONE처리한다. HomeFirstAudioContentItem.price == 0이면 무료 콘텐츠로 판단하고무료TextView를VISIBLE로 표시한다.HomeFirstAudioContentItem.price > 0이면무료TextView를GONE처리한다.HomeFirstAudioContentItem으로 표시하는 아이템은 모두 크리에이터의 첫 콘텐츠이므로FIRST글자를 포함하는LinearLayout을 항상 표시한다.- 위 조건에 해당하지 않는 태그는 모두
GONE처리한다. - 기존
AudioContentCardView의AudioContentTag.Original,AudioContentTag.Point,AudioContentTag.First,AudioContentTag.Free계약을 우선 재사용한다. HomeFirstAudioContentItem응답에는 오리지널 여부 필드가 없으므로 오리지널 태그는 표시하지 않는다.
섹션 구성과 UI 재사용 도식
Figma 24:5514 기준 홈 추천 화면은 아래 순서로 배치한다. 제외 섹션은 구현하지 않는다.
HomeRecommendation 화면
├─ 상단 title-bar / tab-bar / nav
│ ├─ title-bar: view_title_bar_home
│ │ └─ right icons: ic_bar_cash, ic_bar_search, ic_bar_bell
│ └─ tab-bar: TextTabBarView(추천 selected, 랭킹, 팔로잉)
└─ 추천 content scroll area
├─ 라이브 가로 목록: lives
│ ├─ Figma instance: live, more
│ ├─ 재사용: v2.widget.livethumbnail.LiveThumbnailSimpleView
│ └─ 신규: 더보기 item 또는 기존 more UI 대응 adapter item 필요
├─ 배너 캐러셀: banners
│ ├─ Figma instance: banner
│ └─ 재사용: v2.widget.banner.BannerView
├─ 최근 활동한 크리에이터: recentlyActiveCreators
│ ├─ Figma instance: section-title, list-act
│ ├─ 재사용: view_section_title
│ └─ 신규: list-act 형태의 최근 활동 카드 UI 필요
├─ 최근 데뷔한 크리에이터: recentDebutCreators
│ ├─ Figma instance: section-title, creater
│ ├─ 재사용: view_section_title
│ └─ 신규: 최근 데뷔 크리에이터 카드 UI
├─ 첫 오디오 콘텐츠: firstAudioContents
│ ├─ Figma instance: contents, profile
│ ├─ 재사용: v2.widget.AudioContentCardView
│ └─ 신규: 카드 하단 profile 결합 adapter item 필요 여부 확인
├─ AI 캐릭터: aiCharacters
│ ├─ Figma instance: section-title, chat-thumbnail
│ ├─ 재사용: view_section_title
│ └─ 재사용: v2.widget.characterchatthumbnail.CharacterChatThumbnailView
├─ 장르별 크리에이터: genreCreators
│ ├─ Figma instance: section-title, profile, button-capsule
│ ├─ 재사용: view_section_title
│ └─ 신규: 장르 그룹 카드, 2행 profile grid, 모두 팔로우 버튼
├─ 추천 필모그래피
│ └─ 제외: 만들지 않음
├─ 최근 응원이 많은 크리에이터: cheerCreators
│ ├─ Figma instance: section-title, profile, button-capsule
│ ├─ 재사용: view_section_title
│ └─ 신규: profile grid, 모두 팔로우 버튼
├─ 또 다른 모습
│ └─ 제외: 만들지 않음
├─ 인기 커뮤니티: popularCommunityPosts
│ ├─ Figma instance: section-title, feed
│ └─ 재사용/수정: v2.widget.feed.FeedCommunityView 또는 FeedAdapter Community variant
└─ 사업자 정보
└─ 신규: 3줄 말줄임 + 더보기/접기 TextView 영역
Section Mapping
| API field | Figma node range | 표시 섹션 | 재사용 후보 | 신규 필요 여부 |
|---|---|---|---|---|
lives |
24:5516 |
라이브 가로 목록 | LiveThumbnailSimpleView |
more item 확인 필요 |
banners |
24:5525 |
배너 캐러셀 | BannerView |
없음 |
recentlyActiveCreators |
24:5529 |
방금 활동한 크리에이터 | view_section_title |
list-act 신규 필요 |
recentDebutCreators |
24:5534 |
최근 데뷔한 크리에이터 | view_section_title |
신규 카드 필요 |
firstAudioContents |
24:5539 |
첫 오디오 콘텐츠 | AudioContentCardView |
태그 조건 매핑 확인 필요 |
aiCharacters |
24:5551 |
AI 캐릭터 | view_section_title, CharacterChatThumbnailView |
DTO mapping 필요 |
genreCreators |
24:5611, 24:5636 후보 |
장르별 크리에이터 | view_section_title |
그룹 카드, 모두 팔로우 버튼 신규 필요 |
cheerCreators |
24:5636 후보 |
최근 응원이 많은 크리에이터 | view_section_title |
profile grid, 모두 팔로우 버튼 신규 필요 |
popularCommunityPosts |
24:5645, 309:19774, 309:19775 |
인기 커뮤니티 | view_section_title, FeedCommunityView |
이미지/유료 상태 UI 수정 필요 |
| 사업자 정보 | 218:2058 |
사업자 정보 | 없음 | 접기/더보기 신규 필요 |
제외 섹션
- Figma
24:5557근처의추천 필모그래피로 판단되는 카드형 시리즈/필모그래피 영역은 구현하지 않는다. - Figma
24:5602근처의또 다른 모습으로 판단되는 콘텐츠 grid 영역은 구현하지 않는다. - 제외 섹션과 연결되는 서버 필드가 현재 응답에 없으므로 adapter item도 만들지 않는다.
Edge Cases
- 모든 추천 리스트가 비어 있으면 홈 추천 영역은 비어 있는 섹션을 노출하지 않고, 기존 홈 화면 empty 정책을 따른다.
- 특정 섹션만 비어 있으면 해당 section-title과 목록 전체를 숨긴다.
- 긴 제목, 닉네임, 커뮤니티 본문은 각 widget의 말줄임 정책을 따른다.
HomeAiCharacterItem.profileImage가 null이면 호출부 이미지 로딩 정책에 따라 placeholder 또는 빈 상태를 표시한다.HomePopularCommunityPostItem.imageUrl또는audioUrl이 null이어도 커뮤니티 feed는 본문/반응 수 중심으로 표시 가능해야 한다.- 유료 미구매 포스트의 가격 capsule은
price값을 사용하고, 유료 구매 완료 또는 무료 포스트에는 가격 capsule을 표시하지 않는다. HomeBannerItem은type없이eventItem,creatorId,seriesId,link값 기준으로 이동한다.- 배너 이동 우선순위는
eventItem,creatorId,seriesId,link순서로 처리한다. link가 웹 URL이면Intent.ACTION_VIEW를 사용해 외부 웹 URL로 이동한다.link가 내부 딥링크이면 기존 딥링크 실행 정책에 따라 앱 내부 딥링크를 실행한다.- 웹 URL도 내부 딥링크도 아닌
link는 이동하지 않는다.
8. UX / UI Expectations
- Figma
24:5514의 세로 순서, 좌우 여백, 가로 스크롤 형태를 유지한다. HomeMainFragment의 추천 tab page로 표시하며,TextTabBarView에서 추천 선택 상태가 명확해야 한다.ViewPager나 swipe로 tab을 넘기는 동작은 없어야 하며, tab 글자 터치로만 전환한다.- 세로 스크롤 중에도
TextTabBarView가 화면에 남아 있어야 하므로, 스크롤 컨테이너는TextTabBarView아래 content 영역에만 적용한다. - 상단 라이브 목록, 배너, 추천 카드들은 어두운 홈 배경 위에서 기존 v2 widget 색상/typography/radius를 유지한다.
- 각 섹션 제목은 기존
view_section_title을 사용한다. 최근 응원이 많은 크리에이터,장르별 크리에이터의 모두 팔로우 버튼은 success 전/후 상태가 명확히 구분되어야 한다.- 인기 커뮤니티는 keyword 없이 본문, 선택적 이미지, 유료 잠금 상태, reaction row를 보여야 한다.
- 유료 미구매 커뮤니티 이미지는 내용을 바로 읽을 수 없도록 blur/lock overlay가 적용되어야 한다.
- 유료 구매 완료 또는 무료 커뮤니티 이미지는 overlay 없이 표시하고,
구매완료태그는 표시하지 않는다. - 가로 목록은 화면 밖 다음 item이 일부 보이도록 Figma의 peek 느낌을 유지한다.
- 커뮤니티 본문과 사업자 정보는 긴 텍스트가 화면 폭을 밀어내지 않아야 한다.
- 사업자 정보는 기본 3줄만 보여 홈 탐색을 방해하지 않고, 사용자가 원할 때 전체 내용을 확인할 수 있어야 한다.
- 터치 동작은 UI 컴포넌트 내부에서 목적지를 결정하지 않고 화면/adapter callback으로 위임한다.
9. Technical Constraints
- 현재 프로젝트는 Android XML Views + Kotlin + ViewBinding 기반이므로 XML layout, RecyclerView/adapter, custom view 패턴을 우선한다.
- UI는 기존
kr.co.vividnext.sodalive.v2.main.HomeMainFragment에 구현한다. HomeMainFragment는 이번 범위에서 추천 content만 직접 구성하며,ViewPager2,FragmentStateAdapter, tab별 신규 Fragment 3개 구조는 도입하지 않는다.TextTabBarView아래 추천 content 영역만NestedScrollView또는 동등한 단일 세로 스크롤 컨테이너로 구성한다.- 신규 API/Repository/ViewModel 및 그와 연결된 하위 코드는
kr.co.vividnext.sodalive.v2패키지 하위에 작성한다. - 기존
kr.co.vividnext.sodalive.v2.widget.*컴포넌트를 우선 재사용한다. - 기존 API 인터페이스에 메서드를 추가하지 않고, 홈 추천 전용 신규 API 인터페이스를 만든다.
- 이미지 로딩 라이브러리를 새로 추가하지 않고 기존 호출부의 이미지 로딩 방식을 따른다.
- 외부 라이브러리를 추가하지 않는다.
- API 모델은 기존 네트워크 스택과 JSON 파서 규칙을 따른다.
- string resource 기반 다국어 처리를 적용하며, UI 표시 문자열을 Kotlin 코드에 직접 하드코딩하지 않는다.
- Figma에 있는 기존 widget과 다른 신규 UI는 구현 계획에서 파일 경로와 테스트 범위를 명시한 뒤 최소 범위로 작성한다.
- 신규 순수 변환 로직(activity type mapper, count/time formatter 등)은 가능하면 local unit test로 검증한다.
10. Metrics
- PRD와 구현 계획에 Figma 섹션 배치, 재사용 widget, 신규 필요 컴포넌트가 한눈에 확인 가능하게 정리된다.
HomeRecommendationResponse의 각 필드가 노출/제외/확인필요 중 하나로 분류된다.LIVE,LIVE_REPLAY,AUDIO,COMMUNITY표시 문자열이 string resource 기반으로 매핑된다.HomeMainFragment에서view_title_bar_home,TextTabBarView,view_section_title재사용이 확인된다.FeedCommunityView에서 keyword 영역이 추천 페이지에 노출되지 않고, 이미지와 유료 미구매 overlay가 표시된다.AudioContentCardView에서ic_content_tag_point,무료,FIRST태그가 조건에 맞게 표시되고,ic_content_tag_original은 표시되지 않는다.- 제외 대상인
추천 필모그래피,또 다른 모습섹션이 화면에 생성되지 않는다. - 모두 팔로우 API success 후 버튼이
모두 팔로우 완료와ic_new_following상태로 변경된다. - 사업자 정보는 기본 3줄 말줄임, 더보기 후 전체 표시, 접기 후 3줄 복귀가 동작한다.
- 기존 v2 widget 재사용 범위가 구현 diff에서 확인된다.
- 관련 unit test, resource merge,
./gradlew :app:testDebugUnitTest또는 구현 범위에 맞는 단일 테스트가 성공한다.
11. Open Questions
- 홈 추천 API endpoint는
/api/v2/home/recommendations로 확정됐다. HTTP method는GET으로 가정하되, 구현 전 백엔드 계약 또는 기존HomeApi패턴에서 최종 확인한다. - 모두 팔로우 API는
POST /api/v2/home/recommendations/creators/follow, request body는FollowRecommendedCreatorsRequest(creatorIds: List<Long>)로 확정됐다. - 인증 token 처리 방식은 아직 제공되지 않았다. 구현 전 기존
HomeApi확장 지점과 공통 인증 interceptor 사용 여부를 확인해야 한다. genreCreators와cheerCreators의 profile grid는 기존 profile widget이 저장소에 있는지 추가 확인 후 재사용/신규를 결정한다.- 배너 이동 정책은
type없이eventItem,creatorId,seriesId,link값 기준으로 처리하는 것으로 확정됐다.link가 내부 딥링크이면 기존 딥링크 실행 정책을 사용한다. activityAt,releaseDate,createdAt,beginDateTime의 표시 포맷은 기존 시간 formatter 재사용 여부를 구현 계획에서 확인한다.
12. 검증 기록
- 2026-06-05: 사용자 추가 요청에 따라 배너
link가 내부 딥링크이면 기존 딥링크 실행 정책에 따라 앱 내부 딥링크를 실행하도록 PRD의 사용자 스토리, Edge Cases, Open Questions를 갱신했다. 문서 변경만 수행했으므로 Gradle 검증은 실행하지 않고 문서 재읽기로 확인한다. - 2026-06-01:
docs/prd/sample-prd.md와docs/agent-guides/work-plan-docs.md를 확인해 신규 문서 위치와 PRD 작성 형식을 맞췄다. - 2026-06-01: Figma
24:5514의 최상위 구조를 확인해live,banner,section-title,contents,chat-thumbnail,profile,feed, 사업자 정보 섹션의 배치와 제외 후보 섹션을 PRD에 반영했다. - 2026-06-01: 저장소의 기존 v2 widget 패키지(
banner,livethumbnail,characterchatthumbnail,feed,AudioContentCardView)와 관련 PRD를 확인해 재사용 후보를 문서화했다. - 2026-06-01: 사용자 추가 제공 정보에 따라 홈 추천 API URL을
GET /api/v2/home/recommendations로 PRD에 반영했다. - 2026-06-01: 사용자 추가 제공 정보에 따라 신규 API 인터페이스 방침,
HomeMainFragment구현 위치,view_title_bar_home,TextTabBarView,view_section_title재사용, 모두 팔로우 API/버튼 상태, 변경된HomeFirstAudioContentItem,HomeAiCharacterItem응답 계약을 PRD에 반영했다. - 2026-06-01: 저장소에서
HomeMainFragment,view_title_bar_home,view_section_title,TextTabBarView,ic_bar_cash,ic_bar_search,ic_bar_bell,ic_new_follow,ic_new_following존재를 확인했다. - 2026-06-01: Figma
24:9092를 확인해 모두 팔로우 완료 버튼의 white capsule,20dpicon,6dpgap,16spmedium text 요구사항을 PRD에 반영했다. - 2026-06-01: 사용자 추가 제공 정보에 따라 모두 팔로우 request body
FollowRecommendedCreatorsRequest(creatorIds: List<Long>?)와 섹션별creatorIds전달 정책을 PRD에 반영했다. - 2026-06-01: 사용자 추가 제공 정보에 따라 모두 팔로우 request body의
creatorIds를 nullable이 아닌List<Long>으로 변경하고 null 의미 확인 항목을 제거했다. - 2026-06-01: 사용자 추가 제공 정보에 따라 모두 팔로우 API HTTP method를
POST로 확정해 PRD에 반영했다. - 2026-06-01: 사용자 추가 제공 정보에 따라
HomeRecommendationResponse.popularCommunities를popularCommunityPosts로 변경하고,HomePopularCommunityPostItem응답 계약을 PRD에 반영했다. - 2026-06-01: 사용자 추가 제공 정보에 따라 추천 페이지의
FeedCommunityView수정 요구사항(keyword 제거, 이미지 추가, 유료 미구매 overlay, 구매완료 태그 제외)과AudioContentCardView태그 표시 정책을 PRD에 반영했다. - 2026-06-01: Figma
309:19774,309:19775의 design context와 screenshot을 확인해 유료 미구매/구매 또는 무료 커뮤니티 feed의 이미지, blur/lock overlay, reaction row 요구사항을 문서화했다. - 2026-06-01: 저장소에서
AudioContentCardView가AudioContentTag.Original,Point,First,Free와ic_content_tag_original,ic_content_tag_point를 이미 지원하는 것을 확인했다. - 2026-06-01: 사용자 추가 제공 정보에 따라
HomeFirstAudioContentItem으로 표시하는 모든 아이템은 첫 콘텐츠로 간주해FIRST태그를 항상 표시하도록 PRD에 반영했다. - 2026-06-01: 사용자 추가 제공 정보에 따라
HomePopularCommunityPostItem.content아래에price: Int를 추가하고, 유료 미구매 가격 capsule 표시값으로 사용하도록 PRD에 반영했다. - 2026-06-01: 사용자 추가 제공 정보에 따라
HomeFirstAudioContentItem.title아래에price: Int를 추가하고,price == 0이면 무료 태그를 표시하도록 PRD에 반영했다. - 2026-06-01: 사용자 추가 제공 정보에 따라
HomeFirstAudioContentItem에서는 오리지널 여부를 판단하지 않고, 오리지널 태그를 항상 숨기는 정책으로 PRD에 반영했다. - 2026-06-01: 사용자 추가 제공 정보에 따라
popularCommunityPosts.price와existOrdered조합으로 유료 미구매/유료 구매 완료/무료 포스트 UI를 판정하도록 PRD에 반영했다. - 2026-06-02: 사용자 추가 제공 정보에 따라
ViewPager/swipe tab 전환을 제외하고, tab 글자 터치 전환만 허용하며,TextTabBarView아래 추천 content 영역만 세로 스크롤되도록 요구사항을 반영했다. - 2026-06-05: Phase 7 구현에서 Figma
24:5645기준 인기 커뮤니티 섹션을FeedCommunityView확장과HomePopularCommunityAdapter로 연결했다. 추천용 커뮤니티는 keyword를 숨기고, 이미지 null 시 이미지 영역을 숨기며, 유료 미구매 상태에서는 overlay와 가격 capsule을 표시한다. 사용자 추가 요청에 따라 인기 커뮤니티 게시글은 최대 10개만 노출하도록 반영했고, 관련 targeted test/full unit test/resource merge/compile/ktlint가 성공했음을 확인했다. - 2026-06-05: Phase 7 리뷰에서 확인된
audioUrl상세 이동 데이터 보존 누락과 유료 미구매 원본 이미지 로드 위험을 수정했다.FeedItem.Community.audioUrl과 mapper 전달을 추가하고, 유료 미구매 item은 원본imageUrl을 로드하지 않도록 adapter를 보완했으며 관련 회귀 테스트와 Gradle 검증이 성공했다. - 2026-06-05: 유료 미구매 item 재바인딩 시 이전 Coil 요청이 뒤늦게 완료될 가능성을 방지하기 위해 locked image 경로에서 기존 Coil 요청을
dispose()로 취소한 뒤 drawable을 비우도록 추가 보완했다. - 2026-06-05: 인기 커뮤니티 Phase 7 UI를 실제 기기에서 확인할 수 있도록
HomeMainFragment의 임시 샘플 content에 무료/유료 미구매/구매 완료 커뮤니티 3건을 추가했다. 관련 컴파일, 홈 레이아웃 테스트, ktlint, resource merge는 성공했으나 연결 기기가 없어installDebug기반 실기기 확인은 수행하지 못했다. - 2026-06-05: 커뮤니티 게시물 이미지가 고정 크기 때문에 잘려 보이는 문제를 수정했다.
view_feed_community.xml에서 root와 이미지 container의 고정 폭/높이를 제거하고,FeedCommunityView에서 실제 card content width 기준346:236비율로 이미지 영역 높이를 계산하도록 변경했다. 관련 Feed/Home 테스트, compile, resource merge, ktlint가 성공했다.