47 KiB
메인 홈 추천 UI와 API 연동 Plan / Task
For agentic workers: 구현 시
superpowers:subagent-driven-development또는superpowers:executing-plans를 사용해 task 단위로 진행한다. 각 단계는 체크박스(- [ ])로 추적하고, 완료 즉시- [x]로 갱신한다.
Goal: Figma home_001(24:5514) 기준 메인 홈 추천 화면을 HomeMainFragment에 구성하고, GET /api/v2/home/recommendations 및 모두 팔로우 API를 기존 XML View + v2 widget 패턴으로 연동한다.
Architecture: 신규 홈 추천 API, Repository, ViewModel, DTO/UI model/mapper는 kr.co.vividnext.sodalive.v2.main.home 하위에 둔다. 화면은 HomeMainFragment와 fragment_v2_main_home.xml을 확장하고, 기존 v2.widget 컴포넌트는 재사용하되 추천 화면에 필요한 최소 확장만 수행한다.
Tech Stack: Kotlin, Android XML Views, ViewBinding, RecyclerView, RxJava3, Retrofit, Gson, Koin, Coil, local unit test.
전제와 성공 기준
- PRD:
docs/20260601_메인_홈_추천_UI와_API_연동/prd.md - 기존
HomeApi에는 메서드를 추가하지 않고 신규HomeRecommendationApi를 만든다. - 신규 화면 관련 하위 코드는
kr.co.vividnext.sodalive.v2패키지 하위에 작성한다. 추천 필모그래피,또 다른 모습섹션은 만들지 않는다.- 각 API 리스트가 비어 있으면 해당 section-title과 목록을 숨긴다.
- 구현 완료 후 최소
./gradlew :app:testDebugUnitTest와./gradlew :app:ktlintCheck를 실행한다.
Phase 1: 기존 구조 확인과 구현 경계 고정
-
Task 1.1: 기존 홈/위젯/네트워크 패턴 확인
- 확인:
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/home/HomeApi.kt - 확인:
app/src/main/java/kr/co/vividnext/sodalive/common/ApiResponse.kt - 확인:
app/src/main/java/kr/co/vividnext/sodalive/extensions/ImageExtensions.kt - 검증:
HomeMainFragment는 현재 빈FrameLayout바인딩만 가지고 있고, 신규 API 등록은AppDI.kt의networkModule,repositoryModule,viewModelModule에 추가해야 함을 확인한다.
- 확인:
-
Task 1.2: 재사용 위젯과 신규 UI 범위 확정
- 확인:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/banner/BannerView.kt - 확인:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/livethumbnail/LiveThumbnailSimpleView.kt - 확인:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/AudioContentCardView.kt - 확인:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/characterchatthumbnail/CharacterChatThumbnailView.kt - 확인:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/feed/FeedCommunityView.kt - 확인:
app/src/main/res/layout/view_section_title.xml - 신규 필요 후보: 최근 활동 카드, 최근 데뷔 크리에이터 카드, 장르별/응원 크리에이터 profile grid, 모두 팔로우 버튼, 사업자 정보 접기 영역.
- 검증: PRD의 Section Mapping 표와 구현 대상/제외 대상이 일치하는지 문서 체크한다.
- 확인:
Phase 2: API DTO, Repository, DI 추가
-
Task 2.1: 홈 추천 API/DTO 파일 생성
- 생성:
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/data/HomeRecommendationModels.kt - 구현 내용:
GET /api/v2/home/recommendationsPOST /api/v2/home/recommendations/creators/followFollowRecommendedCreatorsRequest(val creatorIds: List<Long>)HomeRecommendationResponse와 PRD의 모든 item DTO
- 주의: 서버 필드명은 임의 변경하지 않고 필요할 때만
@SerializedName을 추가한다. - 검증:
HomeRecommendationResponse필드가lives,banners,recentlyActiveCreators,recentDebutCreators,firstAudioContents,aiCharacters,genreCreators,cheerCreators,popularCommunityPosts를 모두 포함한다.
- 생성:
-
Task 2.2: Repository 생성
- 생성:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/data/HomeRecommendationRepository.kt - 구현 내용:
getRecommendations(token: String)followRecommendedCreators(request: FollowRecommendedCreatorsRequest, token: String)
- 검증: 기존 Repository처럼 Retrofit
Single<ApiResponse<...>>를 그대로 반환하고, token은 호출부에서"Bearer ${SharedPreferenceManager.token}"형태로 전달한다.
- 생성:
-
Task 2.3: Koin DI 등록
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt - 구현 내용:
networkModule에HomeRecommendationApi등록repositoryModule에HomeRecommendationRepository등록- 이후 Phase 4에서 생성할
HomeRecommendationViewModel등록
- 검증 명령:
./gradlew :app:compileDebugKotlin - 기대 결과: 신규 API/Repository import 및 Koin 등록 컴파일 성공.
- 수정:
Phase 3: 순수 mapper와 unit test 작성
-
Task 3.1: activity type 표시 mapper 테스트 작성
- 생성:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/RecommendedActivityTypeTest.kt - 대상:
LIVE,LIVE_REPLAY,AUDIO,COMMUNITY, 알 수 없는 code. - 기대:
LIVE,LIVE_REPLAY->R.string.home_recommendation_activity_liveAUDIO->R.string.home_recommendation_activity_audioCOMMUNITY->R.string.home_recommendation_activity_community- unknown -> null 또는 미표시 정책
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests kr.co.vividnext.sodalive.v2.main.home.RecommendedActivityTypeTest - 기대 결과: mapper 구현 전 실패.
- 생성:
-
Task 3.2: activity type mapper 구현
- 생성:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/RecommendedActivityType.kt - 생성:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/HomeRecommendationMappers.kt - 구현 내용:
- 백엔드 code 문자열을 앱 enum으로 변환
- 표시 문자열은
@StringRes로 반환해 Fragment/ViewHolder에서getString()처리 - 알 수 없는 code는 크래시 없이 null 반환 후 UI에서 activity label 미표시
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests kr.co.vividnext.sodalive.v2.main.home.RecommendedActivityTypeTest - 기대 결과: PASS.
- 생성:
-
Task 3.3: string resource 추가
- 수정:
app/src/main/res/values/strings.xml - 수정:
app/src/main/res/values-en/strings.xml - 수정:
app/src/main/res/values-ja/strings.xml - 추가 문자열:
- 추천/랭킹/팔로잉 tab
- 섹션 제목
라이브,오디오,커뮤니티모두 팔로우 하기,모두 팔로우 완료더보기,접기- 사업자 정보 텍스트
- 검증 명령:
./gradlew :app:mergeDebugResources - 기대 결과: resource merge 성공.
- 수정:
Phase 4: ViewModel과 화면 상태 구성
-
Task 4.1: UI model 정의
- 생성:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/HomeRecommendationUiState.kt - 생성:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/HomeRecommendationUiModels.kt - 구현 내용:
Loading,Content,Empty,Error상태- 섹션별 UI model 또는 adapter item
HomeFirstAudioContentItem->AudioContentTag.First,Point,Free조건 매핑HomeAiCharacterItem.originalWorkTitle == null이면 기존CharacterChatThumbnailView의shouldShowOriginalTitle = falseHomePopularCommunityPostItem의price,existOrdered기반 유료 상태 모델
- 검증: DTO를 Fragment/ViewHolder에 직접 노출하지 않는다.
- 생성:
-
Task 4.2: ViewModel 생성
- 생성:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeRecommendationViewModel.kt - 구현 내용:
recommendationStateLiveDatatoastLiveDataisLoadingloadRecommendations()followCreators(sectionKey: String, creatorIds: List<Long>)- 빈
creatorIds면 API 미호출 - 모두 팔로우 success 후 해당 section/button 상태 완료 처리
- 검증:
ApiResponse.success == false,data == null, Throwable 상황에서 기존 패턴처럼 unknown error toast를 노출한다.
- 생성:
-
Task 4.3: ViewModel DI 등록 완료
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt - 구현 내용:
viewModel { HomeRecommendationViewModel(get()) } - 검증 명령:
./gradlew :app:compileDebugKotlin - 기대 결과: Koin 등록 및 ViewModel 생성 컴파일 성공.
- 수정:
Phase 5: HomeMainFragment 레이아웃과 상단 UI 구현
-
Task 5.1: 홈 추천 화면 레이아웃 작성
- 수정:
app/src/main/res/layout/fragment_v2_main_home.xml - 포함:
include또는 직접 배치로view_title_bar_homeTextTabBarViewTextTabBarView아래 추천 content 전용 세로NestedScrollView또는 동등한 scroll container- 추천 content 내부 섹션별 컨테이너와 가로
RecyclerView - 추천 content 내부 사업자 정보 영역
- 제외:
ViewPager2FragmentStateAdapter랭킹,팔로잉용 별도 Fragment랭킹,팔로잉용 숨김 View를 미리 배치하는VISIBLE/GONE구조
- 검증: root background는 기존처럼
@color/black유지하고, 세로 스크롤 시 title-bar와TextTabBarView는 화면에 남으며 그 아래 추천 content만 스크롤된다.
- 수정:
-
Task 5.2: title bar와 tab bar 바인딩
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/HomeMainFragment.kt - 확인:
app/src/main/res/layout/view_title_bar_home.xml - 확인:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/TextTabBarView.kt - 구현 내용:
- right icons 순서:
ic_bar_cash,ic_bar_search,ic_bar_bell - tabs 순서: 추천, 랭킹, 팔로잉
- 추천 tab selected 상태
- tab 전환은 글자 터치 callback으로만 처리
- 좌우 swipe 전환은 추가하지 않음
- 이번 범위에서는 추천 tab content만 바인딩하고
랭킹,팔로잉content는 생성하지 않음
- right icons 순서:
- 검증: 앱 실행 시 상단 bar와 tab이 표시되고 text resource가 적용된다. 좌우 swipe로 tab 전환이 발생하지 않는다.
- 수정:
Phase 6: 섹션 adapter와 재사용 위젯 바인딩
Phase 6까지는 실제 API/ViewModel 연동 전 단계이므로, 실제 기기에서 UI 배치와 섹션 표시 형태를 확인할 수 있도록 Fragment 또는 adapter 호출부에 샘플 데이터를 임시 주입할 수 있다. 샘플 데이터는 Phase 9의 실제
HomeRecommendationViewModelobserve/API 바인딩 전 제거하거나 실제 상태 바인딩으로 대체한다.
-
Task 6.1: 라이브, 배너 섹션 바인딩
- 생성 후보:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeLiveAdapter.kt - 생성 후보:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeBannerBinder.kt - 재사용:
LiveThumbnailSimpleView,BannerView - 구현 내용:
lives가 비면 라이브 섹션 숨김banners가 비면 배너 섹션 숨김- 이미지 로딩은
ImageView.loadUrl()또는 기존 widget adapter의 방식 사용
- 검증: 샘플
lives,banners데이터로 실제 기기에서 라이브 가로 목록과 배너 캐러셀이 의도한 위치/크기로 보인다. 빈 리스트일 때 title/RecyclerView가 함께GONE.
- 생성 후보:
-
Task 6.2: 최근 활동/최근 데뷔 크리에이터 UI 구현
- 생성 후보:
app/src/main/res/layout/item_home_recent_activity_creator.xml - 생성 후보:
app/src/main/res/layout/item_home_recent_debut_creator.xml - 생성 후보:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeRecentActivityCreatorAdapter.kt - 생성 후보:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeRecentDebutCreatorAdapter.kt - 구현 내용:
- 최근 활동 activity type label은 Phase 3 mapper 결과 사용
- unknown activity type은 label view 숨김
- 닉네임/제목은 기존 typography와 말줄임 정책 적용
- 검증: 샘플 creator 데이터로 실제 기기에서 최근 활동/최근 데뷔 카드 배치가 보인다.
LIVE_REPLAY도라이브로 표시.
- 생성 후보:
-
Task 6.3: 첫 오디오 콘텐츠와 AI 캐릭터 섹션 바인딩
- 생성 후보:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFirstAudioAdapter.kt - 생성 후보:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeAiCharacterAdapter.kt - 재사용:
AudioContentCardView,CharacterChatThumbnailView - 구현 내용:
- 첫 오디오 콘텐츠는
AudioContentTag.First항상 포함 isPointAvailable == true면AudioContentTag.Pointprice == 0이면AudioContentTag.FreeAudioContentTag.Original은 포함하지 않음- AI character image는
profileImage사용
- 첫 오디오 콘텐츠는
- 검증: 샘플 audio/AI character 데이터로 실제 기기에서 카드 배치와 이미지/텍스트 영역이 보인다. 오디오 태그 조합이 PRD 조건과 일치.
- 생성 후보:
-
Task 6.4: 장르별/응원 크리에이터와 모두 팔로우 버튼 구현
- 생성 후보:
app/src/main/res/layout/item_home_creator_profile.xml - 생성 후보:
app/src/main/res/layout/view_home_follow_all_button.xml - 생성 후보:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeGenreCreatorAdapter.kt - 생성 후보:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeCheerCreatorAdapter.kt - 구현 내용:
cheerCreators.creatorId목록으로 모두 팔로우 API 호출genreCreators의 해당 그룹creators.creatorId목록으로 모두 팔로우 API 호출- success 후
모두 팔로우 완료,ic_new_following, click disabled - 실패 시 toast/error 표시
- 검증: 샘플 genre/cheer creator 데이터로 실제 기기에서 profile grid와 모두 팔로우 버튼 배치가 보인다. 빈 creator list에서는 API 호출하지 않고 버튼 상태 유지.
- 생성 후보:
-
Task 6.5: 방금 활동한 크리에이터 Figma 정합 수정
- 기준: Figma
24:5529 - 수정:
app/src/main/res/layout/item_home_recent_activity_creator.xml - 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomePhase6Adapters.kt - 생성:
app/src/main/res/drawable/bg_home_recent_activity_card.xml - 생성:
app/src/main/res/drawable/bg_home_recent_activity_type.xml - 구현 내용:
- 세로 프로필형 카드를
244dp x 76dp가로 capsule 카드로 변경 - profile image를
52dp x 52dp로 변경 - 닉네임은
18spbold, activity type은gray_700tag, 보조 텍스트는activityAt표시
- 세로 프로필형 카드를
- 검증:
HomeMainFragmentLayoutTest에 Figma capsule 치수 회귀 테스트를 추가한다.
- 기준: Figma
-
Task 6.6: 홈 추천 섹션 adapter 파일 분리
- 삭제:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomePhase6Adapters.kt - 생성:
HomeLiveAdapter.kt,HomeBannerBinder.kt,HomeRecentActivityCreatorAdapter.kt,HomeRecentDebutCreatorAdapter.kt,HomeFirstAudioAdapter.kt,HomeAiCharacterAdapter.kt,HomeCreatorProfileAdapter.kt,HomeGenreCreatorAdapter.kt,HomeCheerCreatorAdapter.kt,HomeFollowAllButtonBinder.kt,HomeRecyclerItemLayoutParams.kt - 구현 내용:
- 한 파일에 모여 있던 섹션별 adapter/binder를 섹션 단위 파일로 분리
- 공통
RecyclerView.LayoutParams생성 로직은 package-private helper로 분리 - UI 동작과 바인딩 계약은 변경하지 않음
- 검증:
./gradlew :app:compileDebugKotlin,./gradlew :app:testDebugUnitTest --tests kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest,./gradlew :app:ktlintCheck를 실행한다.
- 삭제:
-
Task 6.7: 라이브 섹션 Figma 정합 수정
- 기준: Figma
24:5516 - 수정:
app/src/main/res/layout/fragment_v2_main_home.xml - 수정:
app/src/main/res/values/dimens.xml - 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeLiveAdapter.kt - 수정:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragmentLayoutTest.kt - 구현 내용:
rv_home_lives높이는 아이템 높이에 따라가도록wrap_content유지rv_home_lives시작 padding20dp적용- 라이브 아이템 간격을 Figma 기준
14dp로 적용 - 라이브는 최대 20개까지 표시하고, 20개 초과 시
HomeLiveAdapter마지막 item으로58dp x 102dp검은 배경전체item 추가
- 검증:
HomeMainFragmentLayoutTest에 live rowwrap_content, live adapter item gap, 20개 초과 시전체item 추가 회귀 테스트를 추가한다.
- 기준: Figma
-
Task 6.8: 최근 데뷔한 크리에이터 Figma 정합 수정
- 기준: Figma
24:5534 - 수정:
app/src/main/res/layout/item_home_recent_debut_creator.xml - 수정:
app/src/main/res/layout/fragment_v2_main_home.xml - 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeRecentDebutCreatorAdapter.kt - 수정:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragmentLayoutTest.kt - 생성:
app/src/main/res/drawable/bg_home_recent_debut_card.xml - 생성:
app/src/main/res/drawable/bg_home_recent_debut_dim_gradient.xml - 구현 내용:
- 기존 원형 profile item을
205dp x 259dp이미지 카드로 변경 - 카드 radius
14dp, 하단 dim gradient, 닉네임24spbold 중앙 정렬 적용 rv_home_recent_debut_creators시작 padding14dp, item gap4dp적용
- 기존 원형 profile item을
- 검증:
HomeMainFragmentLayoutTest에 recent debut 카드 치수와 목록 간격 회귀 테스트를 추가한다.
- 기준: Figma
-
Task 6.9: 처음부터 함께 성장! Figma 정합 수정
- 기준: Figma
24:5539 - 생성:
app/src/main/res/layout/item_home_first_audio_content.xml - 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFirstAudioAdapter.kt - 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeRecyclerItemLayoutParams.kt - 수정:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragmentLayoutTest.kt - 구현 내용:
AudioContentCardView재사용 대신 첫 오디오 전용 item layout을 사용한다.- 썸네일을
185dp x 185dp, radius14dp카드로 구성한다. - creator profile을
42dp x 42dp, creator nickname14sp로 구성하고 상세 시간은 표시하지 않는다. rv_home_first_audio_contents시작 padding14dp, item gap4dp를 적용한다.First,Point,Freetag 표시 조건은 기존 UI model의tags를 그대로 사용한다.
- 검증:
HomeMainFragmentLayoutTest에 first audio 카드 치수, 목록 간격, tag visibility 회귀 테스트를 추가한다.
- 기준: Figma
-
Task 6.10: AI 캐릭터 섹션 Figma 정합 수정
- 기준: Figma
24:5551 - 확인:
app/src/main/res/layout/view_character_chat_thumbnail.xml - 수정:
app/src/main/res/layout/fragment_v2_main_home.xml - 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeAiCharacterAdapter.kt - 수정:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragmentLayoutTest.kt - 구현 내용:
크리에이터와 이야기를 나눠요!목록 시작/끝 padding을14dp로 적용한다.- AI 캐릭터 item gap을
4dp로 적용한다. - adapter에서
view_character_chat_thumbnail.xml의 root185dp x wrap_content치수를 generic layout params로 덮어쓰지 않는다.
- 검증:
HomeMainFragmentLayoutTest에 AI 캐릭터 목록 spacing과 adapter item dimension 회귀 테스트를 추가한다.
- 기준: Figma
-
Task 6.11: 장르 크리에이터 모두 팔로우 버튼 Figma 정합 수정
- 기준: Figma
24:5611, 완료 버튼24:9092 - 수정:
app/src/main/res/layout/view_home_follow_all_button.xml - 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowAllButtonBinder.kt - 수정:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragmentLayoutTest.kt - 구현 내용:
- 기본 상태는
모두 팔로우하기,ic_new_follow, 투명 배경과 흰색 30% stroke, 흰색 텍스트를 적용한다. - 완료 상태는
모두 팔로우 완료,ic_new_following, 흰색 배경, 검은색 텍스트를 적용한다. - 완료 상태에서는 터치해도 callback을 호출하지 않는다.
- 기본 상태는
- 검증:
HomeMainFragmentLayoutTest에 모두 팔로우 기본/완료 상태와 완료 상태 no-op 회귀 테스트를 추가한다.
- 기준: Figma
Phase 7: FeedCommunityView 추천 페이지 확장
-
Task 7.1: FeedItem.Community 추천 필드 확장
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/feed/FeedItem.kt - 추가 후보:
imageUrl: String?price: IntexistOrdered: BooleanshowKeyword: Boolean
- 주의: 기존 호출부 기본값을 제공해 기존 feed 사용처 영향 최소화.
- 검증 명령:
./gradlew :app:compileDebugKotlin
- 수정:
-
Task 7.2: 커뮤니티 이미지/유료 overlay 레이아웃 추가
- 수정:
app/src/main/res/layout/view_feed_community.xml - 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/feed/FeedCommunityView.kt - 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/feed/FeedAdapter.kt - 구현 내용:
- keyword는 추천 페이지에서 숨김
imageUrl != null이면346dp x 236dp, radius14dp, centerCrop 이미지 표시price > 0 && existOrdered == false면 blur/lock overlay와 가격 capsule 표시- 무료/구매 완료는 overlay와 가격 capsule 숨김
FeedImageViews.primary로 커뮤니티 이미지도 외부에서 로드 가능하게 노출
- 검증: 기존 Community variant는 기본값으로 keyword를 유지하고, 추천용 item만 keyword를 숨긴다.
- 수정:
-
Task 7.3: 인기 커뮤니티 섹션 바인딩
- 생성 후보:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomePopularCommunityAdapter.kt - 재사용:
FeedAdapter또는FeedCommunityView - 구현 내용:
postId,creatorId,creatorNickname,creatorProfileImage,content,createdAt,likeCount,commentCount,imageUrl,price,existOrdered매핑audioUrl은 별도 플레이어 UI 없이 상세 이동 데이터로만 유지
- 검증: keyword 미노출, 이미지 null이면 이미지 영역
GONE.
- 생성 후보:
Phase 8: 사업자 정보 접기/더보기 구현
- Task 8.1: 사업자 정보 UI 구현
- 수정:
app/src/main/res/layout/fragment_v2_main_home.xml - 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/HomeMainFragment.kt - 구현 내용:
- 기본
maxLines = 3,ellipsize = end 더보기클릭 시 전체 표시접기클릭 시 다시 3줄 말줄임- 3줄 이하 텍스트면 toggle 숨김
- 기본
- 검증: 외부 라이브러리 없이
TextView.post { lineCount }기반으로 toggle 노출 여부 결정.
- 수정:
Phase 9: 라우팅, empty/error/loading 정책 연결
-
Task 9.1: Fragment observe와 loading/toast 연결
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/HomeMainFragment.kt - 구현 내용:
HomeRecommendationViewModel주입loadRecommendations()호출recommendationStateLiveDataobserve 후 각 섹션 bindisLoading은 기존LoadingDialog또는 홈 화면 패턴 확인 후 적용toastLiveData는BaseFragment.showToast()사용
- 검증: API 실패 시 앱 크래시 없이 toast/error 처리.
- 수정:
-
Task 9.2: 클릭 라우팅 연결
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/HomeMainFragment.kt - 확인: 기존 상세 화면 Activity/Fragment 라우팅 파일
- 구현 내용:
- 배너 type별 이동은 기존 딥링크/이동 정책 확인 후 연결
- live, creator, audio content, AI character, community post 클릭은 adapter callback으로 Fragment에 위임
- 확정되지 않은 목적지는 임시 주석으로 남기지 않고 no-op 또는 기존 정책 확인 후 최소 연결
- 검증: UI 컴포넌트 내부에서 목적지를 결정하지 않는다.
- 수정:
Phase 10: 최종 검증과 문서 기록
-
Task 10.1: 단위 테스트와 빌드 검증
- 실행:
./gradlew :app:testDebugUnitTest - 실행:
./gradlew :app:compileDebugKotlin - 실행:
./gradlew :app:mergeDebugResources - 실행:
./gradlew :app:ktlintCheck - 기대 결과: 모두 성공.
- 실행:
-
Task 10.2: 수동 확인
- 확인 항목:
- 추천 tab 선택 상태
- tab 전환은 글자 터치로만 동작하고 swipe 전환은 없음
- 세로 스크롤 시 title-bar와
TextTabBarView는 유지되고TextTabBarView아래 추천 content만 스크롤됨 - 섹션 순서가 PRD 도식과 일치
- 제외 섹션 미노출
- 빈 리스트 섹션 숨김
- 첫 오디오 태그 조건
- activity type 다국어 문자열
- 모두 팔로우 success 후 완료 상태
- 인기 커뮤니티 유료/무료/구매 완료 이미지 상태
- 사업자 정보 더보기/접기
- 기대 결과: PRD Metrics 항목 충족.
- 확인 항목:
-
Task 10.3: 검증 기록 누적
- 수정:
docs/20260601_메인_홈_추천_UI와_API_연동/plan-task.md - 수정:
docs/20260601_메인_홈_추천_UI와_API_연동/prd.md - 구현 내용: 실행 명령, 결과, 실패 시 원인과 후속 조치를 문서 하단
검증 기록에 누적한다. - 주의: 기존 검증 기록은 삭제하거나 덮어쓰지 않는다.
- 수정:
구현 중 확인 필요
- 배너
type별 이동 정책과 서버 code 목록. HomeLiveItem,HomeBannerItem,HomeActiveCreatorItem,HomeCreatorItem,HomeGenreCreatorGroupItem의 최종 서버 필드명.- 시간 표시 포맷:
activityAt,releaseDate,createdAt,beginDateTime에 기존 formatter를 재사용할 수 있는지 확인. - 모두 팔로우 API success response의
data형태.ApiResponse.success == true만으로 완료 처리 가능한지 백엔드 계약 확인. - 사업자 정보 텍스트를
strings.xml로 둘지 서버/설정값으로 받을지 운영 정책 확인.
검증 기록
- 2026-06-02:
docs/20260601_메인_홈_추천_UI와_API_연동/prd.md,docs/agent-guides/work-plan-docs.md를 확인해 계획 문서 위치와 phase/task 형식을 맞췄다. - 2026-06-02:
HomeMainFragment,fragment_v2_main_home.xml,HomeApi,HomeRepository,AppDI,ApiResponse, 주요 v2 widget 파일을 확인해 신규 API/Repository/ViewModel과 UI 작업 범위를 계획에 반영했다. - 2026-06-02: 사용자 추가 제공 정보에 따라
ViewPager2/swipe 전환과 tab별 Fragment 선행 생성을 제외하고,TextTabBarView아래 추천 content만 세로 스크롤되도록 Phase 5와 수동 확인 항목을 갱신했다. - 2026-06-02: Phase 1 파일과 PRD Section Mapping을 확인해
HomeMainFragment/fragment_v2_main_home.xml은 아직 빈 홈 v2 shell이고, Phase 1-3 범위에서는 UI/ViewModel/adapter를 만들지 않는 것으로 구현 경계를 고정했다. - 2026-06-02:
RecommendedActivityTypeTest를 먼저 추가하고./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.RecommendedActivityTypeTest"를 실행해model패키지, mapper 함수,home_recommendation_activity_*리소스 미존재로 실패하는 RED 상태를 확인했다. - 2026-06-02:
HomeRecommendationApi,HomeRecommendationModels,HomeRecommendationRepository를 추가하고AppDI.kt의networkModule/repositoryModule에 신규 API/Repository를 등록했다. Phase 4 대상인HomeRecommendationViewModel등록은 추가하지 않았다. - 2026-06-02:
RecommendedActivityType,HomeRecommendationMappers, 한국어/영어/일본어 string resource를 추가한 뒤 targeted test를 재실행해 PASS로 GREEN 전환을 확인했다. - 2026-06-02:
./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:testDebugUnitTest,./gradlew :app:ktlintCheck를 실행했고 모두 BUILD SUCCESSFUL을 확인했다.lsp_diagnostics는kotlin-lsp미설치로 실행되지 않아 Gradle compile/test/ktlint 결과로 보완했다. - 2026-06-02: 백엔드 activity type code가 대소문자와 무관하게 들어와도 매핑되도록
RecommendedActivityTypeTest에live,Live_RePlay케이스를 추가했다. 수정 전./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.RecommendedActivityTypeTest"에서 해당 2개 테스트 실패로 RED를 확인했다. - 2026-06-02:
RecommendedActivityType.from()의 code 비교를equals(ignoreCase = true)로 변경한 뒤./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.RecommendedActivityTypeTest",./gradlew :app:compileDebugKotlin을 실행했고 모두 BUILD SUCCESSFUL을 확인했다. - 2026-06-02: Phase 6까지 진행했을 때 실제 API/ViewModel 연동 전에도 UI 배치와 섹션 표시 형태를 확인할 수 있도록 샘플 데이터를 임시 주입하는 검증 방식을 Phase 6 설명과 섹션별 검증 항목에 추가했다. 샘플 데이터는 Phase 9 실제 상태 바인딩 전 제거하거나 대체해야 한다.
- 2026-06-02: Phase 4.1로
HomeRecommendationUiState,HomeRecommendationUiModels,HomeRecommendationResponse.toContent()와 섹션별 mapper를 추가했다. DTO를 Fragment/ViewHolder 계약으로 직접 노출하지 않고, 첫 오디오 태그(First/Point/Free), AI character original title 표시 여부, 인기 커뮤니티 유료 상태 모델을 UI model로 변환하도록 구성했다. - 2026-06-02: Phase 4.2로
HomeRecommendationViewModel을 추가해recommendationStateLiveData,toastLiveData,isLoading,loadRecommendations(),followCreators(sectionKey, creatorIds)를 구현했다. 추천 API 성공 시 Content/Empty 상태로 분기하고, 실패/data null/Throwable은 Error 상태와 unknown error toast를 노출하도록 했다. 빈 creatorIds에서는 모두 팔로우 API를 호출하지 않는다. - 2026-06-02: Phase 4.3으로
AppDI.kt에HomeRecommendationViewModelimport와viewModel { HomeRecommendationViewModel(get()) }등록을 추가했다.lsp_diagnostics는kotlin-lsp미설치로 실행되지 않아 Gradle 검증으로 보완할 예정이다. - 2026-06-02: Phase 4 검증으로
./gradlew :app:compileDebugKotlin --rerun-tasks,./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*",./gradlew :app:testDebugUnitTest,./gradlew :app:ktlintCheck,./gradlew :app:compileDebugKotlin을 실행했고 모두 BUILD SUCCESSFUL을 확인했다. 최초 증분 컴파일에서recentContentModule,chatTalkRoomModuleunresolved가 발생했으나 해당 파일이 존재하고 tracked 상태임을 확인했으며,--rerun-tasks재실행 후 성공해 증분 캐시 문제로 분리했다. ktlint 최초 실행에서는HomeRecommendationMappers.kt의 긴 줄 2건이 실패해 줄바꿈 수정 후 재실행으로 성공했다. - 2026-06-02: Phase 5 RED 검증으로
HomeMainFragmentLayoutTest를 추가하고./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest"를 실행했다. 구현 전view_home_title_bar,text_tab_bar_home,nsv_home_recommendation_content, 섹션/RecyclerView/title icon ID가 없어 컴파일 실패하는 RED 상태를 확인했다. - 2026-06-02: Phase 5.1로
fragment_v2_main_home.xml을ConstraintLayout기반으로 구성해view_title_bar_home,view_text_tab_bar,NestedScrollView추천 content shell을 배치했다. title bar와 tab bar는 scroll container 밖에 두고, 추천 content 내부에 섹션별 container와 가로RecyclerView, 사업자 정보 영역만 추가했다.ViewPager2,FragmentStateAdapter, 랭킹/팔로잉 전용 content는 추가하지 않았다. - 2026-06-02: Phase 5.2로
view_title_bar_home.xml의 right icon을ic_bar_cash,ic_bar_search,ic_bar_bell순서로 확장하고,HomeMainFragment에서TextTabBarView메뉴를 추천/랭킹/팔로잉 순서와 selected index 0으로 바인딩했다. 좌우 swipe 전환은 추가하지 않았다. - 2026-06-02: Phase 5 GREEN/검증으로
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest",./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck를 실행했고 모두 BUILD SUCCESSFUL을 확인했다.lsp_diagnostics는kotlin-lsp미설치로 실행되지 않아 Gradle compile/test/ktlint 결과로 보완했다. - 2026-06-02: 홈 상단
TextTabBarView가 추천 화면 전용이 아니라 홈 탭 공용 탭(추천/랭킹/팔로잉)임을 반영해 string resource 이름을home_recommendation_tab_*에서screen_home_tab_*으로 변경했다. 구현 전HomeMainFragment참조만 먼저 바꾼./gradlew :app:compileDebugKotlin에서 새 string ID 미정의로 RED 실패를 확인했다. - 2026-06-02: 배너 아래 섹션 제목 요구사항을 반영해
최근 데뷔한 크리에이터,처음부터 함께 성장!,크리에이터와 이야기를 나눠요!에는view_section_title의 더보기 chevron을 표시하고,방금 활동한 크리에이터,최근 응원이 많은 크리에이터,인기 커뮤니티에는 chevron을 숨기도록HomeMainFragment에서 초기화했다. 장르 섹션은 백엔드 장르명 바인딩을 위해view_section_title을 쓰지 않고 별도 title row로 분리했으며 장르명 색상은@color/color_3bb9f1로 지정했다. 구현 전HomeMainFragmentLayoutTest에서 새 section title ID 미정의로 RED 실패를 확인했고, 이후./gradlew :app:compileDebugKotlin --rerun-tasks,./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest" --rerun-tasks,./gradlew :app:mergeDebugResources가 BUILD SUCCESSFUL임을 확인했다. 최초 병렬 Gradle 실행 중 KSP incremental cache 오류가 있었으나 순차 재실행으로 성공해 캐시 경합 문제로 분리했다. - 2026-06-02: Phase 6.1-6.4로 라이브/배너/최근 활동/최근 데뷔/첫 오디오/AI 캐릭터/장르 크리에이터/응원 크리에이터 adapter와 binder를 추가하고,
HomeMainFragment에서 빈 리스트 섹션을GONE처리하도록 바인딩했다. 배너는BannerView, 라이브는LiveThumbnailSimpleView, 첫 오디오는AudioContentCardView, AI 캐릭터는CharacterChatThumbnailView를 재사용했고, 임시 샘플 데이터는phase6SampleContent()에 격리해 Phase 9에서 실제 상태 바인딩으로 교체할 수 있게 했다. 모두 팔로우 버튼은 creatorId가 비어 있으면 callback을 호출하지 않도록 연결했다. - 2026-06-02: Phase 6 검증으로
./gradlew :app:compileDebugKotlin,./gradlew :app:testDebugUnitTest --tests kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest,./gradlew :app:mergeDebugResources,./gradlew :app:ktlintCheck,./gradlew :app:installDebug를 실행했고 모두 BUILD SUCCESSFUL을 확인했다. 최초 병렬 Gradle 실행은 Kotlin 출력 디렉터리 잠금 경합으로 실패해./gradlew --stop후 순차 재실행했다.lsp_diagnostics는kotlin-lsp미설치와 XML LSP 미구성으로 실행되지 않았다. 연결 기기에서 런처 실행은 성공했지만MainV2Activity직접 실행은exported=false로 차단되었고, 런처 경로는 splash의 검은 화면에 머물러 홈 추천 UI 실기기 육안 확인은 완료하지 못했다. - 2026-06-02: Phase 6 리뷰에서 Phase 7 전 빈
popularCommunityPosts상태에도인기 커뮤니티섹션 container가 기본 노출될 수 있음을 확인했다.HomeMainFragmentLayoutTest에popular community section is hidden until phase7 binding is implemented회귀 테스트를 추가해 수정 전 실패(AssertionError)를 확인했고,fragment_v2_main_home.xml기본 visibility와HomeMainFragment.bindPopularCommunitySection()을 추가한 뒤 동일 테스트가 BUILD SUCCESSFUL로 통과함을 확인했다. - 2026-06-02: Phase 6 수정 후
./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck,./gradlew :app:testDebugUnitTest를 재실행했고 모두 BUILD SUCCESSFUL을 확인했다. 재리뷰에서 이전인기 커뮤니티빈 섹션 노출 지적이 수정됐고, Phase 6.1-6.4 범위의 남은 승인 차단 이슈가 없다는 무조건 승인을 받았다. - 2026-06-02: Figma
24:5529기준방금 활동한 크리에이터섹션을 확인해 기존 세로 프로필형 카드가 디자인과 다름을 확인했다.HomeMainFragmentLayoutTest에recent activity creator item matches figma capsule dimensions테스트를 먼저 추가했고, 기존 구현에서 실패하는 RED 상태를 확인했다. 이후item_home_recent_activity_creator.xml을244dp x 76dp가로 capsule 구조로 변경하고HomePhase6Adapters.kt에서 보조 텍스트를activityAt으로 바인딩하도록 수정했으며, 동일 테스트가 BUILD SUCCESSFUL로 통과함을 확인했다. - 2026-06-02:
HomePhase6Adapters.kt에 모든 섹션 adapter/binder가 모여 있어 섹션별 유지보수가 어렵다는 지적에 따라 adapter/binder를 섹션 단위 파일로 분리했다.HomePhase6Adapters.kt는 삭제하고, 공통 item margin 생성 로직은HomeRecyclerItemLayoutParams.kt로 분리했다. 동작 변경 없이 파일 구조만 정리하는 리팩터링이다. - 2026-06-02: Figma
24:5516기준ll_home_live_section을 확인해 라이브 행 높이,전체item, 아이템 간격이 디자인과 다름을 확인했다.HomeMainFragmentLayoutTest에 live row 치수, live adapter item gap, 20개 초과 시전체item 추가 회귀 테스트를 먼저 추가했고, 구현 전 adapter전체view type 미지원과 20개 cap 미지원으로 RED 실패를 확인했다. 이후fragment_v2_main_home.xml에서 별도tv_home_live_moreoverlay를 제거하고,HomeLiveAdapter가 live를 최대 20개까지 표시한 뒤 20개 초과 시 마지막 item으로58dp x 102dp검은 배경전체를 추가하도록 수정했으며, 동일 테스트가 BUILD SUCCESSFUL로 통과함을 확인했다. - 2026-06-02: 라이브 섹션
전체item 방식 변경 후./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck,./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest",./gradlew :app:testDebugUnitTest를 실행했고 모두 BUILD SUCCESSFUL을 확인했다.lsp_diagnostics는 Kotlin/XML LSP 미구성으로 실행하지 못해 Gradle compile/test/ktlint로 보완했다. - 2026-06-02: Figma
24:5534기준최근 데뷔한 크리에이터섹션을 확인해 기존112dp세로 원형 profile item이 디자인과 다름을 확인했다.HomeMainFragmentLayoutTest에 recent debut 카드 치수와 목록 간격 테스트를 먼저 추가했고, 기존 구현에서recent debut creator item matches figma card dimensions,home recent debut section matches figma list spacing두 테스트가 실패하는 RED 상태를 확인했다. - 2026-06-02:
item_home_recent_debut_creator.xml을205dp x 259dp이미지 카드 구조로 변경하고, radius14dp배경/하단 dim gradient/24spbold 중앙 닉네임을 적용했다.HomeRecentDebutCreatorAdapter에는 최근 데뷔 전용4dpitem gap을 적용했고,rv_home_recent_debut_creators시작 padding을 Figma 기준14dp로 맞췄다. 동일 targeted 테스트 재실행 결과 BUILD SUCCESSFUL을 확인했다. - 2026-06-02: 최근 데뷔 수정 후
./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck는 BUILD SUCCESSFUL을 확인했다../gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest"는 이번 최근 데뷔 테스트는 통과했지만 기존home live section matches figma row dimensions가rv_home_lives높이 기대값(102dp)과 현재 XMLwrap_content가 맞지 않아 실패했다. 이후 사용자 확인에 따라rv_home_lives높이는 아이템 높이를 따라가야 하므로wrap_content가 올바른 계약으로 정정했다. - 2026-06-02: Figma
24:5539기준처음부터 함께 성장!섹션을 확인해 기존AudioContentCardView기반 item이 전용 profile row 구조와 item gap을 재현하기 어렵다는 점을 확인했다.HomeMainFragmentLayoutTest에 first audio 전용 item 치수, 목록 간격, tag visibility 테스트를 먼저 추가했고, 구현 전item_home_first_audio_content와 관련 view ID 미존재로 RED 컴파일 실패를 확인했다. - 2026-06-02:
item_home_first_audio_content.xml을 추가하고HomeFirstAudioAdapter가AudioContentCardView대신 전용 item을 inflate하도록 변경했다. 썸네일은185dp x 185dp, creator profile은42dp x 42dp, item gap은4dp로 맞췄고,First/Point/Freetag visibility는 기존tags모델로 바인딩했다../gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest"재실행 결과 BUILD SUCCESSFUL을 확인했다. - 2026-06-02: 리뷰에서 first audio 썸네일 이미지 clipping과
Freetag visibility 테스트 누락이 차단 이슈로 지적되어item_home_first_audio_content.xml에clipToOutline="true"를 추가하고HomeMainFragmentLayoutTest에서First/Point/Free개별 tag visibility를 모두 검증하도록 보강했다. 이후./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest",./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck,./gradlew :app:testDebugUnitTest를 실행했고 모두 BUILD SUCCESSFUL을 확인했다. - 2026-06-02: first audio adapter에서 nullable image URL이 재사용된 ViewHolder의 이전 이미지를 남길 수 있는 케이스를 확인했다.
first audio adapter clears nullable images테스트를 추가해 수정 전 실패를 확인한 뒤,HomeFirstAudioAdapter에서coverImage/creatorProfileImage가 null이면 drawable을 명시적으로 비우도록 수정했다. 이후 해당 테스트,HomeMainFragmentLayoutTest전체,./gradlew :app:compileDebugKotlin,./gradlew :app:mergeDebugResources,./gradlew :app:ktlintCheck,./gradlew :app:testDebugUnitTest를 실행했고 모두 BUILD SUCCESSFUL을 확인했다. - 2026-06-02: first audio 썸네일은 이미지뿐 아니라
FIRST/Point/Freeoverlay까지 같은 radius로 잘려야 한다는 사용자 확인에 따라 Coil transformation 방식이 아니라 썸네일 parentFrameLayout전체에 KotlinclipToOutline = true와ViewOutlineProvider.setRoundRect(..., 14dp)를 적용했다. XMLandroid:clipToOutline은 lint 경고를 피하기 위해 사용하지 않았다.first audio adapter clips thumbnail container테스트를 추가했고,./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest",./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck,./gradlew :app:testDebugUnitTest를 실행해 모두 BUILD SUCCESSFUL을 확인했다. - 2026-06-02:
AudioContentCardView의 이미지 표시 영역도 first audio 전용 item과 동일하게 이미지와 overlay tag가 함께 roundRect clipping되도록 확인하고,First/Point/Freetag 속성을item_home_first_audio_content.xml과 맞췄다.HomeMainFragmentLayoutTest에audio content card clips image area and overlay tags together,audio content card tag attributes match first audio item회귀 테스트를 추가했다../gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest",./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck,./gradlew :app:testDebugUnitTest를 실행했고 모두 BUILD SUCCESSFUL을 확인했다. - 2026-06-02:
AudioContentCardView와item_home_first_audio_content.xml의 badge별 제어를 위해Original/First/Point/Freebadge에 안정적인 id를 추가했다.AudioContentCardView의 runtime 생성 badge에도 동일 id를 부여하고,First와Freebadge 높이를24dp로 유지하도록 맞췄다.HomeMainFragmentLayoutTest에서 badge id/높이 계약을 검증하도록 보강했으며./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest",./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck,./gradlew :app:testDebugUnitTest를 실행해 모두 BUILD SUCCESSFUL을 확인했다. - 2026-06-02: Figma
24:5551기준크리에이터와 이야기를 나눠요!섹션을 확인해 기존 목록 padding20dp, adapter item gap12dp, genericRecyclerView.LayoutParams(WRAP_CONTENT, WRAP_CONTENT)적용이view_character_chat_thumbnail.xml의 root185dp x wrap_content계약을 보존하지 못함을 확인했다.HomeMainFragmentLayoutTest에 character thumbnail root 치수, AI 캐릭터 목록 spacing, adapter item dimension 회귀 테스트를 먼저 추가했고, 수정 전 targeted test에서 새 테스트 2건 실패로 RED를 확인했다. - 2026-06-02:
rv_home_ai_characterspadding을14dp로 맞추고,HomeAiCharacterAdapter에서 inflate된view_character_chat_thumbnail.xmlroot layout params를 유지한 채marginEnd만4dp로 적용했다. 수정 후./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest",./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck를 실행했고 모두 BUILD SUCCESSFUL을 확인했다.lsp_diagnostics는 Kotlin/XML LSP 미구성으로 실행하지 못해 Gradle compile/test/ktlint로 보완했다. - 2026-06-04: Figma
24:5611, 완료 버튼24:9092기준 장르 크리에이터 모두 팔로우 버튼을 확인해 기본 상태는ic_new_follow, 투명 배경과 흰색 30% stroke, 흰색 텍스트이고 완료 상태는ic_new_following, 흰색 배경, 검은색 텍스트여야 함을 확인했다.HomeMainFragmentLayoutTest에 모두 팔로우 기본/완료 상태와 완료 상태 no-op 회귀 테스트를 먼저 추가했고, 구현 전bg_home_follow_all_button리소스 미존재로 RED 컴파일 실패를 확인했다. - 2026-06-04:
bg_home_follow_all_button.xml을 추가하고view_home_follow_all_button.xml의 기본 상태를 Figma 활성 상태로 변경했다.HomeFollowAllButtonBinder는 완료 상태에서bg_round_corner_999_white, 검은 텍스트,ic_new_following,모두 팔로우 완료를 적용하고 터치 시 callback을 호출하지 않도록 수정했다. 이후./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest",./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck,./gradlew :app:testDebugUnitTest를 실행했고 모두 BUILD SUCCESSFUL을 확인했다../gradlew :app:installDebug는 연결된 기기가 없어No connected devices!로 실패해 실기기 설치 확인은 수행하지 못했다.