# 메인 랭킹 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: 기존 구조와 기준값 재확인 - [x] **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곳으로 확정했다. - [x] **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을 확인한다. - `SmallGrid`의 `widthPx <= 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과 `SmallGrid`의 `widthPx <= 140` 분기를 확인했다. 콘텐츠 랭킹 순위 숫자 fontFamily는 이미 `@font/pattaya_regular`이다. --- ### Phase 2: 402dp 반응형 scale 계약 추가 - [x] **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 실패를 확인했다. - [x] **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: 크리에이터 랭킹 적용 - [x] **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위, 2~7위, 8~10위, 11위 이상 baseline 유지 - 검증: - Run: `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingTextStyleTest"` - Expected: scale 적용 전 RED 실패. - 결과: - 2026-07-10: 구현 전 `CreatorRankingTextStyle.scaledBy` 미존재로 RED 실패를 확인했다. - [x] **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. - [x] **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: 콘텐츠 랭킹 적용 - [x] **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: 후속 수정으로 `SmallGrid`가 `setCardSize()` 전 `bind()`만 호출되어도 402dp 미만 text size를 축소하는 회귀 테스트를 `ContentRankingCardViewTest`에 추가했다. - [x] **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을 적용했고, `SmallGrid`의 `widthPx <= 140` 분기는 유지했다. `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.contentranking.*"` PASS. - 2026-07-10: 후속 수정으로 `ContentRankingGridCardView`가 adapter의 `setCardSize()` 선호출에만 의존하지 않도록 `bind()`에서 fallback text style을 적용하게 보완했다. - [x] **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 기준을 단일화했다. - [x] **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: 통합 검증 - [x] **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. - [x] **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. - [x] **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 기반으로 대체 기록했다.