85 KiB
크리에이터 랭킹 페이지 Plan / Task
For agentic workers: 구현 시
superpowers:subagent-driven-development또는superpowers:executing-plans를 사용해 task 단위로 진행한다. 각 단계는 체크박스(- [ ])로 추적하고, 완료 즉시- [x]로 갱신한다.
Goal: HomeMainFragment의 Text Tab bar에서 랭킹 선택 시 GET /api/v2/home/rankings/creators 응답을 기존 creatorranking 위젯으로 표시한다.
Architecture: 신규 홈 크리에이터 랭킹 API, Repository, ViewModel, DTO/UI model/mapper는 기존 홈 추천 패턴과 같은 kr.co.vividnext.sodalive.v2.main.home 하위에 둔다. 화면은 HomeMainFragment와 fragment_v2_main_home.xml을 최소 확장하고, 기존 kr.co.vividnext.sodalive.v2.widget.creatorranking 위젯은 showRankChange=false 숨김 옵션만 필요한 만큼 확장한다.
Tech Stack: Kotlin, Android XML Views, ViewBinding, RecyclerView, RxJava3, Retrofit, Gson, Koin, Coil, Robolectric/local unit test.
후속 Rewrite 전제
- 후속 구현에서는 크리에이터 랭킹 view를 기존 view 부분 보정이 아니라 새 view로 다시 작성한다.
- 신규 크리에이터 랭킹 view는
ConstraintLayout을 사용하고FrameLayout을 사용하지 않는다. - Figma 기준은 1 per row
24:5659, 2 per row24:5660, 3 per row24:5668, 11~20 lower row24:5670이다. - adapter view type은 ranks
1~10, ranks11~20두 개만 둔다. rank > 20은 이번 문서 갱신 및 후속 rewrite 계획에서 mapper/API 동작을 변경하지 않는다. 별도 요구가 있기 전까지 현재 lower-row 처리 방식은 유지할 수 있다.- rank change와
NEW표시 로직은CreatorRankingDeltaPresentation과HomeCreatorRankingMappers의미를 유지한다. - ranks
1~10텍스트 크기 정책은 1 item row rank/name/delta96sp/32sp/16sp, 2 item row54sp/22sp/16sp, 3 item row36sp/14sp/14sp이다. - ranks
11~20은 Figma24:5670lower-row 기준으로 rank40sp, name18sp를 사용한다. - XML/Kotlin에서 layout sizing 목적으로 고정 width/height를 새로 도입하지 않는다.
wrap_content,match_parent, margins, padding, constraints, match-constraint, 측정된 available width, aspect handling을 필요에 따라 사용한다. - 테스트는 placement, text-style model, mapper, delta presentation, item behavior 같은 logic contract에만 작성한다.
- view size, margin, padding, constraints,
TextViewdimensions, inflated layout params, visibility attributes를 검증하는 UI layout/visual test는 작성하지 않는다.
전제와 성공 기준
- PRD:
docs/20260608_크리에이터_랭킹_페이지/prd.md - Figma:
24:5654 - Capsule Tab bar(
주간 인기,지금 뜨는 중,남성 인기,여성 인기)는 배치하지 않는다. rankChange는null/0->Stay, 양수 ->Increase, 음수 ->Decrease로 매핑한다.isNew=true는rankChange보다 우선해New로 매핑한다.showRankChange=false이면 모든 rank-num 영역을 완전히 숨긴다.- API 응답은 서버에서
rank오름차순으로 내려오지만, 클라이언트에서도 한 번 더rank기준 오름차순 정렬한다. creatorId=0은 차단 관계로 보고isBlocked=true, 클릭 불가로 처리한다.creatorId>0item만UserProfileActivity로 이동하며, 별도 analytics/logging은 추가하지 않는다.- 구현 완료 후 최소 다음 명령을 실행한다.
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*"./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*"./gradlew :app:mergeDebugResources./gradlew :app:compileDebugKotlin./gradlew :app:ktlintCheck
파일 구조
- 생성:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/data/HomeCreatorRankingModels.ktHomeCreatorRankingResponse,HomeCreatorRankingItemResponseDTO를 정의한다.
- 생성:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/data/HomeCreatorRankingApi.ktGET /api/v2/home/rankings/creatorsRetrofit endpoint를 정의한다.
- 생성:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/data/HomeCreatorRankingRepository.kt- API 호출을 감싸고 기존 repository 패턴과 동일하게 token을 전달한다.
- 생성:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/HomeCreatorRankingMappers.kt- API 응답을
CreatorRankingItem목록으로 변환한다.
- API 응답을
- 생성:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/HomeCreatorRankingUiState.ktLoading,Content,Empty,Error상태를 정의한다.
- 생성:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeCreatorRankingViewModel.kt- 랭킹 API 호출, loading, toast, state를 관리한다.
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt- 신규 API, Repository, ViewModel을 Koin에 등록한다.
- 수정:
app/src/main/res/layout/fragment_v2_main_home.xmlTextTabBarView아래에 랭킹 전용RecyclerView를 추가한다.
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/HomeMainFragment.kt랭킹탭 전환, 랭킹 adapter, ViewModel observe, 프로필 이동을 연결한다.
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingItem.ktshowRankChange표시 계약을 추가한다.
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingLargeCardView.kt - 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingCompactCardView.kt - 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingHorizontalCardView.ktshowRankChange=false일 때 rank-num 영역을GONE처리한다.
- 테스트 수정/생성:
- 수정:
app/src/test/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingItemTest.kt - 수정:
app/src/test/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingAdapterLayoutTest.kt - 생성:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeCreatorRankingMapperTest.kt - 수정:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragmentLayoutTest.kt
- 수정:
Phase 1: 기존 구조 확인과 작업 경계 고정
-
Task 1.1: 기존 홈/랭킹 위젯/DI 구조 확인
- 확인:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/HomeMainFragment.kt - 확인:
app/src/main/res/layout/fragment_v2_main_home.xml - 확인:
app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt - 확인:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/data/HomeRecommendationApi.kt - 확인:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeRecommendationViewModel.kt - 확인:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingAdapter.kt - 확인:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingItem.kt - 검증: 기존 추천 content는
nsv_home_recommendation_content아래에 있고, 랭킹 content는 별도 container가 필요함을 확인한다.
- 확인:
-
Task 1.2: 구현 제외 범위 재확인
- 확인:
docs/20260608_크리에이터_랭킹_페이지/prd.md - 제외:
- Capsule Tab bar
- 팔로잉 탭 content
- analytics/logging
- ViewPager2/swipe 전환
- 검증: 계획 문서의 모든 phase가 위 제외 범위를 침범하지 않는지 확인한다.
- 확인:
Phase 2: creatorranking 위젯 rank-num 숨김 계약 확장
-
Task 2.1:
CreatorRankingItem표시 계약 테스트 추가- 수정:
app/src/test/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingItemTest.kt - 추가 테스트:
- 기본
showRankChange는true showRankChange=false인 item은 rank change 표시 대상이 아님creatorId=0,isBlocked=trueitem은isTouchable=false
- 기본
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingItemTest" - 기대 결과:
showRankChange속성 미구현으로 RED 실패.
- 수정:
-
Task 2.2:
CreatorRankingItem에showRankChange추가- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingItem.kt - 구현 내용:
val showRankChange: Boolean = true를 기본값 있는 마지막 파라미터로 추가한다.- 기존 테스트/호출부가 깨지지 않도록 기본값을 유지한다.
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingItemTest" - 기대 결과: PASS.
- 수정:
-
Task 2.3: rank-num 숨김 view 테스트 추가
- 수정:
app/src/test/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingAdapterLayoutTest.kt - 추가 테스트:
Large,Compact,Horizontalcard에showRankChange=falseitem을 bind하면ll_creator_ranking_delta가GONEshowRankChange=trueitem을 bind하면 기존처럼ll_creator_ranking_delta가VISIBLE
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingAdapterLayoutTest" - 기대 결과: view bind 미구현으로 RED 실패.
- 수정:
-
Task 2.4: rank-num 숨김 구현
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingLargeCardView.kt - 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingCompactCardView.kt - 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingHorizontalCardView.kt - 구현 내용:
bindDelta(item)시작부에서item.showRankChange == false이면 delta container를View.GONE으로 설정하고 return한다.item.showRankChange == true이면 delta container를View.VISIBLE로 복구한 뒤 기존 presentation 적용을 유지한다.
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*" - 기대 결과: PASS.
- 수정:
Phase 3: 홈 크리에이터 랭킹 API/DTO/mapper 작성
-
Task 3.1: mapper RED 테스트 작성
- 생성:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeCreatorRankingMapperTest.kt - 테스트 케이스:
- 응답 item을
rank오름차순으로 재정렬한다. isNew=true는RankingChangeType.New, amount0으로 매핑한다.rankChange=null또는0은RankingChangeType.Stay, amount0으로 매핑한다.rankChange=5는RankingChangeType.Increase, amount5로 매핑한다.rankChange=-3은RankingChangeType.Decrease, amount3으로 매핑한다.showRankChange=false이면 모든CreatorRankingItem.showRankChange=false로 매핑한다.creatorId=0은isBlocked=true,isTouchable=false로 매핑한다.rank < 1item은 제외한다.
- 응답 item을
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeCreatorRankingMapperTest" - 기대 결과: DTO/mapper 미구현으로 RED 실패.
- 생성:
-
Task 3.2: API DTO와 mapper 구현
- 생성:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/data/HomeCreatorRankingModels.kt - 생성:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/HomeCreatorRankingMappers.kt - 구현 내용:
data class HomeCreatorRankingResponse(val showRankChange: Boolean, val items: List<HomeCreatorRankingItemResponse>)data class HomeCreatorRankingItemResponse(val rank: Int, val rankChange: Int?, val isNew: Boolean, val creatorId: Long, val nickname: String, val profileImageUrl: String)fun HomeCreatorRankingResponse.toCreatorRankingItems(): List<CreatorRankingItem>rank >= 1filtering,ranksorting,RankingChangeTypemapping,abs(rankChange)amount mappingcreatorId == 0L->isBlocked=true
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeCreatorRankingMapperTest" - 기대 결과: PASS.
- 생성:
-
Task 3.3: API/Repository 작성
- 생성:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/data/HomeCreatorRankingApi.kt - 생성:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/data/HomeCreatorRankingRepository.kt - 구현 내용:
@GET("/api/v2/home/rankings/creators")fun getCreatorRankings(@Header("Authorization") authHeader: String): Single<ApiResponse<HomeCreatorRankingResponse>>- repository는
getCreatorRankings(token: String)으로 API를 위임한다.
- 검증 명령:
./gradlew :app:compileDebugKotlin - 기대 결과: 신규 API/Repository 컴파일 성공.
- 생성:
Phase 4: ViewModel과 DI 등록
-
Task 4.1: UI state와 ViewModel 작성
- 생성:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/HomeCreatorRankingUiState.kt - 생성:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeCreatorRankingViewModel.kt - 구현 내용:
HomeCreatorRankingUiState.LoadingHomeCreatorRankingUiState.Content(val items: List<CreatorRankingItem>)HomeCreatorRankingUiState.EmptyHomeCreatorRankingUiState.Error(val message: String?)rankingStateLiveData,isLoading,toastLiveDataloadCreatorRankings()- 기존
HomeRecommendationViewModel과 동일하게SharedPreferenceManager.token, RxJava scheduler, unknown error toast 패턴 사용
- 검증 명령:
./gradlew :app:compileDebugKotlin - 기대 결과: ViewModel 컴파일 성공.
- 생성:
-
Task 4.2: Koin DI 등록
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt - 구현 내용:
- import 추가:
HomeCreatorRankingApi,HomeCreatorRankingRepository,HomeCreatorRankingViewModel networkModule에single { ApiBuilder().build(get(), HomeCreatorRankingApi::class.java) }repositoryModule에factory { HomeCreatorRankingRepository(get()) }viewModelModule에viewModel { HomeCreatorRankingViewModel(get()) }
- import 추가:
- 검증 명령:
./gradlew :app:compileDebugKotlin - 기대 결과: Koin 등록과 import 컴파일 성공.
- 수정:
Phase 5: 홈 레이아웃과 탭 전환 UI 연결
-
Task 5.1: 홈 레이아웃에 랭킹 목록 추가 RED 테스트 작성
- 수정:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragmentLayoutTest.kt - 추가 테스트:
fragment_v2_main_home.xml에rv_home_creator_rankings가 존재한다.rv_home_creator_rankings는TextTabBarView아래에 직접 constraint 된다.- Capsule Tab bar 관련 view id가 존재하지 않는다.
- 초기 visibility는
GONE이다.
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest.home ranking layout*" - 기대 결과: 신규 RecyclerView 미존재로 RED 실패.
- 수정:
-
Task 5.2:
fragment_v2_main_home.xml에 랭킹 RecyclerView 추가- 수정:
app/src/main/res/layout/fragment_v2_main_home.xml - 구현 내용:
androidx.recyclerview.widget.RecyclerView추가- id:
@+id/rv_home_creator_rankings - width/height:
0dp - top:
@id/text_tab_bar_homebottom - bottom/start/end: parent
android:visibility="gone"android:clipToPadding="false"android:paddingHorizontal="@dimen/spacing_14"android:paddingTop="@dimen/spacing_14"android:paddingBottom="@dimen/spacing_28"
- 제외: Capsule Tab bar view 추가 금지.
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest.home ranking layout*"및./gradlew :app:mergeDebugResources - 기대 결과: PASS.
- 수정:
-
Task 5.3:
HomeMainFragment탭 전환/adapter 연결 테스트 작성- 수정:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragmentLayoutTest.kt - 추가 테스트:
CreatorRankingAdapter.createGridLayoutManager()가 랭킹 RecyclerView에 사용되는 소스 계약랭킹index 선택 시 추천 content는GONE, 랭킹 RecyclerView는VISIBLE추천index 선택 시 추천 content는VISIBLE, 랭킹 RecyclerView는GONEcreatorId=0item은 프로필 이동 intent를 만들지 않는다.creatorId>0item은UserProfileActivity+Constants.EXTRA_USER_IDintent를 만든다.
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest.home ranking*" - 기대 결과: Fragment 연결 미구현으로 RED 실패.
- 수정:
-
Task 5.4:
HomeMainFragment에 랭킹 탭 content 연결- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/HomeMainFragment.kt - 구현 내용:
private val homeCreatorRankingViewModel: HomeCreatorRankingViewModel by viewModel()private val creatorRankingAdapter = CreatorRankingAdapter { openCreatorRankingProfile(it) }rvHomeCreatorRankings.layoutManager = CreatorRankingAdapter.createGridLayoutManager(requireContext())rvHomeCreatorRankings.adapter = creatorRankingAdapter- tab index 상수:
HOME_TAB_RECOMMENDATION = 0,HOME_TAB_RANKING = 1,HOME_TAB_FOLLOWING = 2 setOnTabSelectedListener에서 추천/랭킹만 content 전환 처리한다.- 랭킹 최초 선택 시
homeCreatorRankingViewModel.loadCreatorRankings()를 호출한다. HomeCreatorRankingUiState.Content이면creatorRankingAdapter.submitItems(items)Empty/Error이면 빈 목록을 submit한다.openCreatorRankingProfile(item)은item.creatorId > 0일 때만UserProfileActivity를Constants.EXTRA_USER_ID와 함께 실행한다.- 별도 analytics/logging은 추가하지 않는다.
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest.home ranking*"및./gradlew :app:compileDebugKotlin - 기대 결과: PASS.
- 수정:
Phase 6: 통합 검증과 문서 기록
-
Task 6.1: targeted test 실행
- 실행:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*"./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeCreatorRankingMapperTest"./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest"
- 기대 결과: 모두
BUILD SUCCESSFUL. - 실패 시: 실패 원인을 이 문서의 Verification Log에 누적하고, 수정 전 관련 task 체크박스를 되돌린다.
- 실행:
-
Task 6.2: compile/resource/lint 검증
- 실행:
./gradlew :app:mergeDebugResources./gradlew :app:compileDebugKotlin./gradlew :app:ktlintCheck
- 기대 결과: 모두
BUILD SUCCESSFUL. - 참고: 기존
.editorconfig disabled_rulesdeprecation warning은 신규 실패가 아니면 별도 수정하지 않는다.
- 실행:
-
Task 6.3: 최종 문서 검증 기록 누적
- 수정:
docs/20260608_크리에이터_랭킹_페이지/plan-task.md - 수정:
docs/20260608_크리에이터_랭킹_페이지/prd.md - 구현 내용:
- 실행한 명령, 성공/실패 결과, 실패 시 원인과 보완 내용을 Verification Log에 누적한다.
- 기존 Verification Log는 삭제하거나 덮어쓰지 않는다.
- 검증: PRD와 plan-task의 완료 상태와 실제 구현 상태가 일치한다.
- 수정:
Phase 7: 순위 텍스트 고정 박스 정렬 보정
-
Task 7.1: 순위 텍스트 박스 정렬 RED 테스트 추가
- 수정:
app/src/test/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingAdapterLayoutTest.kt - 구현 내용:
- Large, Compact medium, Compact small, Horizontal variant의 순위 영역 박스 크기/위치와 내부 중앙 정렬을 검증한다.
- Figma margin 값을 임의로 추가하지 않고 기존 박스 크기 안의 정렬만 검증한다.
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingAdapterLayoutTest" - 기대 결과: production 수정 전 중앙 정렬 assertion이 실패한다.
- 수정:
-
Task 7.2: 순위 텍스트 박스 내부 정렬 보정
- 수정:
app/src/main/res/layout/view_creator_ranking_large_card.xml - 수정:
app/src/main/res/layout/view_creator_ranking_compact_card.xml - 수정:
app/src/main/res/layout/view_creator_ranking_horizontal_card.xml - 구현 내용:
- 기존 Kotlin 코드의 고정 박스 크기/left/top 계산은 유지한다.
- 순위 TextView가 박스 내부에서 중앙 정렬되도록 최소 속성만 추가한다.
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingAdapterLayoutTest" - 기대 결과: RED 테스트가
BUILD SUCCESSFUL로 전환된다.
- 수정:
-
Task 7.3: 후속 검증과 문서 기록 누적
- 실행:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*"./gradlew :app:mergeDebugResources
- 수정:
docs/20260608_크리에이터_랭킹_페이지/prd.md - 수정:
docs/20260608_크리에이터_랭킹_페이지/plan-task.md - 기대 결과: 모두
BUILD SUCCESSFUL, Verification Log 누적.
- 실행:
Phase 8: Figma 최신 순위 영역 수치 보정
-
Task 8.1: 순위 영역 최신 수치 RED 테스트 추가
- 수정:
app/src/test/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingAdapterLayoutTest.kt - 구현 내용:
- Figma
24:5658기준 1위, 27위, 810위, 11위 이후 순위 숫자 박스 크기와 rank-num 위치를 검증한다. - rank-num 상승/하락/유지/New 표시의 기존 노출 정책은 유지한다.
- Figma
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingAdapterLayoutTest" - 기대 결과: production 수정 전 1위/8
10위 순위 박스와 1위/810위 rank-num 위치 assertion이 실패한다.
- 수정:
-
Task 8.2: 순위 숫자 박스와 rank-num 위치 보정
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingLargeCardView.kt - 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingCompactCardView.kt - 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingHorizontalCardView.kt - 구현 내용:
- 1위 순위 숫자 박스는
86x116, rank-num은left=20,top=116기준으로 맞춘다. - 2~7위 순위 숫자 박스는
56x70, rank-num은left=10,top=70기준으로 맞춘다. - 8~10위 순위 숫자 박스는
52x50,left=0, rank-num은left=10,top=50기준으로 맞춘다. - 11위 이후 순위 텍스트는 rank group 내부에서
48x52기준으로 맞춘다.
- 1위 순위 숫자 박스는
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingAdapterLayoutTest" - 기대 결과: RED 테스트가
BUILD SUCCESSFUL로 전환된다.
- 수정:
-
Task 8.3: 후속 검증과 문서 기록 누적
- 실행:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*"./gradlew :app:mergeDebugResources./gradlew :app:ktlintCheck
- 수정:
docs/20260608_크리에이터_랭킹_페이지/prd.md - 수정:
docs/20260608_크리에이터_랭킹_페이지/plan-task.md - 기대 결과: 모두
BUILD SUCCESSFUL, Verification Log 누적.
- 실행:
Phase 9: rank-num 간격 시각 보정
-
Task 9.1: rank 텍스트 하단 보정 회귀 테스트 추가
- 수정:
app/src/test/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingAdapterLayoutTest.kt - 구현 내용:
- Large, Compact medium, Compact small, Horizontal variant의 순위
TextView가includeFontPadding=false를 유지하는지 검증한다. - 순위
TextView에 variant별 하단 padding이 적용되어 Pattaya glyph가 rank-num 영역에 붙어 보이지 않도록 검증한다.
- Large, Compact medium, Compact small, Horizontal variant의 순위
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingAdapterLayoutTest" - 기대 결과: production 수정 전 padding assertion이 실패한다.
- 수정:
-
Task 9.2: rank 텍스트 내부 하단 padding 보정
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingLargeCardView.kt - 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingCompactCardView.kt - 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingHorizontalCardView.kt - 구현 내용:
- 기존 Figma 좌표값과 rank-num top/left는 변경하지 않는다.
- 순위 숫자
TextView내부에 scale 기반 하단 padding을 적용해 폰트 glyph가 위쪽으로 보정되도록 한다.
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingAdapterLayoutTest" - 기대 결과: RED 테스트가
BUILD SUCCESSFUL로 전환된다.
- 수정:
-
Task 9.3: 후속 검증과 문서 기록 누적
- 실행:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*"./gradlew :app:mergeDebugResources./gradlew :app:ktlintCheck
- 수정:
docs/20260608_크리에이터_랭킹_페이지/prd.md - 수정:
docs/20260608_크리에이터_랭킹_페이지/plan-task.md - 기대 결과: 모두
BUILD SUCCESSFUL, Verification Log 누적.
- 실행:
Phase 10: 메인 홈 랭킹 탭 Figma 최신 시각 보정
-
Task 10.1: Figma 최신 텍스트 크기와 item 간격 RED 테스트 추가
- 수정:
app/src/test/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingAdapterLayoutTest.kt - 수정:
app/src/test/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingLayoutCalculatorTest.kt - 구현 내용:
- Figma
24:5668기준 3열 Compact 순위36sp, 닉네임14sp, rank-num 숫자14sp를 검증한다. - Figma
24:5661기준 2열 Compact 순위54sp, 닉네임22sp, rank-num 숫자16sp를 회귀 검증한다. - Figma
24:5670기준 11위 이후 Horizontal rank group 내부 세로 배치와 New/순위 변동 표시를 검증한다. - 랭킹 item 간격
8dp기준으로 2열/3열 item 폭 계산을 검증한다.
- Figma
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingAdapterLayoutTest" - 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingLayoutCalculatorTest" - 기대 결과: production 수정 전 3열 Compact 순위/변동 텍스트 크기와 item 간격 assertion이 실패한다.
- 검증 기록: production 수정 전
CreatorRankingAdapterLayoutTest를 실행해 3열 Compact 순위 텍스트 크기 assertion 실패를 확인했다.CreatorRankingLayoutCalculatorTest는 계산기에8dp를 직접 전달하는 순수 계산 테스트라 기존 코드에서도 통과했으며, Adapter의 실제 간격 상수는 Task 10.2에서 함께 보정했다.
- 수정:
-
Task 10.2: Compact 텍스트 크기와 랭킹 item 간격 보정
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingCompactCardView.kt - 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingAdapter.kt - 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt - 구현 내용:
- 3열 Compact 순위 텍스트를
36sp, rank-num 숫자를14sp로 보정한다. - 2열 Compact 순위
54sp, 닉네임22sp, rank-num 숫자16sp는 유지한다. - 랭킹 item 폭 계산 기준과 실제 RecyclerView item decoration 간격을
8dp로 보정한다. - 11위 이후 Horizontal rank group의 기존 세로 배치와 New badge 크기는 유지한다.
- 3열 Compact 순위 텍스트를
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingAdapterLayoutTest" - 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingLayoutCalculatorTest" - 기대 결과: RED 테스트가
BUILD SUCCESSFUL로 전환된다. - 검증 기록:
CreatorRankingCompactCardView에서 3열 Compact 순위36sp, rank-num 숫자14sp를 적용하고 2열 Compact rank-num 숫자16sp를 명시 유지했다.CreatorRankingAdapter의 폭 계산 상수를8dp로 보정하고, 실제GridLayoutManager배치에서도 인접 item offset 합이8dp가 되도록 전용CreatorRankingItemDecoration을 추가했다.HomeMainFragment에는 중복 추가 방지 조건과 함께 decoration을 연결했다. 병렬 Gradle 실행 중 Kotlin incremental cache 충돌이 발생해./gradlew --stop,./gradlew clean후 순차 재실행했고,CreatorRankingAdapterLayoutTest,CreatorRankingLayoutCalculatorTest,HomeMainFragmentLayoutTest.home ranking fragment wires adapter and grid layout manager가 모두BUILD SUCCESSFUL로 통과했다.
- 수정:
-
Task 10.3: 후속 검증과 문서 기록 누적
- 실행:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*"./gradlew :app:mergeDebugResources./gradlew :app:compileDebugKotlin./gradlew :app:ktlintCheck
- 수정:
docs/20260608_크리에이터_랭킹_페이지/prd.md - 수정:
docs/20260608_크리에이터_랭킹_페이지/plan-task.md - 기대 결과: 신규 변경 관련 테스트와 빌드가 통과하고, ktlint 기존 전역 위반이 있으면 Verification Log에 누적한다.
- 검증 기록:
creatorranking.*,mergeDebugResources,compileDebugKotlin,ktlintCheck,git diff --check를 실행했다. 최초ktlintCheck에서 변경 파일인CreatorRankingAdapter.kt긴 줄 1건과 기존 전역 위반이 함께 보고되어 변경 파일 줄바꿈만 수정했고, 이후ktlintCheck가BUILD SUCCESSFUL로 통과했다.
- 실행:
Phase 11: rank-area wrap_content 계약 보정
-
Task 11.1: PRD/계획 문서에 후속 계약 반영
- 수정:
docs/20260608_크리에이터_랭킹_페이지/prd.md - 수정:
docs/20260608_크리에이터_랭킹_페이지/plan-task.md - 구현 내용:
- 순위 숫자
TextView의 XML/Kotlin width/height는 모든 variant에서wrap_content를 유지한다. - Kotlin은 순위 숫자/닉네임/rank-num 텍스트 크기와 rank area의 spacing/margin만 조정한다.
- 순위 숫자와 rank-num은 Large/Compact/Horizontal의 rank area 안에서 함께 가운데 정렬한다.
- 순위 숫자
- 검증: 구현 전 문서에 Phase 11 후속 범위와 성공 기준을 한국어로 기록한다.
- 검증 기록: 구현 전 PRD와 plan-task에 rank
TextViewwrap_content유지, Kotlin의 텍스트 크기/spacing/margin 조정 범위, rank와 rank-num의 rank area 중앙 정렬 계약을 기록했다.
- 수정:
-
Task 11.2: rank-area 계약 테스트 갱신
- 수정:
app/src/test/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingAdapterLayoutTest.kt - 구현 내용:
- Large, Compact medium, Compact small, Horizontal의
tv_creator_ranking_rankwidth/height가ViewGroup.LayoutParams.WRAP_CONTENT인지 검증한다. - 순위
TextView의Gravity.CENTER,includeFontPadding=false계약을 유지한다. - Compact medium 순위
54sp/닉네임22sp/rank-num16sp, Compact small 순위36sp/닉네임14sp/rank-num14sp계약을 유지한다. - Horizontal은
ll_creator_ranking_rank_group이LinearLayout.VERTICAL,Gravity.CENTER, rank childwrap_content를 유지하는지 검증한다. - Large/Compact는 rank group 안에서 순위와 rank-num이 함께 중앙 정렬되는지 검증한다.
- Large, Compact medium, Compact small, Horizontal의
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingAdapterLayoutTest" - 기대 결과: production 수정 전 고정 width/height assertion 변경에 따라 실패한다.
- 검증 기록: production 수정 전 실행 결과 Large/Compact는
ll_creator_ranking_rank_group미구현으로 실패했고, Horizontal은 rankTextView고정 layoutParams 때문에wrap_contentassertion이 실패했다.
- 수정:
-
Task 11.3: Large/Compact/Horizontal rank-area 최소 구현
- 수정:
app/src/main/res/layout/view_creator_ranking_large_card.xml - 수정:
app/src/main/res/layout/view_creator_ranking_compact_card.xml - 수정:
app/src/main/res/layout/view_creator_ranking_horizontal_card.xml - 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingLargeCardView.kt - 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingCompactCardView.kt - 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingHorizontalCardView.kt - 구현 내용:
- Large/Compact는 순위 숫자와
ll_creator_ranking_delta를 rank group으로 묶고 group을 rank area 중앙 정렬 기준으로 배치한다. - Horizontal은 기존 rank group 세로/중앙 정렬을 유지하되 rank
TextView고정 width/height 설정을 제거한다. - Kotlin에서
tv_creator_ranking_rank에 고정 width/height를 설정하지 않고, 텍스트 크기와 rank/delta spacing만 조정한다.
- Large/Compact는 순위 숫자와
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingAdapterLayoutTest" - 기대 결과: 갱신된 rank-area 계약 테스트가
BUILD SUCCESSFUL로 통과한다. - 검증 기록: Large/Compact XML에 rank group을 추가해 순위 숫자와
ll_creator_ranking_delta를 함께 세로 중앙 정렬했고, Large/Compact/Horizontal Kotlin에서 rankTextView고정 width/height 설정을 제거했다. 동일CreatorRankingAdapterLayoutTest가BUILD SUCCESSFUL로 통과했다.
- 수정:
-
Task 11.4: 후속 검증과 문서 기록 누적
- 실행:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingAdapterLayoutTest"./gradlew :app:mergeDebugResources./gradlew :app:compileDebugKotlin
- 수정:
docs/20260608_크리에이터_랭킹_페이지/prd.md - 수정:
docs/20260608_크리에이터_랭킹_페이지/plan-task.md - 기대 결과: 모두
BUILD SUCCESSFUL, Verification Log에 한국어로 결과 누적. - 검증 기록:
CreatorRankingAdapterLayoutTest,mergeDebugResources,compileDebugKotlin이 모두BUILD SUCCESSFUL로 통과했다.rg로 Kotlin 내 rankTextView고정 sizing 잔여 없음과 XMLwrap_content유지를 확인했다.
- 실행:
Phase 12: 8~10위 Compact small 순위 표시 보정
-
Task 12.1: 8~10위 Compact small 문제 원인 확인과 문서 반영
- 수정:
docs/20260608_크리에이터_랭킹_페이지/prd.md - 수정:
docs/20260608_크리에이터_랭킹_페이지/plan-task.md - 구현 내용:
tv_creator_ranking_rank자체는wrap_content지만, Compact small parentll_creator_ranking_rank_group폭이52 * scale로 고정되어10표시가 답답해질 수 있음을 기록한다.- 8~10위 Compact small rank group은
wrap_content로 유지한다. - 8~10위 Compact small rank와 rank-num 간격은 Kotlin margin으로 더 좁힌다.
- 8~10위 Compact small 닉네임은 14sp보다 작게 표시한다.
- 검증 기록: 직접 파일 확인과 병렬 explore 결과 모두
CreatorRankingCompactCardView.positionSmall()의 rank group 고정 폭을 핵심 원인으로 지목했다. 구현 전 PRD와 plan-task에 Phase 12 범위와 성공 기준을 반영했다.
- 수정:
-
Task 12.2: Compact small rank=10/parent wrap_content RED 테스트 갱신
- 수정:
app/src/test/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingAdapterLayoutTest.kt - 구현 내용:
- 실제 3열 카드 폭에 가까운
119x119조건에서rank=10bind 후 순위 텍스트가10인지 검증한다. - Compact small rank group width가
WRAP_CONTENT인지 검증한다. - Compact small 닉네임 텍스트 크기가
13sp인지 검증한다. - Compact small rank-num top margin이 음수 보정되어 rank와 rank-num 간격이 줄어드는지 검증한다.
- 실제 3열 카드 폭에 가까운
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingAdapterLayoutTest" - 기대 결과: production 수정 전 rank group fixed width, 닉네임 14sp, rank-num margin 미보정으로 실패한다.
- 검증 기록: production 수정 전 실행해 Compact small rank group width assertion 실패를 확인했다.
- 수정:
-
Task 12.3: Compact small rank group/간격/닉네임 최소 보정
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingCompactCardView.kt - 구현 내용:
- Compact small에서 rank group width를
WRAP_CONTENT로 변경한다. - Compact small 닉네임 텍스트 크기를
13sp로 줄인다. - Compact small rank-num top margin을 scale 기반 음수 margin으로 설정해 rank와 rank-num 간격을 좁힌다.
- Large, Compact medium, Horizontal, API/ViewModel/Adapter 동작은 변경하지 않는다.
- Compact small에서 rank group width를
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingAdapterLayoutTest" - 기대 결과: 갱신된 테스트가
BUILD SUCCESSFUL로 통과한다. - 검증 기록:
CreatorRankingCompactCardView.positionSmall()에서 rank group width를WRAP_CONTENT로 변경하고, 닉네임을13sp로 줄였으며, rank-num top margin을-4 * scale로 보정했다. 동일 테스트가BUILD SUCCESSFUL로 통과했다.
- 수정:
-
Task 12.4: 후속 검증과 문서 기록 누적
- 실행:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingAdapterLayoutTest"./gradlew :app:mergeDebugResources./gradlew :app:compileDebugKotlin./gradlew :app:ktlintCheck
- 수정:
docs/20260608_크리에이터_랭킹_페이지/prd.md - 수정:
docs/20260608_크리에이터_랭킹_페이지/plan-task.md - 기대 결과: 모두
BUILD SUCCESSFUL, Verification Log에 한국어로 결과 누적. - 검증 기록:
CreatorRankingAdapterLayoutTest,mergeDebugResources,compileDebugKotlin,ktlintCheck,git diff --check가 모두 통과했다. 병렬 Gradle 실행 중 Kotlin incremental cache 충돌이 있었으나./gradlew --stop후 순차 재실행으로 통과했다.
- 실행:
Phase 13: Rewrite 문서 요구사항 정리
-
Task 13.1: PRD에 rewrite scope와 제약 추가
- 수정:
docs/20260608_크리에이터_랭킹_페이지/prd.md - 구현 내용:
- 크리에이터 랭킹 view를 새로 작성하는 후속 범위를 추가한다.
- 신규 view는
ConstraintLayout을 사용하고FrameLayout을 사용하지 않는다고 명시한다. - adapter view type은 ranks
1~10, ranks11~20두 개만 둔다고 명시한다. rank > 20은 이번 문서 갱신에서 mapper/API 동작을 바꾸지 않고, 별도 요구 전까지 현재 lower-row 처리를 유지할 수 있다고 기록한다.
- 검증: PRD에 production code 변경 없이 rewrite 요구사항만 반영되어 있다.
- 수정:
-
Task 13.2: plan-task에 Phase 13 이후 구현 계획 추가
- 수정:
docs/20260608_크리에이터_랭킹_페이지/plan-task.md - 구현 내용:
- Phase 13 이후를 unchecked 상태로 추가한다.
- 단계 순서는 docs, logic-only test rewrite, placement/text-style logic, adapter two-view rewrite, ConstraintLayout view rewrite, obsolete FrameLayout cleanup, home integration cleanup, final validation이다.
- 기존 Verification Log는 삭제하거나 덮어쓰지 않고 새 기록만 추가한다.
- 검증: Phase 12 이후에 Phase 13 이상이 이어지고 모든 신규 task가
- [ ]상태다.
- 수정:
Phase 14: Logic-only 테스트 재작성
-
Task 14.1: 기존 UI layout/visual 테스트 제거 대상 분류
- 확인:
app/src/test/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingAdapterLayoutTest.kt - 확인:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragmentLayoutTest.kt - 구현 내용:
- view size, margin, padding, constraints,
TextViewdimensions, inflated layout params, visibility attributes 검증을 제거 대상으로 분류한다. - placement, text-style model, mapper, delta presentation, item behavior 검증은 logic contract 테스트로 유지하거나 이동한다.
- view size, margin, padding, constraints,
- 검증: 후속 테스트 작업에서 삭제할 UI layout/visual assertion과 유지할 logic assertion이 구분되어 있다.
- 확인:
-
Task 14.2: logic contract 테스트로 재작성
- 수정:
app/src/test/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingItemTest.kt - 수정:
app/src/test/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingLayoutCalculatorTest.kt - 수정 또는 생성:
app/src/test/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingPlacementTest.kt - 수정 또는 생성:
app/src/test/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingTextStyleTest.kt - 구현 내용:
- ranks
1~10, ranks11~20구분을 순수 로직으로 검증한다. - 1 item row, 2 item row, 3 item row, lower-row text style model을 검증한다.
CreatorRankingDeltaPresentation의 기존NEW, 상승, 하락, 유지 의미를 유지한다.HomeCreatorRankingMappers의 기존 rank change 및showRankChange의미를 유지한다.
- ranks
- 제외:
- 실제 view 크기, margin, padding, constraints, inflated layout params, visibility attributes assertion 추가 금지.
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*" - 기대 결과: logic contract 테스트만 남고 UI layout/visual test는 없다.
- 수정:
Phase 15: Placement와 text-style 로직 작성
-
Task 15.1: rank placement model 작성
- 수정 또는 생성:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingPlacement.kt - 구현 내용:
- adapter position과 rank를 기준으로 1 item row, 2 item row, 3 item row, lower row를 결정한다.
- ranks
1~10은 상위 view type 안에서 row basis를 결정한다. - ranks
11~20은 lower-row basis를 사용한다. rank > 20은 mapper/API 동작 변경 없이 현재 lower-row 처리와 호환되게 둔다.
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingPlacementTest" - 기대 결과: placement logic contract가 통과한다.
- 수정 또는 생성:
-
Task 15.2: text-style model 작성
- 수정 또는 생성:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingTextStyle.kt - 구현 내용:
- 1 item row rank/name/delta
96sp/32sp/16sp - 2 item row rank/name/delta
54sp/22sp/16sp - 3 item row rank/name/delta
36sp/14sp/14sp - ranks
11~20lower-row rank/name40sp/18sp
- 1 item row rank/name/delta
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingTextStyleTest" - 기대 결과: text-style logic contract가 통과한다.
- 수정 또는 생성:
Phase 16: Adapter two-view rewrite
-
Task 16.1: adapter view type을 두 개로 축소
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingAdapter.kt - 구현 내용:
- view type은 ranks
1~10, ranks11~20두 개만 둔다. - ranks
1~10view holder는 placement model로 1 item row, 2 item row, 3 item row 표현을 선택한다. - ranks
11~20view holder는 lower-row 표현을 사용한다. rank > 20은 별도 mapper/API 변경 없이 현재 lower-row 처리와 호환되게 둔다.
- view type은 ranks
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*" - 기대 결과: adapter view type logic 테스트가 통과한다.
- 수정:
-
Task 16.2: adapter item behavior 유지
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingAdapter.kt - 구현 내용:
CreatorRankingItem.isTouchable와 click listener 동작을 유지한다.showRankChange=false의미는 delta presentation 적용 경로에서 유지한다.creatorId=0item 클릭 불가 계약을 유지한다.
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingItemTest" - 기대 결과: 기존 item behavior가 회귀하지 않는다.
- 수정:
Phase 17: ConstraintLayout view rewrite
-
Task 17.1: ranks 1~10 view를 ConstraintLayout으로 작성
- 수정 또는 생성:
app/src/main/res/layout/view_creator_ranking_top_card.xml - 수정 또는 생성:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingTopCardView.kt - 구현 내용:
- root는
ConstraintLayout을 사용한다. FrameLayout은 사용하지 않는다.- Figma
24:5659,24:5660,24:5668기준으로 1 item row, 2 item row, 3 item row 표현을 처리한다. - 고정 width/height를 layout sizing 목적으로 새로 도입하지 않는다.
wrap_content,match_parent, margins, padding, constraints, match-constraint, 측정된 available width, aspect handling을 필요에 따라 사용한다.
- root는
- 검증 명령:
./gradlew :app:mergeDebugResources - 기대 결과: 신규 XML resource가 빌드된다.
- 수정 또는 생성:
-
Task 17.2: ranks 11~20 view를 ConstraintLayout으로 작성
- 수정 또는 생성:
app/src/main/res/layout/view_creator_ranking_lower_row.xml - 수정 또는 생성:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingLowerRowView.kt - 구현 내용:
- root는
ConstraintLayout을 사용한다. FrameLayout은 사용하지 않는다.- Figma
24:5670lower-row basis를 사용한다. - rank
40sp, name18sp를 적용한다. - rank change와
NEW표시 의미는CreatorRankingDeltaPresentation경로를 유지한다.
- root는
- 검증 명령:
./gradlew :app:mergeDebugResources - 기대 결과: lower-row XML resource가 빌드된다.
- 수정 또는 생성:
Phase 18: Obsolete FrameLayout cleanup
-
Task 18.1: obsolete FrameLayout 기반 view 제거
- 수정 또는 삭제: 기존
creatorrankinglegacy card view XML/Kotlin 중 더 이상 참조되지 않는 파일 - 구현 내용:
- 새 adapter가 참조하지 않는
FrameLayout기반 card view 파일을 제거한다. - 참조가 남은 legacy 파일은 삭제하지 않고 호출 경로를 먼저 끊는다.
- 리소스 id, binding import, unused import 중 이번 변경으로 생긴 잔여만 정리한다.
- 새 adapter가 참조하지 않는
- 검증 명령:
./gradlew :app:compileDebugKotlin - 기대 결과: obsolete view 제거 후 컴파일이 통과한다.
- 수정 또는 삭제: 기존
-
Task 18.2: FrameLayout 신규 사용 금지 확인
- 확인:
app/src/main/res/layout/ - 확인:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/ - 구현 내용:
- 후속 rewrite로 추가한 creator ranking view에
FrameLayout이 없는지 확인한다. - production code 또는 tests에 불필요한 obsolete view 참조가 남지 않았는지 확인한다.
- 후속 rewrite로 추가한 creator ranking view에
- 검증: 검색 결과에서 신규 creator ranking view의
FrameLayout사용이 없다.
- 확인:
Phase 19: Home integration cleanup
-
Task 19.1: 홈 랭킹 연결부 정리
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/HomeMainFragment.kt - 구현 내용:
- 새 adapter와 view holder 생성 경로를 연결한다.
- 기존
HomeCreatorRankingMappers의미를 바꾸지 않는다. - 기존 tab 전환, 최초 로드, empty/error 처리, profile 이동 guard를 유지한다.
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*" - 기대 결과: 홈 랭킹 mapper와 item behavior가 회귀하지 않는다.
- 검증 기록:
fragment_v2_main_home.xml의tools:listitem을 새view_creator_ranking_lower_row로 갱신했고,HomeMainFragment는 기존CreatorRankingAdapter, tab 전환, 최초 로드, empty/error 처리, profile 이동 guard 경로를 유지했다. 랭킹 관련 layout 속성 assertion은 logic/source contract 중심으로 축소했다../gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*"가BUILD SUCCESSFUL로 통과했다.
- 수정:
-
Task 19.2: home integration 문서 기록 누적
- 수정:
docs/20260608_크리에이터_랭킹_페이지/plan-task.md - 수정:
docs/20260608_크리에이터_랭킹_페이지/prd.md - 구현 내용:
- home integration cleanup에서 유지한 mapper/API, profile 이동, rank change 의미를 Verification Log에 누적한다.
- 기존 Verification Log는 삭제하거나 덮어쓰지 않는다.
- 검증: 문서 기록과 실제 구현 범위가 일치한다.
- 검증 기록: home integration cleanup에서 mapper/API, profile 이동, rank change 의미를 변경하지 않았고, 검증 결과를 Verification Log에 누적했다.
- 수정:
Phase 20: Final validation
-
Task 20.1: logic-only targeted test 실행
- 실행:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*"./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*"
- 기대 결과: logic contract 테스트가
BUILD SUCCESSFUL로 통과한다. - 제외: UI layout/visual 속성 검증 테스트를 새로 작성하거나 실행 대상으로 추가하지 않는다.
- 검증 기록:
./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*",./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*",./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeCreatorRankingMapperTest"가 모두BUILD SUCCESSFUL로 통과했다.
- 실행:
-
Task 20.2: build와 style 검증
- 실행:
./gradlew :app:mergeDebugResources./gradlew :app:compileDebugKotlin./gradlew :app:ktlintCheck
- 기대 결과: 모두
BUILD SUCCESSFUL. - 참고: 기존 전역 경고나 기존 전역 위반이 있으면 신규 변경과 분리해 Verification Log에 기록한다.
- 검증 기록:
./gradlew :app:mergeDebugResources,./gradlew --no-daemon :app:compileDebugKotlin,./gradlew --no-daemon :app:ktlintCheck,git diff --check가 모두 통과했다. 병렬 Gradle 실행 중 Kotlin incremental cache 삭제/backup 오류와 timeout이 발생했으나./gradlew --stop및--no-daemon순차 재실행으로 통과했다. Gradle deprecated feature warning과 기존 Kotlin warning은 신규 변경과 무관한 기존 경고로 보고 수정하지 않았다.
- 실행:
-
Task 20.3: 최종 문서 검증 기록 누적
- 수정:
docs/20260608_크리에이터_랭킹_페이지/plan-task.md - 수정:
docs/20260608_크리에이터_랭킹_페이지/prd.md - 구현 내용:
- 실행한 검증 명령과 결과를 Verification Log에 누적한다.
ConstraintLayout사용,FrameLayout미사용, two-view adapter, logic-only test 정책 준수 여부를 기록한다.- 기존 Verification Log는 삭제하거나 덮어쓰지 않는다.
- 검증: Phase 13~20의 체크 상태, 실제 구현 상태, 최종 검증 기록이 일치한다.
- 검증 기록: Phase 13~20 체크 상태와 실제 구현/검증 상태를 맞추고,
ConstraintLayout사용,FrameLayout미사용, two-view adapter, logic-only test 정책 준수 결과를 Verification Log에 누적했다.
- 수정:
Phase 21: 상위 랭킹 카드 margin 보정
-
Task 21.1: margin-only 후속 범위 문서화
- 수정:
docs/20260608_크리에이터_랭킹_페이지/plan-task.md - 구현 내용:
- ranks
1~10top-card의 닉네임 margin과 순위 left margin만 보정한다. - rank
1닉네임 margin은 좌/우20dp, 아래24dp로 적용한다. - ranks
2~10닉네임 margin은 좌/우/아래10dp로 적용한다. - 순위 left margin은 rank
110dp, ranks2~78dp, ranks8~106dp로 적용한다. - 이번 단계에서는 순위 텍스트와 delta 사이 간격, ranks
11+lower-row delta 동작은 변경하지 않는다.
- ranks
- 검증: 후속 구현 범위와 제외 범위가 문서에 명확히 기록되어 있다.
- 수정:
-
Task 21.2: top-card margin policy logic 추가
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingTopCardMargin.kt - 수정:
app/src/test/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingTopCardMarginTest.kt - 구현 내용:
- rank 구간별 닉네임 좌/우/아래 margin과 rank group start margin을 순수 로직으로 분리한다.
- ranks
1,2~7,8~10값을 검증한다. - ranks
11+와 delta spacing은 테스트 대상에 포함하지 않는다.
- 검증: margin policy 테스트가 요청 수치를 검증한다.
- 수정:
-
Task 21.3: top-card view에 margin policy 적용
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingTopCardView.kt - 구현 내용:
CreatorRankingTopCardView.bind()에서 rank별 margin policy를ll_creator_ranking_rank_group과tv_creator_ranking_name에 적용한다.CreatorRankingDeltaPresentation, delta icon margin, 순위 텍스트와 delta 사이 간격,CreatorRankingLowerRowView는 변경하지 않는다.
- 검증: top-card margin policy가 bind 시 적용되고 lower-row/delta spacing 변경이 없다.
- 수정:
-
Task 21.4: 후속 검증과 문서 기록 누적
- 수정:
docs/20260608_크리에이터_랭킹_페이지/plan-task.md - 실행:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*"./gradlew :app:mergeDebugResources./gradlew :app:compileDebugKotlin./gradlew :app:ktlintCheckgit diff --check
- 기대 결과: 모두
BUILD SUCCESSFUL또는 출력 없음. - 검증 기록: 실행 결과와 lower-row/delta spacing 제외 여부를 Verification Log에 누적한다.
- 수정:
Phase 22: 하위 랭킹 delta 표시 보정
-
Task 22.1: lower-row delta 표시 보정 범위 문서화
- 수정:
docs/20260608_크리에이터_랭킹_페이지/plan-task.md - 구현 내용:
- ranks
1~10과 ranks11~20의 delta 표시 정책은 동일하게showRankChange를 따른다. - ranks
11~20에서만 delta가 보이지 않는 문제는 mapper/API 의미 변경이 아니라 lower-row layout/measurement clipping 가능성으로 처리한다. - top-card rank/delta/name 및 lower-row rank/delta/name
TextView는 이미includeFontPadding=false이므로, 이번 단계에서는 top-card 순위 텍스트와 delta 사이 간격을 변경하지 않는다. - 3열 grid의 delta amount text size는
14sp이고,NEW표시는 text가 아니라36dp x 23dpimage presentation임을 확인한다.
- ranks
- 검증: 구현 범위가 lower-row delta visibility 보정으로 제한되고 API/mapper/top-card spacing 변경이 제외되어 있다.
- 수정:
-
Task 22.2: lower-row measurement clipping 최소 보정
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingLowerRowView.kt - 구현 내용:
- lower-row의 기존 Figma 비율 height를 기본값으로 유지하되, rank group content가 잘리지 않도록 필요한 최소 height를 함께 고려한다.
showRankChange=false숨김 의미와CreatorRankingDeltaPresentation적용 의미는 변경하지 않는다.HomeCreatorRankingMappers, API DTO,CreatorRankingTopCardView, top-card XML은 변경하지 않는다.
- 검증: ranks
11~20lower-row에서 delta group이 clipping되지 않도록 측정된다.
- 수정:
-
Task 22.3: 후속 검증과 문서 기록 누적
- 수정:
docs/20260608_크리에이터_랭킹_페이지/plan-task.md - 실행:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*"./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*"./gradlew :app:mergeDebugResources./gradlew :app:compileDebugKotlin./gradlew :app:ktlintCheckgit diff --check
- 기대 결과: 모두
BUILD SUCCESSFUL또는 출력 없음. - 검증 기록: lower-row delta visibility 보정, top-card spacing 미변경, 3열 delta text/NEW image 차이를 Verification Log에 누적한다.
- 수정:
Phase 23: 상위 랭킹 순위 텍스트 margin 적용 대상 보정
-
Task 23.1: rank text margin 대상 보정 범위 문서화
- 수정:
docs/20260608_크리에이터_랭킹_페이지/plan-task.md - 구현 내용:
- Phase 21의 순위 left margin은 rank/delta를 감싸는
ll_creator_ranking_rank_group이 아니라tv_creator_ranking_rank에만 적용한다. - rank delta 위치와 rank group 자체 위치는 변경하지 않는다.
- 닉네임 margin 정책은 기존 Phase 21 값을 유지한다.
- Phase 21의 순위 left margin은 rank/delta를 감싸는
- 검증: 보정 범위가 rank text start margin 적용 대상으로 제한되어 있다.
- 수정:
-
Task 23.2: top-card margin policy와 적용 대상 보정
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingTopCardMargin.kt - 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingTopCardView.kt - 수정:
app/src/test/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingTopCardMarginTest.kt - 구현 내용:
- margin policy 명칭을 rank group start가 아닌 rank text start 의미로 정리한다.
CreatorRankingTopCardView.bind()에서tv_creator_ranking_rank의MarginLayoutParams.marginStart만 rank별 값으로 적용한다.ll_creator_ranking_rank_group,ll_creator_ranking_delta,CreatorRankingDeltaPresentation은 변경하지 않는다.
- 검증: rank별 값은 기존 Phase 21 수치를 유지하고 적용 대상만 rank text로 제한된다.
- 수정:
-
Task 23.3: 후속 검증과 문서 기록 누적
- 수정:
docs/20260608_크리에이터_랭킹_페이지/plan-task.md - 실행:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*"./gradlew :app:mergeDebugResources./gradlew :app:compileDebugKotlin./gradlew :app:ktlintCheckgit diff --check
- 기대 결과: 모두
BUILD SUCCESSFUL또는 출력 없음. - 검증 기록: rank text margin 적용 대상 보정 결과를 Verification Log에 누적한다.
- 수정:
Phase 24: rankTextStartDp 변경 롤백
-
Task 24.1: rankTextStartDp 롤백 범위 문서화
- 수정:
docs/20260608_크리에이터_랭킹_페이지/plan-task.md - 구현 내용:
- Phase 23의
rankTextStartDp변경을 롤백한다. - margin policy 명칭과 적용 대상을 Phase 21의
rankGroupStartDp기준으로 되돌린다. - 닉네임 margin, lower-row delta measurement, API/mapper 의미는 변경하지 않는다.
- Phase 23의
- 검증: 롤백 범위가
rankTextStartDp변경에 한정되어 있다.
- 수정:
-
Task 24.2: rankGroupStartDp 적용 복원
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingTopCardMargin.kt - 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingTopCardView.kt - 수정:
app/src/test/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingTopCardMarginTest.kt - 구현 내용:
rankTextStartDp를rankGroupStartDp로 되돌린다.CreatorRankingTopCardView.bind()에서ll_creator_ranking_rank_group의MarginLayoutParams.marginStart에 rank별 값을 다시 적용한다.- Phase 21의 닉네임 margin 값은 유지한다.
- 검증: rank group margin application이 복원된다.
- 수정:
-
Task 24.3: 롤백 검증과 문서 기록 누적
- 수정:
docs/20260608_크리에이터_랭킹_페이지/plan-task.md - 실행:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*"./gradlew :app:mergeDebugResources./gradlew :app:compileDebugKotlin./gradlew :app:ktlintCheckgit diff --check
- 기대 결과: 모두
BUILD SUCCESSFUL또는 출력 없음. - 검증 기록:
rankTextStartDp변경 롤백 결과를 Verification Log에 누적한다.
- 수정:
Verification Log
- 2026-06-30: Phase 24로 사용자 요청에 따라 Phase 23의
rankTextStartDp변경을 롤백했다.CreatorRankingTopCardMargin은rankGroupStartDp명칭으로 복원했고,CreatorRankingTopCardView.bind()는ll_creator_ranking_rank_group의MarginLayoutParams.marginStart에 rank별 값을 다시 적용한다. 닉네임 margin, lower-row delta measurement, API/mapper 의미는 변경하지 않았다. 검증으로./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*",./gradlew --no-daemon :app:mergeDebugResources,./gradlew --no-daemon :app:compileDebugKotlin,./gradlew --no-daemon :app:ktlintCheck,git diff --check가 모두BUILD SUCCESSFUL또는 출력 없음으로 통과했다. Gradle deprecated warning과.editorconfig disabled_rulesdeprecation warning은 기존 경고로 보고 수정하지 않았다. - 2026-06-30: Phase 23으로 Phase 21의 순위 left margin 적용 대상을
ll_creator_ranking_rank_group에서tv_creator_ranking_rank로 보정했다.CreatorRankingTopCardMargin.rankGroupStartDp를rankTextStartDp로 정리하고,CreatorRankingTopCardView.bind()에서는 rank text의MarginLayoutParams.marginStart에만 rank별 값을 적용한다. rank delta 위치와 rank group 자체 위치, 닉네임 margin 정책,CreatorRankingDeltaPresentation은 변경하지 않았다. 검증으로./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*",./gradlew --no-daemon :app:mergeDebugResources,./gradlew --no-daemon :app:compileDebugKotlin,./gradlew --no-daemon :app:ktlintCheck,git diff --check가 모두BUILD SUCCESSFUL또는 출력 없음으로 통과했다. Gradle deprecated warning과.editorconfig disabled_rulesdeprecation warning은 기존 경고로 보고 수정하지 않았다. - 2026-06-30: Phase 22로 ranks
11~20lower-row delta가 ranks1~10과 동일하게showRankChange정책을 따르도록 유지하면서, delta가 보이지 않는 원인을 lower-row measurement clipping 가능성으로 보고CreatorRankingLowerRowView.onMeasure()를 보정했다. 기존 Figma 비율 height를 기본값으로 유지하되 rank group measured height와 root vertical padding 합보다 작아지지 않도록 재측정한다.HomeCreatorRankingMappers, API DTO,CreatorRankingDeltaPresentation,showRankChange의미, top-card rank/delta spacing은 변경하지 않았다. top-card/lower-row rank/delta/name은 이미includeFontPadding=false라 추가 font padding 변경은 하지 않았고, 3열 grid delta amount text는14sp,NEW는 text가 아니라36dp x 23dpimage presentation임을 확인했다. 검증으로./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*",./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*",./gradlew --no-daemon :app:mergeDebugResources,./gradlew --no-daemon :app:compileDebugKotlin,./gradlew --no-daemon :app:ktlintCheck,git diff --check가 모두BUILD SUCCESSFUL또는 출력 없음으로 통과했다. home test 실행 중 Kotlin incremental cache registration 오류가 있었으나 fallback 후BUILD SUCCESSFUL로 종료했다. Gradle deprecated warning과.editorconfig disabled_rulesdeprecation warning은 기존 경고로 보고 수정하지 않았다. - 2026-06-30: Phase 21 margin-only 후속으로
CreatorRankingTopCardMargin순수 로직과CreatorRankingTopCardMarginTest를 추가해 rank1,2~7,8~10의 닉네임 좌/우/하단 margin 및 rank group start margin 값을 검증했다.CreatorRankingTopCardView.bind()에서는 기존ll_creator_ranking_rank_group,tv_creator_ranking_name의MarginLayoutParams에만 정책을 적용했다.CreatorRankingDeltaPresentation, delta icon margin,showRankChange,CreatorRankingLowerRowView, lower-row XML, content ranking 파일은 변경하지 않았다. 검증으로./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingTopCardMarginTest",./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*",./gradlew :app:ktlintCheck가 모두BUILD SUCCESSFUL로 통과했고,GIT_MASTER=1 git diff --check는 출력 없이 통과했다.compileDebugKotlin과mergeDebugResources는 위 테스트 실행 중 성공 또는 up-to-date로 확인했다. Gradle deprecated feature warning과.editorconfig disabled_rulesdeprecation warning은 기존 경고로 보고 수정하지 않았다. - 2026-06-29: Phase 19~20 최종 검증으로
fragment_v2_main_home.xml의 ranking list preview를 새view_creator_ranking_lower_row로 갱신하고,HomeMainFragment의 기존 adapter 연결, tab 전환, 최초 로드, empty/error 처리, profile 이동 guard, mapper/API 의미가 유지됨을 확인했다.HomeMainFragmentLayoutTest의 랭킹 layout 속성 assertion은 logic/source contract 중심으로 축소했다. - 2026-06-29: 최종 검증으로
./gradlew :app:mergeDebugResources,./gradlew --no-daemon :app:compileDebugKotlin,./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*",./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeCreatorRankingMapperTest",./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest",./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*",./gradlew --no-daemon :app:ktlintCheck,git diff --check가 모두BUILD SUCCESSFUL또는 출력 없음으로 통과했다.rg로 신규 creator ranking XML/Kotlin에FrameLayout사용이 없고, old Large/Compact/Horizontal/LayoutCalculator/CardVariant/CardSize/setCardSize 참조가 creator ranking 범위에 남지 않았음을 확인했다. 병렬 Gradle 실행 중 Kotlin incremental cache 삭제/backup 오류와 timeout이 있었으나./gradlew --stop및--no-daemon순차 재실행으로 통과했다. - 2026-06-29: Phase 16~18로
CreatorRankingAdapter의 내부 view type을 ranks1~10top-card와 ranks11+lower-row 두 개로 축소하고, 새CreatorRankingTopCardView/CreatorRankingLowerRowView및view_creator_ranking_top_card.xml/view_creator_ranking_lower_row.xml을ConstraintLayoutroot로 작성했다. 기존CreatorRankingLargeCardView,CreatorRankingCompactCardView,CreatorRankingHorizontalCardView,CreatorRankingLayoutCalculator,CreatorRankingCardVariant와 old layout 세 개는 참조 제거 후 삭제했고,fragment_v2_main_home.xml의tools:listitem은 lower-row layout으로 갱신했다. mapper/API 동작과 content ranking 파일은 변경하지 않았고, rank gradient,CreatorRankingItem.displayName(...),isTouchable, adapterloadUrl+CreatorRankingBlur.transformations,CreatorRankingDeltaPresentation.from(...),showRankChange=falsedelta hide 경로,CreatorRankingTextStyle.fromRank(...)텍스트 크기 적용을 유지했다. 검증으로./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*",./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeCreatorRankingMapperTest",GIT_MASTER=1 git diff --check가 모두 성공했다.rg로 creatorranking production 범위의 obsolete Large/Compact/Horizontal/LayoutCalculator/CardVariant/setCardSize/CardSize 참조와 신규 creator ranking XML/Kotlin의FrameLayout사용이 없음을 확인했다. Gradle deprecated feature warning 및 기존 전역 Kotlin warning은 기존 경고로 보고 수정하지 않았다. - 2026-06-29: Phase 14/15로
CreatorRankingAdapterLayoutTest의 Robolectric inflation 및 view size/margin/padding/constraint/TextView dimension/visibility assertion을 제거하고 span/decoration 순수 로직 계약만 남겼다.CreatorRankingPlacement는CreatorRankingViewType.TopTen/Lower와itemsPerRow계약으로 갱신했고,CreatorRankingTextStyle및CreatorRankingTextStyleTest를 추가했다. 고정 card dimension을 요구하던CreatorRankingLayoutCalculatorTest는 삭제했다. 검증으로./gradlew :app:compileDebugKotlin,./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*",./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeCreatorRankingMapperTest"를 실행했고 모두BUILD SUCCESSFUL로 통과했다. 최초 위젯 테스트 실행에서 Kotlin 증분 빌드 참조 오류가 한 번 발생했으나compileDebugKotlin재실행 후 동일 테스트가 성공했다. Gradle deprecated feature warning은 기존 경고로 보고 수정하지 않았다. - 2026-06-29: Phase 11 요구사항으로 rank-area 계약을 갱신했다. PRD와 계획 문서에
tv_creator_ranking_rankXML/Kotlin width/heightwrap_content유지, Kotlin의 텍스트 크기 및 spacing/margin 조정 범위, 순위 숫자와 rank-num의 rank area 중앙 정렬 기준을 먼저 반영했다. - 2026-06-29: Phase 11.2 RED로
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingAdapterLayoutTest"를 실행해 4건 실패를 확인했다. Large/Compact는 rank group이 없어 실패했고, Horizontal은 rankTextView가 Kotlin에서 고정 layoutParams를 받아wrap_content계약을 위반했다. - 2026-06-29: Phase 11.3으로
view_creator_ranking_large_card.xml,view_creator_ranking_compact_card.xml에ll_creator_ranking_rank_group을 추가해 rank와 delta를 함께 세로 중앙 정렬했다.CreatorRankingLargeCardView,CreatorRankingCompactCardView,CreatorRankingHorizontalCardView에서는 rankTextView고정 width/height 설정을 제거하고 rank group/delta 배치만 조정했다. - 2026-06-29: Phase 11.4 검증으로
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingAdapterLayoutTest",./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin을 순차 실행했고 모두BUILD SUCCESSFUL로 통과했다.rg로 Kotlin 내 rankTextView고정 sizing 잔여 없음과 세 XML의tv_creator_ranking_rankwrap_content유지를 확인했다. Gradle deprecated feature warning은 기존 빌드 경고로 보고 수정하지 않았다. - 2026-06-29: 추가 확인 중 Horizontal rank-num 간격이 XML
layout_marginTop에 남아 있어 사용자 요구사항의 Kotlin spacing 조정 범위와 맞지 않음을 확인했다.view_creator_ranking_horizontal_card.xml의 margin을 제거하고CreatorRankingHorizontalCardView에서 scale 기반topMargin을 설정하도록 보정했다. 이후CreatorRankingAdapterLayoutTest,mergeDebugResources,compileDebugKotlin이 모두BUILD SUCCESSFUL로 통과했고,rg로 XML 고정 margin 및 Kotlin rankTextView고정 sizing 잔여 없음도 확인했다. 최초 병렬 Gradle 중 Kotlin incremental cache 충돌이 있었으나 fallback/재실행으로 성공했으며, 기존 deprecation warning은 수정하지 않았다. - 2026-06-29: Phase 12 요구사항으로 8~10위 Compact small의 rank/rank-num 간격 과다, rank parent 고정 폭 의심,
10표시 문제, 닉네임 축소 요구를 분석했다. 직접 확인과 병렬 explore 결과 모두CreatorRankingCompactCardView.positionSmall()에서 rank group 폭이52 * scale로 고정되는 점을 핵심 원인으로 확인했고, rankTextView자체는 XML/Kotlin 모두wrap_content임을 확인했다. - 2026-06-29: Phase 12 RED로
CreatorRankingAdapterLayoutTest를 갱신해 실제 3열 폭에 가까운119x119조건에서rank=10, rank groupWRAP_CONTENT, 닉네임13sp, rank-numtopMargin=-4를 검증하도록 했다. production 수정 전에는 rank group fixed width assertion이 실패했고,CreatorRankingCompactCardView.positionSmall()보정 후 동일 테스트가BUILD SUCCESSFUL로 통과했다. - 2026-06-29: Phase 12 최종 검증으로
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingAdapterLayoutTest",./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck,git diff --check가 통과했다. 병렬 Gradle 실행 중 Kotlin incremental cache 충돌이 있었으나./gradlew --stop후 순차 재실행으로 통과했다. - 2026-06-08:
superpowers:writing-plans지침, PRDdocs/20260608_크리에이터_랭킹_페이지/prd.md, 기존 홈 추천 계획 문서,fragment_v2_main_home.xml,HomeMainFragment,AppDI, 기존 홈 추천 API/ViewModel,creatorranking위젯 구조와 테스트 위치를 확인했다. - 2026-06-08: 이번 단계는 계획 문서 작성만 수행했으며 구현/빌드/테스트는 실행하지 않았다.
- 2026-06-08: Phase 1 범위로 PRD와 기존
HomeMainFragment,fragment_v2_main_home.xml,AppDI, 홈 추천 API/Repository/ViewModel,creatorranking위젯/테스트 구조를 재확인했다. Capsule Tab bar, 팔로잉 탭 content, analytics/logging, ViewPager2/swipe 전환은 Phase 1-3 구현 범위에서 제외했다. - 2026-06-08: Phase 2 TDD RED로
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingItemTest"를 실행해showRankChange미구현 컴파일 실패를 확인했다. 이후CreatorRankingItem.showRankChange기본값을 추가하고 동일 명령이BUILD SUCCESSFUL로 통과했다. - 2026-06-08: Phase 2 rank-num 숨김 TDD RED로
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingAdapterLayoutTest"를 실행했다. 최초 Robolectric 설정 누락으로 Koin 초기화 오류가 발생해 기존 위젯 테스트 패턴과 동일하게@Config(sdk = [28], application = Application::class)를 적용했고, 이후 Large/Compact/Horizontal 숨김 assertion 3건 실패를 확인했다. 세 카드 view에showRankChange=false시ll_creator_ranking_delta를GONE처리하도록 구현한 뒤./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*"가BUILD SUCCESSFUL로 통과했다. - 2026-06-08: Phase 3 mapper TDD RED로
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeCreatorRankingMapperTest"를 실행해HomeCreatorRankingResponse,HomeCreatorRankingItemResponse,toCreatorRankingItems미구현 컴파일 실패를 확인했다. 이후 DTO와 mapper를 추가하고 동일 명령이BUILD SUCCESSFUL로 통과했다. - 2026-06-08: Phase 3 API/Repository를 추가한 뒤
./gradlew :app:compileDebugKotlin이BUILD SUCCESSFUL로 통과했다. 검증 중 병렬 Gradle 실행 1건에서classes.jarzip header 오류가 발생했으나, 동일 타겟을 단독 재실행해./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*",./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeCreatorRankingMapperTest",./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck모두BUILD SUCCESSFUL을 확인했다..editorconfig disabled_rulesdeprecation warning은 기존 경고로 보고 수정하지 않았다. - 2026-06-08: Phase 4로
HomeCreatorRankingUiState,HomeCreatorRankingViewModel을 추가하고AppDI에HomeCreatorRankingApi,HomeCreatorRankingRepository,HomeCreatorRankingViewModel을 등록했다. 검증 명령./gradlew :app:compileDebugKotlin이BUILD SUCCESSFUL로 통과했다. Gradle deprecated feature warning은 기존 빌드 경고로 보고 수정하지 않았다. - 2026-06-08: Phase 5.1 RED로
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest.home ranking layout*"를 실행해R.id.rv_home_creator_rankings미정의 컴파일 실패를 확인했다. 이후fragment_v2_main_home.xml에rv_home_creator_rankings를TextTabBarView아래 직접 constraint되는GONERecyclerView로 추가했고, 동일 테스트와./gradlew :app:mergeDebugResources가BUILD SUCCESSFUL로 통과했다. - 2026-06-08: Phase 5.3 RED로
HomeMainFragmentLayoutTest에 랭킹 adapter/grid, 추천/랭킹 탭 visibility 전환, 최초 랭킹 load, ranking state observe/submit,creatorId > 0프로필 이동 guard 계약 테스트를 추가하고./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest.home ranking*"를 실행해 5개 assertion 실패를 확인했다. 이후HomeMainFragment에HomeCreatorRankingViewModel,CreatorRankingAdapter,CreatorRankingAdapter.createGridLayoutManager(requireContext()), tab index 상수, 최초 로드 guard, ranking observer,openCreatorRankingProfileguard를 연결했고 동일 테스트와./gradlew :app:compileDebugKotlin이BUILD SUCCESSFUL로 통과했다. 기존 Gradle deprecated feature warning과 Kotlin/JDK deprecation warning은 신규 실패가 아니므로 수정하지 않았다. - 2026-06-08: Phase 6.1 targeted test로
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*",./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeCreatorRankingMapperTest",./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest"를 순차 실행했고 모두BUILD SUCCESSFUL로 통과했다. - 2026-06-08: Phase 6.2 통합 검증으로
./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck를 순차 실행했고 모두BUILD SUCCESSFUL로 통과했다. Gradle deprecated feature warning은 기존 빌드 경고로 보고 수정하지 않았다. - 2026-06-08: Phase 6.3으로 PRD와 plan-task 문서의 Verification Log를 누적하고 Phase 6 체크박스를 완료 처리했다. 이번 Phase 6에서는 신규 production code 변경이 없어 별도 RED 테스트 추가 없이 기존 targeted test와 build/lint 검증으로 완료했다.
- 2026-06-09: 사용자 확인에 따라 순위 숫자에 별도 left margin을 추가하지 않고, Figma의 고정 텍스트 박스 내부 중앙 정렬을 맞추는 Phase 7 후속 작업을 추가했다.
- 2026-06-09: Phase 7.1 RED로
CreatorRankingAdapterLayoutTest에 Large/Compact medium/Compact small/Horizontal 순위 박스 검증을 추가하고./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingAdapterLayoutTest"를 실행했다. Large/Compact medium/Compact small 3건이Gravity.CENTERassertion에서 실패해 순위 TextView 내부 정렬 미반영을 확인했다. - 2026-06-09: Phase 7.2로
view_creator_ranking_large_card.xml,view_creator_ranking_compact_card.xml,view_creator_ranking_horizontal_card.xml의 순위 TextView에android:gravity="center"를 추가했다. 동일CreatorRankingAdapterLayoutTest가BUILD SUCCESSFUL로 전환됐다. - 2026-06-09: Phase 7.3 검증으로
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*"와./gradlew :app:mergeDebugResources를 실행했고 모두BUILD SUCCESSFUL로 통과했다. Gradle deprecated feature warning은 기존 빌드 경고로 보고 수정하지 않았다. - 2026-06-09: Figma
24:5658design context와 screenshot을 재확인했고, 순위 숫자 박스 및 rank-num 위치에서 현재 구현과 다른 최신 기준값을 Phase 8 후속 작업으로 추가했다. - 2026-06-09: Phase 8.1 RED로
CreatorRankingAdapterLayoutTest의 순위 숫자 박스/순위 변화 표시 위치 기대값을 Figma24:5658기준으로 갱신하고 실행했다. production 수정 전 1위/27위/810위 순위 박스, 11위 이후 rank group top, 1위/8~10위 rank-num 위치 assertion 6건 실패를 확인했다. - 2026-06-09: Phase 8.2로
CreatorRankingLargeCardView,CreatorRankingCompactCardView,CreatorRankingHorizontalCardView의 위치 계산을 Figma 기준으로 보정했다. 동일CreatorRankingAdapterLayoutTest가BUILD SUCCESSFUL로 전환됐다. New badge는 기존 PRD가 이미지 리소스 사용을 요구하고ic_rank_new.png가 36x23으로 Figma 크기와 일치해 유지했다. - 2026-06-09: Phase 8.3 검증으로
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*",./gradlew :app:mergeDebugResources,./gradlew :app:ktlintCheck를 실행했다. 최초 ktlint에서 테스트 파일 불필요한 빈 줄 2건이 실패해 정리했고, 이후CreatorRankingAdapterLayoutTest와ktlintCheck가BUILD SUCCESSFUL로 통과했다. Gradle deprecated feature warning은 기존 빌드 경고로 보고 수정하지 않았다. - 2026-06-25: Phase 9.1로
CreatorRankingAdapterLayoutTest에 순위TextView의includeFontPadding=false유지와 variant별 하단 padding(1위 10px, 27위 6px, 810위 5px, 11위 이후 4px) 검증을 추가했다. Phase 9.2로 기존 Figma 좌표와 rank-num top/left는 유지하고 순위TextView내부 하단 padding만 scale 기반으로 적용했다. - 2026-06-25: Phase 9 검증 중 최초 병렬 Gradle 실행에서 Kotlin incremental cache 충돌과 timeout이 발생해
./gradlew --stop,./gradlew clean후 순차 재실행했다../gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingAdapterLayoutTest",./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*",./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin은 모두BUILD SUCCESSFUL로 통과했다../gradlew :app:ktlintCheck는 변경 파일이 아닌 기존 전역 위반(Agora.kt,audio_contentpackage-name, 기존CreatorRankingAdapter.kt긴 줄 등)으로 실패했으며,git diff --check는 출력 없이 통과했다. - 2026-06-29: Phase 10 요구사항으로 Figma
24:5668,24:5661,24:5670design context와 screenshot을 확인했다. 3열 Compact는 순위36sp, 닉네임14sp, rank-num 숫자14sp, 2열 Compact는 순위54sp, 닉네임22sp, rank-num 숫자16sp, 11위 이후 Horizontal은 rank group 내부 세로 배치 유지, 랭킹 item 간격은8dp로 정리했다. - 2026-06-29: Phase 10.1 RED로
CreatorRankingAdapterLayoutTest에 Compact 2열/3열 텍스트 크기와 Horizontal rank group 세로 배치 검증을 추가하고 실행했다. production 수정 전 3열 Compact 순위 텍스트 크기 assertion 실패를 확인했다.CreatorRankingLayoutCalculatorTest는8dp입력 기준 계산 테스트라 기존 코드에서도 통과했다. - 2026-06-29: Phase 10.2로
CreatorRankingCompactCardView의 3열 Compact 순위 텍스트를36sp, rank-num 숫자를14sp로 보정하고 2열 rank-num 숫자16sp를 명시 유지했다.CreatorRankingAdapter의 랭킹 item 폭 계산 기준을8dp로 변경하고, 실제GridLayoutManager배치에서 인접 item offset 합이8dp가 되도록CreatorRankingItemDecoration을 추가했다.HomeMainFragment에는 decoration을 중복 없이 적용했다. - 2026-06-29: Phase 10 리뷰 게이트에서 카드 폭 계산만 줄이면 실제
GridLayoutManageritem 사이 간격이8dp로 보장되지 않는다는 차단 이슈가 나왔다. 이에CreatorRankingAdapterLayoutTest에 전용 decoration offset 계약을 추가하고,HomeMainFragmentLayoutTest.home ranking fragment wires adapter and grid layout manager에 decoration 연결 검증을 추가했다. production 수정 전에는CreatorRankingItemDecoration미구현 컴파일 실패를 확인했고, 구현 후 두 테스트가BUILD SUCCESSFUL로 통과했다. - 2026-06-29: Phase 10 검증 중 최초 병렬 Gradle 실행에서 Kotlin incremental cache 충돌과 timeout이 발생해
./gradlew --stop,./gradlew clean후 순차 재실행했다. 이후./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingAdapterLayoutTest",./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingLayoutCalculatorTest",./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.creatorranking.*",./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck가 모두BUILD SUCCESSFUL로 통과했다.git diff --check도 출력 없이 통과했다. - 2026-06-29: Phase 13~20 후속 rewrite 계획을 추가했다. 순서는 docs, logic-only test rewrite, placement/text-style logic, adapter two-view rewrite, ConstraintLayout view rewrite, obsolete FrameLayout cleanup, home integration cleanup, final validation이며, 모든 신규 task는 구현 전 상태로
- [ ]체크박스를 유지했다. - 2026-06-29: 후속 rewrite 전제로
ConstraintLayout사용,FrameLayout미사용, adapter view type 두 개(ranks1~10, ranks11~20), Figma24:5659,24:5660,24:5668,24:5670, 텍스트 크기 정책, mapper/API 변경 제외, logic-only 테스트 정책을 계획 문서에 반영했다.