Files

21 KiB

메인 랭킹 UI 반응형 크기 조정 Plan / Task

Goal: 메인 홈 크리에이터 랭킹과 메인 콘텐츠 랭킹에서 402dp 이상은 현재 크기를 유지하고, 402dp 미만은 현재 크기를 device width / 402 비율로 축소한다. 크리에이터 랭킹 순위 숫자 폰트는 Pattaya로 맞춘다.

Architecture: 기존 creatorranking/contentranking 위젯 구조를 유지하고, 공통 402dp scale 계산은 두 랭킹 위젯에서 재사용 가능한 최소 단위로 분리한다. 기존 rank placement, card variant, mapper, API, 클릭 이동은 변경하지 않는다.

Tech Stack: Kotlin, Android XML Views, ViewBinding, RecyclerView, Android resource font, JUnit4/Robolectric local unit test.


전제와 성공 기준

  • PRD: docs/20260710_메인_랭킹_UI_반응형_크기_조정/prd.md
  • 기준 폭은 402dp이다.
  • device width >= 402dp이면 현재 글자/아이콘/UI 크기와 동일해야 한다.
  • device width < 402dp이면 현재 기준값에 device width / 402 scale을 적용한다.
  • Font - Pattaya 적용 대상은 크리에이터 랭킹의 순위 숫자 텍스트로 확정한다.
  • 402dp 미만 축소는 device width 기준 비율 적용이므로 별도 최소 글자 크기 하한은 두지 않는다.
  • 콘텐츠 랭킹 순위 숫자 폰트는 기존 Pattaya 표시를 유지한다.
  • 콘텐츠 닉네임은 현재 설정값을 기준으로 402dp 이상 유지, 402dp 미만 비율 축소한다.
  • API, DTO, mapper, ranking type, click routing, empty/error/loading 정책은 변경하지 않는다.
  • 구현 완료 후 최소 다음 명령을 실행한다.
    • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*"
    • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.contentranking.*"
    • ./gradlew :app:mergeDebugResources
    • ./gradlew :app:compileDebugKotlin
    • ./gradlew :app:ktlintCheck
    • git diff --check

현재 기준값

크리에이터 랭킹

Rank group 순위 글자 순위 변동 숫자 순위 변동 아이콘 크리에이터 닉네임
1위 96sp 16sp 기본 14dp x 14dp, NEW 36dp x 23dp 32sp
2~7위 54sp 16sp 기본 14dp x 14dp, NEW 36dp x 23dp 22sp
8~10위 36sp 14sp 기본 14dp x 14dp, NEW 36dp x 23dp 14sp
11위 이상 40sp 16sp 기본 14dp x 14dp, NEW 36dp x 23dp 18sp

콘텐츠 랭킹

Rank group 순위 글자 순위 변동 숫자 순위 변동 아이콘 콘텐츠 타이틀 콘텐츠 닉네임
1위 Large 96sp 16sp 기본 14dp x 14dp, NEW 36dp x 23dp 22sp 12sp
2~7위 MediumGrid 54sp 16sp 기본 14dp x 14dp, NEW 36dp x 23dp 22sp 12sp
8~10위 SmallGrid widthPx <= 140이면 36sp, 그 외 54sp 16sp 기본 14dp x 14dp, NEW 36dp x 23dp widthPx <= 140이면 14sp, 그 외 22sp 12sp
11위 이상 Horizontal 40sp 16sp 기본 14dp x 14dp, NEW 36dp x 23dp 18sp 14sp

파일 구조

  • 수정 후보: app/src/main/java/kr/co/vividnext/sodalive/v2/widget/ranking/RankingResponsiveScale.kt
    • 402dp 기준 scale 계산을 공통 로직으로 분리한다.
  • 생성 후보: app/src/test/java/kr/co/vividnext/sodalive/v2/widget/ranking/RankingResponsiveScaleTest.kt
    • 402dp, 401dp, 360dp, fallback scale 계약을 검증한다.
  • 수정 후보: app/src/main/res/layout/view_creator_ranking_top_card.xml
    • 크리에이터 랭킹 순위 숫자 fontFamily를 @font/pattaya_regular로 변경한다.
  • 수정 후보: app/src/main/res/layout/view_creator_ranking_lower_row.xml
    • 크리에이터 랭킹 순위 숫자 fontFamily를 @font/pattaya_regular로 변경한다.
  • 수정 후보: app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingTextStyle.kt
    • 현재 기준 크기와 scale 적용 결과를 분리해 계산한다.
  • 수정 후보: app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingTopCardView.kt
    • 순위/닉네임/순위 변동 텍스트와 순위 변동 아이콘 크기에 scale을 적용한다.
  • 수정 후보: app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingLowerRowView.kt
    • 11위 이상 row의 순위/닉네임/순위 변동 텍스트와 순위 변동 아이콘 크기에 scale을 적용한다.
  • 수정 후보: app/src/test/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingTextStyleTest.kt
    • rank group별 baseline과 402dp scale 적용 계약을 검증한다.
  • 수정 후보: app/src/main/java/kr/co/vividnext/sodalive/v2/widget/contentranking/ContentRankingLargeCardView.kt
    • Large 카드의 순위/타이틀/닉네임/순위 변동 UI에 scale을 적용한다.
  • 수정 후보: app/src/main/java/kr/co/vividnext/sodalive/v2/widget/contentranking/ContentRankingGridCardView.kt
    • MediumGrid/SmallGrid 카드의 조건부 baseline에 scale을 적용한다.
  • 수정 후보: app/src/main/java/kr/co/vividnext/sodalive/v2/widget/contentranking/ContentRankingHorizontalCardView.kt
    • Horizontal 카드의 순위/타이틀/닉네임/순위 변동 UI에 scale을 적용한다.
  • 생성 후보: app/src/test/java/kr/co/vividnext/sodalive/v2/widget/contentranking/ContentRankingResponsiveSizeTest.kt
    • 콘텐츠 랭킹 card variant별 baseline과 scale 적용 계약을 검증한다.

Phase 1: 기존 구조와 기준값 재확인

  • Task 1.1: 크리에이터 랭킹 현재 기준값 확인

    • 확인:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingTextStyle.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingDeltaPresentation.kt
      • app/src/main/res/layout/view_creator_ranking_top_card.xml
      • app/src/main/res/layout/view_creator_ranking_lower_row.xml
    • 작업:
      • rank group별 순위/닉네임/순위 변동 텍스트 baseline을 확인한다.
      • caret/New 아이콘 baseline과 pill padding/margin 값을 확인한다.
      • 현재 순위 숫자 fontFamily와 목표 Pattaya 차이를 확인한다.
    • 검증:
      • Run: rg -n "rankTextSizeSp|nameTextSizeSp|deltaTextSizeSp|iconWidthDp|iconHeightDp|fontFamily" app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking app/src/main/res/layout/view_creator_ranking_top_card.xml app/src/main/res/layout/view_creator_ranking_lower_row.xml
      • Expected: PRD baseline 값과 변경 대상 fontFamily가 확인된다.
    • 결과:
      • 2026-07-10: CreatorRankingTextStyle.kt, CreatorRankingDeltaPresentation.kt, creator ranking layout 2개에서 PRD baseline과 현재 순위 숫자 fontFamily @font/phosphate_solid를 확인했다. @font/pattaya_regular 리소스가 존재하므로 변경 대상은 creator ranking 순위 숫자 TextView 2곳으로 확정했다.
  • Task 1.2: 콘텐츠 랭킹 현재 기준값 확인

    • 확인:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/widget/contentranking/ContentRankingLargeCardView.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/widget/contentranking/ContentRankingGridCardView.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/widget/contentranking/ContentRankingHorizontalCardView.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/widget/contentranking/ContentRankingDeltaPresentation.kt
      • app/src/main/res/layout/view_content_ranking_large_card.xml
      • app/src/main/res/layout/view_content_ranking_grid_card_content.xml
      • app/src/main/res/layout/view_content_ranking_horizontal_card.xml
    • 작업:
      • card variant별 순위/타이틀/닉네임/순위 변동 baseline을 확인한다.
      • SmallGridwidthPx <= 140 조건부 baseline을 확인한다.
      • 콘텐츠 랭킹 순위 숫자 fontFamily가 기존 Pattaya 계열인지 확인한다.
    • 검증:
      • Run: rg -n "textSize|widthPx <= SMALL_THRESHOLD_PX|SMALL_THRESHOLD_PX|iconWidthDp|iconHeightDp|fontFamily" app/src/main/java/kr/co/vividnext/sodalive/v2/widget/contentranking app/src/main/res/layout/view_content_ranking_large_card.xml app/src/main/res/layout/view_content_ranking_grid_card_content.xml app/src/main/res/layout/view_content_ranking_horizontal_card.xml
      • Expected: PRD baseline 값과 조건부 SmallGrid 정책이 확인된다.
    • 결과:
      • 2026-07-10: ContentRankingLargeCardView.kt, ContentRankingGridCardView.kt, ContentRankingHorizontalCardView.kt, ContentRankingDeltaPresentation.kt, content ranking layout 3개에서 PRD baseline과 SmallGridwidthPx <= 140 분기를 확인했다. 콘텐츠 랭킹 순위 숫자 fontFamily는 이미 @font/pattaya_regular이다.

Phase 2: 402dp 반응형 scale 계약 추가

  • Task 2.1: 공통 scale 계산 테스트 작성

    • 생성:
      • app/src/test/java/kr/co/vividnext/sodalive/v2/widget/ranking/RankingResponsiveScaleTest.kt
    • 테스트:
      • screenWidthDp=402이면 1.0
      • screenWidthDp=430이면 1.0
      • screenWidthDp=360이면 360f / 402f
      • screenWidthDp<=0이면 1.0
    • 검증:
      • Run: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.ranking.RankingResponsiveScaleTest"
      • Expected: 구현 전 RED 실패.
    • 결과:
      • 2026-07-10: 구현 전 RankingResponsiveScale 미존재로 Unresolved reference RED 실패를 확인했다.
  • Task 2.2: 공통 scale 계산 로직 구현

    • 생성:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/widget/ranking/RankingResponsiveScale.kt
    • 구현:
      • 기준 폭 상수 BASE_WIDTH_DP = 402
      • screenWidthDp >= BASE_WIDTH_DP이면 1f
      • screenWidthDp in 1 until BASE_WIDTH_DP이면 screenWidthDp / BASE_WIDTH_DP.toFloat()
      • fallback은 1f
    • 검증:
      • Run: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.ranking.RankingResponsiveScaleTest"
      • Expected: PASS.
    • 결과:
      • 2026-07-10: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.ranking.RankingResponsiveScaleTest" PASS.

Phase 3: 크리에이터 랭킹 적용

  • Task 3.1: 크리에이터 랭킹 텍스트 스타일 테스트 작성

    • 수정 또는 생성:
      • app/src/test/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingTextStyleTest.kt
    • 테스트:
      • 402dp 이상에서 기존 baseline 크기 유지
      • 360dp에서 baseline에 360 / 402 scale 적용
      • rank group별 1위, 27위, 810위, 11위 이상 baseline 유지
    • 검증:
      • Run: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingTextStyleTest"
      • Expected: scale 적용 전 RED 실패.
    • 결과:
      • 2026-07-10: 구현 전 CreatorRankingTextStyle.scaledBy 미존재로 RED 실패를 확인했다.
  • Task 3.2: 크리에이터 랭킹 폰트와 텍스트 scale 적용

    • 수정:
      • app/src/main/res/layout/view_creator_ranking_top_card.xml
      • app/src/main/res/layout/view_creator_ranking_lower_row.xml
      • app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingTextStyle.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingTopCardView.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingLowerRowView.kt
    • 구현:
      • 순위 숫자 fontFamily를 @font/pattaya_regular로 변경한다.
      • resources.configuration.screenWidthDp에서 scale을 계산한다.
      • 순위/닉네임/순위 변동 숫자 setTextSize()에 scale 적용 값을 전달한다.
    • 검증:
      • Run: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*"
      • Expected: PASS.
    • 결과:
      • 2026-07-10: creator ranking 순위 숫자 fontFamily를 @font/pattaya_regular로 변경하고, 순위/닉네임/순위 변동 텍스트에 402dp scale을 적용했다. ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*" PASS.
  • Task 3.3: 크리에이터 랭킹 순위 변동 UI scale 적용

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingTopCardView.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingLowerRowView.kt
    • 구현:
      • caret 아이콘 14dp x 14dp에 scale 적용
      • NEW 아이콘 36dp x 23dp에 scale 적용
      • pill padding과 icon margin이 시각 크기에 영향을 주는 경우 scale 적용
      • showRankChange=false 숨김 정책은 유지
    • 검증:
      • Run: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*"
      • Expected: PASS.
    • 결과:
      • 2026-07-10: creator ranking caret/New 아이콘, icon margin, pill horizontal padding에 402dp scale을 적용했다. creator ranking targeted test PASS.

Phase 4: 콘텐츠 랭킹 적용

  • Task 4.1: 콘텐츠 랭킹 반응형 크기 테스트 작성

    • 생성:
      • app/src/test/java/kr/co/vividnext/sodalive/v2/widget/contentranking/ContentRankingResponsiveSizeTest.kt
    • 테스트:
      • Large baseline은 402dp 이상에서 순위 96sp, 타이틀 22sp, 닉네임 12sp
      • MediumGrid baseline은 402dp 이상에서 순위 54sp, 타이틀 22sp, 닉네임 12sp
      • SmallGrid widthPx <= 140 baseline은 순위 36sp, 타이틀 14sp, 닉네임 12sp
      • Horizontal baseline은 순위 40sp, 타이틀 18sp, 닉네임 14sp
      • 360dp에서는 각 baseline에 360 / 402 scale 적용
    • 검증:
      • Run: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.contentranking.ContentRankingResponsiveSizeTest"
      • Expected: scale 적용 전 RED 실패.
    • 결과:
      • 2026-07-10: 구현 전 ContentRankingTextStyle 미존재로 RED 실패를 확인했다.
      • 2026-07-10: 후속 수정으로 SmallGridsetCardSize()bind()만 호출되어도 402dp 미만 text size를 축소하는 회귀 테스트를 ContentRankingCardViewTest에 추가했다.
  • Task 4.2: 콘텐츠 랭킹 텍스트 scale 적용

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/widget/contentranking/ContentRankingLargeCardView.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/widget/contentranking/ContentRankingGridCardView.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/widget/contentranking/ContentRankingHorizontalCardView.kt
    • 구현:
      • resources.configuration.screenWidthDp 기준 scale을 적용한다.
      • 순위/타이틀/닉네임/순위 변동 숫자에 scale 적용 값을 전달한다.
      • SmallGrid는 기존 widthPx <= 140 분기 결과를 baseline으로 삼고 scale만 적용한다.
    • 검증:
      • Run: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.contentranking.*"
      • Expected: PASS.
    • 결과:
      • 2026-07-10: content ranking Large/MediumGrid/SmallGrid/Horizontal의 순위/타이틀/닉네임/순위 변동 숫자에 402dp scale을 적용했고, SmallGridwidthPx <= 140 분기는 유지했다. ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.contentranking.*" PASS.
      • 2026-07-10: 후속 수정으로 ContentRankingGridCardView가 adapter의 setCardSize() 선호출에만 의존하지 않도록 bind()에서 fallback text style을 적용하게 보완했다.
  • Task 4.3: 콘텐츠 랭킹 순위 변동 UI scale 적용

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/widget/contentranking/ContentRankingLargeCardView.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/widget/contentranking/ContentRankingGridCardView.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/widget/contentranking/ContentRankingHorizontalCardView.kt
    • 구현:
      • caret 아이콘 14dp x 14dp에 scale 적용
      • NEW 아이콘 36dp x 23dp에 scale 적용
      • pill padding과 icon margin이 시각 크기에 영향을 주는 경우 scale 적용
      • showRankChange=false 숨김 정책은 유지
    • 검증:
      • Run: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.contentranking.*"
      • Expected: PASS.
    • 결과:
      • 2026-07-10: content ranking caret/New 아이콘, icon margin, pill horizontal padding에 402dp scale을 적용했다. content ranking targeted test PASS.
      • 2026-07-10: 후속 수정으로 delta text size도 각 카드의 ContentRankingTextStyle.deltaTextSizeSp를 사용하도록 정리해 텍스트 scale 기준을 단일화했다.
  • Task 4.4: 콘텐츠 랭킹 SmallGrid 8~10위 순위 숫자 기준값 보정

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/widget/contentranking/ContentRankingTextStyle.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/widget/contentranking/ContentRankingResponsiveSizeTest.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/widget/contentranking/ContentRankingCardViewTest.kt
    • 구현:
      • ContentRankingGridCardView의 8~10위 SmallGrid가 사용하는 순위 숫자 baseline을 36sp로 맞춘다.
      • 콘텐츠 타이틀 14sp, 콘텐츠 닉네임 12sp, 402dp 미만 비율 축소 정책은 유지한다.
    • 검증:
      • Run: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.contentranking.*"
      • Expected: PASS.
    • 결과:
      • 2026-07-10: ContentRankingTextStyle.smallGrid()의 순위 숫자 baseline을 40sp에서 36sp로 보정했다. 콘텐츠 타이틀 14sp, 콘텐츠 닉네임 12sp, 402dp 미만 비율 축소 정책은 유지했다. ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.contentranking.*" PASS.

Phase 5: 통합 검증

  • Task 5.1: 리소스와 Kotlin 컴파일 검증

    • 검증:
      • Run: ./gradlew :app:mergeDebugResources
      • Expected: font resource 및 XML 변경이 정상 merge된다.
      • Run: ./gradlew :app:compileDebugKotlin
      • Expected: Kotlin 컴파일 성공.
    • 결과:
      • 2026-07-10: ./gradlew :app:mergeDebugResources PASS. ./gradlew :app:compileDebugKotlin PASS.
  • Task 5.2: 린트와 diff 검증

    • 검증:
      • Run: ./gradlew :app:ktlintCheck
      • Expected: Kotlin style 위반 없음.
      • Run: git diff --check
      • Expected: trailing whitespace 또는 patch 오류 없음.
    • 결과:
      • 2026-07-10: 최초 ktlintCheck에서 신규 테스트 공백 2건과 미사용 import 1건을 수정했다. 재실행 결과 ./gradlew :app:ktlintCheck PASS, git diff --check PASS.
  • Task 5.3: 수동 화면 확인

    • 확인:
      • 402dp 이상 기기 또는 emulator에서 기존 크기 유지
      • 402dp 미만 기기 또는 emulator에서 비율 축소
      • 크리에이터 랭킹 순위 숫자 폰트가 Pattaya
      • 콘텐츠 닉네임이 402dp 이상에서 현재 크기 유지, 402dp 미만에서 축소
      • 순위 변동 caret/New 아이콘과 pill이 텍스트와 함께 축소
    • 검증 기록:
      • 구현 후 실행 기기, 화면 폭, 확인 결과를 이 항목 아래에 누적한다.
      • 2026-07-10: 실제 emulator 실행은 수행하지 못했다. 대신 402dp 이상/미만/폭 미확인 fallback 계약은 RankingResponsiveScaleTest, creator/content baseline 및 360dp scale 계약은 CreatorRankingTextStyleTest, ContentRankingResponsiveSizeTest로 검증했고, resource merge로 creator Pattaya font XML 적용을 확인했다.

Verification Log

  • 2026-07-10: 콘텐츠 랭킹 SmallGrid 8~10위 순위 숫자 기준값을 요구사항에 맞춰 36sp로 보정했다. ContentRankingResponsiveSizeTest, ContentRankingCardViewTest 기대값을 함께 갱신했고, ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.contentranking.*", ./gradlew :app:ktlintCheck, git diff --check PASS.
  • 2026-07-10: 콘텐츠 랭킹 글자 크기 적용 누락 의심 후속 확인을 진행했다. 실제 TextView.textSize 검증 테스트를 ContentRankingCardViewTest에 추가했고, Large/MediumGrid/SmallGrid/Horizontal 카드에서 360dp 기준 축소가 적용됨을 확인했다. 콘텐츠 랭킹 view의 setCardSize()/bind() 순서와 무관하게 텍스트 스타일이 유지되도록 적용 위치를 보강했다. ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.contentranking.*", ./gradlew :app:ktlintCheck, git diff --check PASS.
  • 2026-07-10: 사용자 요청에 따라 문서만 생성했다. Production code, test code, resource file은 수정하지 않았고 Gradle 검증은 실행하지 않았다.
  • 2026-07-10: 랭킹 402dp 반응형 scale 구현 후 targeted creator/content/ranking 테스트, resource merge, Kotlin compile, ktlintCheck, git diff --check를 실행해 PASS를 확인했다. 실제 emulator 수동 확인은 수행하지 못해 테스트와 resource merge 기반으로 대체 기록했다.