Files
sodalive-android/docs/20260601_메인_홈_추천_UI와_API_연동/prd.md

33 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를 받아 Figma 24: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 releaseDate: 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.profileImageCharacterChatThumbnailView의 실제 이미지 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

추천 페이지 위젯 수정

추천 페이지에 표시되는 기존 widget은 화면 요구사항에 맞춰 최소 범위로 확장한다. 별도 PRD로 분리하지 않고, 메인 홈 추천 UI의 표시 계약으로 이 문서에 함께 기록한다.

FeedCommunityView Requirements

  • 추천 페이지의 인기 커뮤니티는 HomePopularCommunityPostItemFeedCommunityView 또는 FeedAdapter의 Community variant로 매핑한다.
  • 기존 keyword 영역은 추천 페이지에서는 제거한다.
  • HomePopularCommunityPostItem.content는 본문 영역에 표시한다.
  • HomePopularCommunityPostItem.imageUrl이 있으면 본문 아래 이미지 영역을 표시한다.
  • 이미지 영역은 Figma 309:19774, 309:19775 기준 346dp x 236dp, radius 14dp, 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

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 처리한다.
  • 기존 AudioContentCardViewAudioContentTag.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별 이동 정책은 서버 정의와 기존 딥링크/이동 정책을 확인한 뒤 구현한다.

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 사용 여부를 확인해야 한다.
  • genreCreatorscheerCreators의 profile grid는 기존 profile widget이 저장소에 있는지 추가 확인 후 재사용/신규를 결정한다.
  • 배너 type별 이동 정책(eventId, creatorId, seriesId, link)은 기존 딥링크/화면 이동 규칙과 백엔드 code 목록 확인이 필요하다.
  • activityAt, releaseDate, createdAt, beginDateTime의 표시 포맷은 기존 시간 formatter 재사용 여부를 구현 계획에서 확인한다.

12. 검증 기록

  • 2026-06-01: docs/prd/sample-prd.mddocs/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, 20dp icon, 6dp gap, 16sp medium 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.popularCommunitiespopularCommunityPosts로 변경하고, 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: 저장소에서 AudioContentCardViewAudioContentTag.Original, Point, First, Freeic_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.priceexistOrdered 조합으로 유료 미구매/유료 구매 완료/무료 포스트 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가 성공했다.