Files
sodalive-android/docs/prd/20260520_크리에이터랭킹위젯컴포넌트_prd.md

13 KiB

PRD: 크리에이터 랭킹 위젯 컴포넌트

1. Overview

Figma 20:3702, 20:3709, 20:3711, 20:3713 디자인을 기준으로 크리에이터 랭킹을 순위 구간별 카드 형태로 표현하는 Android XML Views 기반 위젯 컴포넌트를 개발한다.


2. Problem

  • 크리에이터 랭킹은 순위 구간에 따라 카드 UI와 한 줄 배치 개수가 달라져야 한다.
  • 기기 폭이 하나로 고정되지 않으므로 Figma metadata size를 실제 이미지 크기로 고정하면 다양한 화면 폭에서 재사용하기 어렵다.
  • 2위~10위는 순위 구간별 row count는 다르지만 카드 UI는 동일하므로, 별도 medium/small 컴포넌트로 나누면 중복 구현이 생긴다.
  • 순위 변동, 신규 진입, 차단 상태, 터치 가능 여부가 함께 표시되어야 하므로 데이터와 UI 상태 계약을 명확히 해야 한다.

3. Goals

  • Figma 4개 노드 기준의 크리에이터 랭킹 카드 variant와 row 배치 정책을 제공한다.
  • 이미지 크기는 컴포넌트 내부에서 고정하지 않고 실제 사용하는 row container 폭과 row count에 맞춰 계산한다.
  • 순위 구간별 한 줄 배치 규칙을 제공한다.
    • 1위: 한 줄에 1개, Figma 20:3702, 큰 정사각형 카드.
    • 2위~7위: 한 줄에 2개, Figma 20:3709, 기본 정사각형 카드.
    • 8위~10위: 한 줄에 3개, Figma 20:3711, 기본 정사각형 카드.
    • 11위 이후: 가로형으로 한 줄에 1개, Figma 20:3713, 가로형 카드.
  • 2위7위와 8위10위는 UI가 동일하므로 하나의 기본 정사각형 카드 컴포넌트로 통일한다.
  • 1위 큰 카드는 순위 표시 부분이 다르므로 별도 큰 카드 컴포넌트로 작성한다.
  • rank-num 영역은 이전 순위와 비교한 변동 상태를 표시한다.
  • 차단 관계인 크리에이터는 이미지 블러, 이름 비노출 또는 대체문구, 터치 불가 상태로 표시한다.
  • 기존 화면 일괄 적용은 구현 계획에서 별도 task로 제한하고, 컴포넌트 계약을 우선 고정한다.

4. Non-Goals

  • 이번 범위에서는 서버 API 설계나 응답 필드명을 확정하지 않는다. 필요한 클라이언트 데이터 계약만 문서화한다.
  • 팔로우 버튼, 후원 랭킹, 콘텐츠 랭킹, 라이브 랭킹 UI는 변경하지 않는다.
  • Compose 컴포넌트 또는 Compose Theme를 추가하지 않는다.
  • Figma에 없는 skeleton loading, shimmer, pressed animation, 별도 badge, 광고 영역, 페이지네이션 UI를 추가하지 않는다.
  • 차단/차단 해제 기능 자체를 새로 만들지 않는다.
  • 내가 차단했는지, 나를 차단했는지를 UI에서 구분해 표시하지 않는다.
  • 이미지 로딩 라이브러리 교체를 수행하지 않는다.

5. Target Users

  • 크리에이터 랭킹 화면을 보는 앱 사용자.
  • XML 레이아웃과 RecyclerView 기반 랭킹 UI를 구현/유지보수하는 Android 개발자.

6. User Stories

  • 사용자는 크리에이터 랭킹의 상위 순위를 더 큰 카드로 빠르게 확인하고 싶다.
  • 사용자는 순위가 올랐는지, 내려갔는지, 유지됐는지, 신규 진입했는지 알고 싶다.
  • 사용자는 차단 관계에 있는 크리에이터의 상세 정보가 노출되지 않기를 기대한다.
  • 개발자는 순위 구간별 UI를 하나의 명확한 계약으로 바인딩하고 싶다.

7. Core Features

Creator Ranking Widget

크리에이터 랭킹 목록을 순위 구간별 카드 variant와 행 배치 규칙으로 표시한다.

Figma References

Variant and Row Requirements

Rank range Figma node Row count UI variant Size policy
1 20:3702 한 줄에 1개 Large 실제 사용 영역 폭을 1등분해 정사각형으로 표시
2~7 20:3709 한 줄에 2개 Compact 실제 사용 영역 폭을 2등분해 정사각형으로 표시
8~10 20:3711 한 줄에 3개 Compact 실제 사용 영역 폭을 3등분해 정사각형으로 표시
11+ 20:3713 한 줄에 1개 Horizontal 실제 사용 영역 폭을 1등분하고 Figma 가로형 비율로 표시

Variant Details

  • Large: 1위 전용 카드다. 순위 숫자와 순위 변동 표시 영역이 다른 정사각형 카드와 다르므로 별도 layout/custom view로 작성한다.
  • Compact: 2위10위 공통 정사각형 카드다. 2위7위와 8위~10위는 row count만 다르고 UI 구조는 동일하다.
  • Horizontal: 11위 이후 전용 가로형 카드다.
  • Figma metadata size는 참고용 비율 확인에만 사용하고, 구현에서 고정 dp 크기로 사용하지 않는다.

Figma Token Requirements

  • 공통 카드 이미지 radius는 radius_14 또는 14dp를 사용한다.
  • 공통 dim gradient는 위쪽 rgba(0,0,0,0), 아래쪽 black, opacity 50%, 전환 시작점 64.423% 기준으로 구현한다.
  • 공통 rank-num 배경은 gray_900 (#202020), radius 4dp, horizontal padding 4dp, gap 2dp를 사용한다.
  • 공통 rank-num 숫자는 Pretendard Variable Medium, 16sp, line-height 1.45, color white를 사용한다.
  • 공통 caret icon 크기는 14dp x 14dp를 기준으로 한다.
  • 순위 숫자는 Pattaya Regular를 사용하고 white~#EEEEEE vertical gradient와 0px 0px 4px rgba(0,0,0,0.48) shadow를 적용한다.
  • Large creator name은 Pretendard Variable Bold, 32sp, line-height 1.45, color white를 기준으로 한다.
  • 2열 Compact creator name은 Pretendard Variable Bold, 22sp, line-height 1.45, color white를 기준으로 한다.
  • 3열 Compact creator name은 Pretendard Variable Bold, 14sp, line-height normal, color white를 기준으로 한다.
  • Horizontal creator name은 Pretendard Variable Bold, 18sp, line-height 1.45, color white를 기준으로 한다.

Display Requirements

  • 모든 variant는 현재 순위 숫자를 표시한다.
  • rank-num 영역은 순위 변동 상태를 표시한다.
    • 순위 상승: ic_rank_caret_increase.
    • 순위 하락: ic_rank_caret_decrease.
    • 순위 동일: 숫자 없이 ic_rank_caret_stay 아이콘만 표시.
    • 신규 진입: rank-num 대신 ic_rank_new 이미지.
  • 신규 진입이 아니고 순위 동일이 아닌 경우 rank-num에는 이전 순위 대비 변동 숫자를 표시한다.
  • 1위~10위의 카드 이름 영역은 정상 접근 가능 상태에서만 크리에이터 이름을 표시한다.
  • 11위 이후 가로형 카드는 정상 접근 가능 상태에서 크리에이터 이름을 표시한다.

Blocked Creator Requirements

  • 내가 차단했거나 나를 차단한 크리에이터는 하나의 차단 관계 상태로만 전달받는다.
  • 차단 관계 상태에서는 프로필/대표 이미지를 블러 처리한다.
  • 차단 관계 상태의 1위~10위 카드는 크리에이터 이름을 표시하지 않는다.
  • 차단 관계 상태의 1위~10위 카드는 이름을 숨겨도 하단 dim gradient 영역은 유지한다.
  • 차단 관계 상태의 11위 이후 가로형 카드는 크리에이터 이름 대신 접근할 수 없는 정보입니다.를 표시한다.
  • 차단 관계 상태의 카드는 터치할 수 없다.
  • 접근 가능 상태의 카드는 터치할 수 있고, 터치 시 호출부가 크리에이터 상세 이동 등 후속 동작을 처리한다.

Data Contract Requirements

  • 최소 데이터 계약은 다음 정보를 포함해야 한다.
    • creatorId: 크리에이터 식별자.
    • rank: 현재 순위. 1부터 시작한다.
    • previousRank: 이전 순위. 신규 진입이면 null 허용.
    • rankChangeType: increase, decrease, stay, new 중 하나.
    • rankChangeAmount: 신규 진입이 아닌 경우 표시할 변동 숫자.
    • creatorName: 크리에이터 이름.
    • imageUrl: 카드 이미지 URL.
    • isBlocked: 내가 차단했거나 나를 차단한 차단 관계 여부.
  • UI는 isBlocked만 사용하고 차단 방향은 구분하지 않는다.
  • 순위 변동 타입은 크리에이터 랭킹 전용 타입이 아니라 콘텐츠 랭킹과 공유하는 공용 RankingChangeType을 사용한다.

Edge Cases

  • 랭킹 데이터가 0개이면 위젯 영역은 표시하지 않거나 호출부의 empty 정책을 따른다.
  • 랭킹 데이터가 1~10개이면 존재하는 순위까지만 구간 규칙을 적용한다.
  • rank가 누락되거나 1보다 작으면 호출부 데이터 오류로 간주하고 해당 항목을 표시하지 않는다.
  • rankChangeTypenew이면 previousRankrankChangeAmount가 없어도 된다.
  • rankChangeTypestay이면 rankChangeAmount가 있어도 숫자를 표시하지 않는다.
  • rankChangeTypeincrease 또는 decrease인데 rankChangeAmount가 없으면 구현 단계에서 데이터 검증 정책을 정한다.
  • 이미지 로딩 실패 시 placeholder 정책은 기존 이미지 로딩 계층 또는 호출 화면 정책을 따른다.

8. UX / UI Expectations

  • 전체 위젯은 어두운 배경 위에서 사용하는 것을 전제로 한다.
  • Figma 스크린샷 기준 카드 이미지는 rounded corner를 가진다.
  • 카드 이미지는 공통 dim gradient를 가진다. 차단 관계 상태에서 이름을 숨기더라도 1위~10위의 gradient overlay는 유지한다.
  • Large 카드는 1위 전용 순위 표시 형태를 따른다.
  • Compact 카드는 2위~10위에서 동일 UI를 사용하고, row count에 따라 표시 크기만 달라진다.
  • Horizontal 카드는 좌측 순위, 중앙 이미지, 우측 이름 영역을 가진다.
  • 이미지 크기는 고정 dp로 박지 않고 row container 폭에서 계산한다.
  • 정사각형 variant는 계산된 카드 폭과 동일한 높이로 표시한다.
  • 가로형 variant는 부모 폭을 채우고 Figma 가로형 비율에 맞는 높이를 유지한다.
  • 차단 관계 상태는 사용자가 상세로 들어갈 수 없음을 시각적으로 알 수 있어야 한다.

9. Technical Constraints

  • 현재 프로젝트는 Android XML Views + ViewBinding + RecyclerView 기반이므로 XML 레이아웃과 Kotlin custom view/adapter 패턴을 우선한다.
  • 신규 Kotlin 코드는 kr.co.vividnext.sodalive.v2 패키지 하위에 작성한다.
  • 재사용 가능한 위젯은 kr.co.vividnext.sodalive.v2.widget 또는 기능 범위에 맞는 하위 패키지에 둔다.
  • 기존 CreatorRankingAdapteritem_home_creator.xml는 레거시 홈 크리에이터 카드이므로, 기존 화면 변경 없이 새 컴포넌트의 참고 대상으로만 사용한다.
  • 기존 프로젝트의 이미지 로딩 방식이 화면별로 Glide/Coil을 함께 사용하므로, 컴포넌트 내부에 특정 이미지 로더를 강제하지 않는 API를 우선한다.
  • 차단 관계 이미지 블러는 기존 kr.co.vividnext.sodalive.common.image.BlurTransformation 등 기존 blur 구현의 재사용 가능성을 먼저 검토한다.
  • ic_rank_caret_increase, ic_rank_caret_decrease, ic_rank_caret_stay, ic_rank_new 리소스가 없으면 구현 단계에서 디자인 에셋 추가가 필요하다.
  • 기존 CreatorRankingChangeTypeRankingChangeType으로 rename/move해 크리에이터 랭킹과 콘텐츠 랭킹이 같은 타입을 참조하도록 한다.

10. Metrics

  • 순위 구간별 row count가 요구사항과 일치한다.
  • 1위는 Large, 2위~10위는 Compact, 11위 이후는 Horizontal variant로 바인딩된다.
  • rankChangeType별 아이콘/숫자 표시가 문서와 일치한다.
  • stay 상태에서는 숫자 없이 ic_rank_caret_stay만 표시된다.
  • 차단 관계 상태에서 이미지 블러, 이름 비노출/대체문구, 터치 불가가 모두 적용된다.
  • 차단 관계 상태에서 1위~10위 카드의 gradient overlay가 유지된다.
  • 이미지 크기가 고정 dp가 아닌 부모 폭과 row count 기반으로 계산된다.
  • 관련 unit test와 Android resource merge/build가 성공한다.

11. Open Questions

  • 서버 응답에 이전 순위, 신규 진입 여부, 차단 관계 여부가 이미 포함되는지 확인이 필요하다. 없으면 API/DTO 확장이 별도 백엔드 협의 항목이다.
  • Figma get_design_context 재확인 결과 typography/color/radius 토큰은 본 문서의 Figma Token Requirements에 반영했다.
  • rankChangeAmount가 순위 동일일 때는 숫자 없이 ic_rank_caret_stay 아이콘만 표시하는 것으로 확정했다.
  • 차단 관계 상태에서 1위~10위 카드의 이름 영역을 숨길 때 gradient 영역은 유지하는 것으로 확정했다.
  • 순위 변동 타입은 콘텐츠 랭킹과 같은 데이터이므로 공용 RankingChangeType으로 사용하는 것으로 확정했다.