Files
sodalive-android/docs/20260608_크리에이터_랭킹_페이지/prd.md

13 KiB

PRD: 크리에이터 랭킹 페이지

1. Overview

HomeMainFragment의 Text Tab bar에서 랭킹을 선택했을 때 GET /api/v2/home/rankings/creators 응답을 기존 kr.co.vividnext.sodalive.v2.widget.creatorranking 위젯으로 표시하는 홈 랭킹 페이지를 구현한다.


2. Problem

  • 홈 추천 화면에는 추천, 랭킹, 팔로잉 Text Tab bar가 이미 배치되어 있지만, 랭킹 선택 시 표시할 실제 페이지가 없다.
  • Figma 24:5654에는 홈 랭킹 화면과 크리에이터 랭킹 목록이 정의되어 있으나, 3번째 줄의 Capsule Tab bar는 이번 요구사항에서 제외해야 한다.
  • 기존 크리에이터 랭킹 위젯은 previousRank, rankChangeType, rankChangeAmount, creatorName, imageUrl, isBlocked 계약을 사용한다.
  • 신규 API 응답은 showRankChange, items[].rankChange, items[].isNew, items[].nickname, items[].profileImageUrl 형태이므로 기존 위젯 계약으로 변환하는 mapper가 필요하다.

3. Goals

  • HomeMainFragment에서 Text Tab bar의 랭킹 선택 시 크리에이터 랭킹 페이지를 표시한다.
  • API GET /api/v2/home/rankings/creators를 호출해 응답 item을 기존 CreatorRankingAdapter/CreatorRankingItem 기반 UI로 표시한다.
  • Figma 24:5654 기준 상단 TitleBar와 Text Tab bar 아래에 랭킹 목록을 배치한다.
  • Figma에 존재하더라도 3번째 줄 Capsule Tab bar(주간 인기, 지금 뜨는 중, 남성 인기, 여성 인기)는 배치하지 않는다.
  • 기존 kr.co.vividnext.sodalive.v2.widget.creatorranking 위젯을 우선 재사용하고, API 응답과 Figma 정합에 필요한 최소 변경만 수행한다.
  • 랭킹 item 터치 시 접근 가능한 크리에이터의 프로필 화면으로 이동할 수 있도록 한다.

4. Non-Goals

  • Capsule Tab bar 및 기간/성별/인기 유형 필터는 구현하지 않는다.
  • 팔로잉 탭 페이지는 구현하지 않는다.
  • 크리에이터 랭킹 위젯의 순위별 카드 variant 정책 자체를 새로 설계하지 않는다.
  • Figma에 없는 skeleton, shimmer, pagination, pull-to-refresh, 추가 배너, 광고 영역은 구현하지 않는다.
  • 서버 API 스키마를 클라이언트에서 임의로 변경하지 않는다.
  • Compose 전환, ViewPager2 기반 tab swipe 전환, tab별 신규 Fragment 대량 분리는 이번 범위에 포함하지 않는다.

5. Target Users

  • 홈에서 인기 크리에이터 순위를 확인하려는 앱 사용자.
  • HomeMainFragment와 v2 위젯 기반 홈 화면을 유지보수하는 Android 개발자.

6. User Stories

  • 사용자는 홈의 랭킹 탭을 눌러 크리에이터 순위를 바로 보고 싶다.
  • 사용자는 1위, 2~10위, 11위 이후 순위가 시각적으로 구분된 카드로 표시되길 기대한다.
  • 사용자는 신규 진입 또는 순위 변동 정보를 랭킹 카드에서 확인하고 싶다.
  • 사용자는 랭킹 item을 눌러 해당 크리에이터 프로필로 이동하고 싶다.
  • 개발자는 API 응답을 기존 랭킹 위젯 계약으로 명확히 변환해 재사용하고 싶다.

7. Core Features

Home Ranking Tab Page

HomeMainFragment의 Text Tab bar에서 랭킹 선택 상태일 때 크리에이터 랭킹 목록을 표시한다.

Requirements

  • Text Tab bar 항목은 기존과 동일하게 추천, 랭킹, 팔로잉 순서를 유지한다.
  • 랭킹 선택 시 Text Tab bar selected index가 랭킹으로 갱신되어야 한다.
  • TitleBar와 Text Tab bar는 기존 홈 추천 화면과 동일하게 상단에 유지한다.
  • Text Tab bar 아래 content 영역만 랭킹 페이지 content로 교체한다.
  • 랭킹 페이지 content는 세로 스크롤 가능한 목록으로 구성한다.
  • Figma 24:5654의 3번째 줄 Capsule Tab bar는 배치하지 않으므로, 랭킹 목록은 Text Tab bar 아래에서 바로 시작한다.
  • 추천 탭으로 다시 전환하면 기존 추천 페이지 content가 표시되어야 한다.

Edge Cases

  • API loading 중에는 기존 홈 추천 API loading 처리와 일관된 정책을 따른다.
  • API error 또는 empty 응답이면 랭킹 목록 영역을 비우거나 기존 홈 empty/error 정책에 맞춰 처리한다.
  • items가 빈 배열이면 CreatorRankingAdapter에는 빈 목록을 전달하고, 불필요한 placeholder UI는 추가하지 않는다.

Creator Ranking API Integration

홈 랭킹 페이지에서 GET /api/v2/home/rankings/creators를 호출하고 응답을 UI model로 변환한다.

API Endpoint

  • GET /api/v2/home/rankings/creators

Response Contract

{
  "showRankChange": true,
  "items": [
    {
      "rank": 1,
      "rankChange": 5,
      "isNew": false,
      "creatorId": 123,
      "nickname": "creator",
      "profileImageUrl": "https://cdn.example.com/profile.png"
    }
  ]
}

Mapping Requirements

Response field UI/widget field Requirement
items[].creatorId CreatorRankingItem.creatorId 그대로 전달한다.
items[].rank CreatorRankingItem.rank 1 이상인 item만 표시한다.
items[].nickname CreatorRankingItem.creatorName 그대로 전달한다.
items[].profileImageUrl CreatorRankingItem.imageUrl 그대로 전달한다.
items[].isNew CreatorRankingItem.rankChangeType true이면 RankingChangeType.New로 매핑한다.
items[].rankChange CreatorRankingItem.rankChangeType, CreatorRankingItem.rankChangeAmount null 또는 0이면 Stay, 양수이면 Increase, 음수이면 Decrease로 매핑하고 표시 숫자는 절대값을 사용한다.
showRankChange 순위 변동 표시 여부 false이면 모든 item의 rank-num 영역을 완전히 숨긴다.

Rank Change Rules

  • isNew=true이면 rankChange 값과 무관하게 RankingChangeType.New로 표시한다.
  • isNew=false && (rankChange=null || rankChange=0)이면 RankingChangeType.Stay로 표시한다.
  • isNew=false && rankChange > 0이면 RankingChangeType.Increase로 표시한다.
  • isNew=false && rankChange < 0이면 RankingChangeType.Decrease로 표시한다.
  • IncreaseDecrease의 표시 숫자는 abs(rankChange)를 사용한다.
  • showRankChange=false이면 isNew, rankChange 값과 무관하게 rank-num 영역을 완전히 숨긴다.
  • API 응답 item은 서버에서 항상 rank 오름차순으로 내려오지만, 클라이언트에서도 한 번 더 rank 기준 오름차순 정렬 후 표시한다.

Click Requirements

  • creatorId > 0인 item만 클릭 이벤트가 동작한다.
  • creatorId > 0인 item을 터치하면 UserProfileActivity로 이동하고 Constants.EXTRA_USER_IDcreatorId를 전달한다.
  • creatorId = 0인 item은 차단 관계인 크리에이터로 간주하며 클릭 이벤트가 동작하지 않는다.
  • 랭킹 item 터치 시 크리에이터 프로필 이동 외 별도 analytics/logging은 추가하지 않는다.

Creator Ranking Widget Reuse

기존 kr.co.vividnext.sodalive.v2.widget.creatorranking 컴포넌트를 랭킹 페이지 목록에 사용한다.

Existing Widget Fit

  • Figma 24:5654의 카드 구조는 기존 크리에이터 랭킹 위젯 PRD의 순위 구간과 일치한다.
    • 1위: Large
    • 2위~7위: 2열 Compact
    • 8위~10위: 3열 Compact
    • 11위 이후: Horizontal
  • 이미지 radius, dim gradient, Pattaya 순위 숫자, rank-num, New badge는 기존 위젯 계약을 따른다.
  • API 응답에서 차단 관계인 크리에이터는 creatorId=0으로 내려오므로 creatorId=0 item은 isBlocked=true, creatorId>0 item은 isBlocked=false로 매핑한다.

Required Change Candidates

  • showRankChange=false일 때 rank-num 영역을 완전히 숨기는 옵션이 기존 위젯에 없으면 최소 확장이 필요하다.
  • 기존 CreatorRankingItem.rankChangeAmount는 non-null Int이므로 rankChange=null 응답을 Stay0으로 안전하게 변환해야 한다.
  • 기존 위젯은 creatorName/imageUrl 이름을 사용하므로 API DTO와 UI model mapper를 분리한다.
  • 기존 Adapter의 span size는 position 기반으로 계산하므로 서버 정렬 보장과 별개로 mapper 또는 UI state에서 rank 기준으로 한 번 더 정렬한다.
  • creatorId=0 item은 기존 위젯의 차단 상태 UI를 적용하고, 클릭 listener가 동작하지 않도록 보장한다.

Edge Cases

  • rank < 1 item은 기존 CreatorRankingItem 생성 조건에 맞지 않으므로 표시하지 않는다.
  • nickname이 빈 값이면 빈 문자열 그대로 표시하되, 별도 대체 문구는 추가하지 않는다.
  • profileImageUrl이 빈 값이거나 이미지 로딩에 실패하면 기존 loadUrl/이미지 로딩 정책을 따른다.
  • creatorId=0인 차단 관계 item은 상세 이동을 막고, 기존 차단 상태 위젯 정책에 따라 이미지 블러와 이름 비노출/대체문구를 적용한다.
  • 동일 rank가 중복되면 서버 데이터 오류로 보고 클라이언트는 받은 순서 또는 rank 정렬 결과를 그대로 표시한다. 중복 보정 UI는 추가하지 않는다.

8. UX / UI Expectations

  • 전체 배경은 기존 홈과 동일한 black 계열을 유지한다.
  • TitleBar와 Text Tab bar는 Figma 24:5654 및 기존 홈 추천 구현과 동일한 위치/스타일을 유지한다.
  • Capsule Tab bar를 제거한 상태에서도 Text Tab bar 아래 여백이 과도하게 남지 않아야 한다.
  • 랭킹 목록 좌우 margin과 item gap은 기존 CreatorRankingAdapter와 Figma 목록 폭을 기준으로 맞춘다.
  • 랭킹 탭 선택 상태가 흰색 텍스트로 명확히 드러나야 한다.
  • 1위~20위까지 응답이 내려오면 Figma 예시처럼 20위까지 자연스럽게 스크롤로 확인할 수 있어야 한다.
  • 긴 닉네임은 기존 위젯의 ellipsize/line 제한 정책을 따른다.

9. Technical Constraints

  • Android XML Views, ViewBinding, RecyclerView 기반 기존 구조를 유지한다.
  • 신규 API DTO, Repository, ViewModel, mapper, UI model은 기존 홈 추천 패턴을 확인해 kr.co.vividnext.sodalive.v2.main.home 하위에 둔다.
  • 신규 Activity, Fragment, ViewModel 및 연결 하위 코드는 kr.co.vividnext.sodalive.v2 패키지 하위에 작성한다.
  • 화면은 우선 HomeMainFragmentfragment_v2_main_home.xml의 기존 상단 구조를 확장해 구현한다.
  • 기존 CreatorRankingAdapter.createGridLayoutManager()를 사용해 span 정책을 유지한다.
  • 크리에이터 프로필 이동은 creatorId > 0일 때만 기존 UserProfileActivityConstants.EXTRA_USER_ID 사용 패턴을 재사용한다.
  • 네트워크/API 등록은 기존 AppDI.kt의 홈 추천 API/Repository/ViewModel 등록 패턴을 따른다.
  • 구현 전 docs/20260608_크리에이터_랭킹_페이지/plan-task.md를 작성한 뒤 해당 계획에 따라 최소 구현한다.

10. Metrics

  • 랭킹 탭 선택 시 GET /api/v2/home/rankings/creators 응답 item이 CreatorRankingAdapter에 전달된다.
  • Figma 24:5654의 Capsule Tab bar는 화면에 존재하지 않는다.
  • 1위, 27위, 810위, 11위 이후 variant가 기존 위젯 정책과 일치한다.
  • isNew=true item은 New badge로 표시된다.
  • isNew=false && (rankChange=null || rankChange=0) item은 유지 상태로 표시된다.
  • rankChange > 0 item은 상승, rankChange < 0 item은 하락으로 표시된다.
  • showRankChange=false 응답에서는 rank-num 영역이 완전히 숨겨진다.
  • rank < 1 item은 표시되지 않는다.
  • creatorId=0 item은 클릭되지 않고, creatorId>0 item만 UserProfileActivity로 이동한다.
  • API 응답은 클라이언트에서 rank 기준 오름차순으로 한 번 더 정렬된다.
  • 빈 응답, API 실패, 이미지 실패가 crash 없이 처리된다.
  • 관련 mapper/unit test, HomeMainFragment layout test, compileDebugKotlin, ktlintCheck가 성공한다.

11. Open Questions

  • 없음.

12. References


13. Verification Log

  • 2026-06-08: docs/prd/sample-prd.md, docs/agent-guides/work-plan-docs.md, 기존 크리에이터 랭킹 위젯 PRD, CreatorRankingItem, CreatorRankingAdapter, CreatorRankingDeltaPresentation, RankingChangeType, HomeMainFragment를 확인했다.
  • 2026-06-08: Figma 24:5654의 design context와 screenshot을 확인했다. 화면에는 Capsule Tab bar가 포함되어 있으나 사용자 요구에 따라 PRD 범위에서 제외했다.
  • 2026-06-08: 이번 단계는 PRD 작성만 수행했으며 구현/빌드/테스트는 실행하지 않았다.
  • 2026-06-08: 사용자 추가 제공 정보에 따라 rankChange의 양수/음수/0 매핑, showRankChange=false 시 rank-num 완전 숨김, 클라이언트 rank 재정렬, creatorId=0 차단 관계 및 클릭 불가 정책을 반영했다.
  • 2026-06-08: 사용자 추가 제공 정보에 따라 랭킹 item 터치 시 UserProfileActivity 이동 외 별도 analytics/logging을 추가하지 않는 것으로 확정하고 Open Questions를 없음으로 정리했다.