Files
sodalive-android/docs/20260601_메인_홈_추천_UI와_API_연동/plan-task.md

24 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 하위에 둔다. 화면은 HomeMainFragmentfragment_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.ktnetworkModule, 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/recommendations
      • POST /api/v2/home/recommendations/creators/follow
      • FollowRecommendedCreatorsRequest(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
    • 구현 내용:
      • networkModuleHomeRecommendationApi 등록
      • repositoryModuleHomeRecommendationRepository 등록
      • 이후 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_live
      • AUDIO -> R.string.home_recommendation_activity_audio
      • COMMUNITY -> 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이면 기존 CharacterChatThumbnailViewshouldShowOriginalTitle = false
      • HomePopularCommunityPostItemprice, existOrdered 기반 유료 상태 모델
    • 검증: DTO를 Fragment/ViewHolder에 직접 노출하지 않는다.
  • Task 4.2: ViewModel 생성

    • 생성: app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeRecommendationViewModel.kt
    • 구현 내용:
      • recommendationStateLiveData
      • toastLiveData
      • isLoading
      • loadRecommendations()
      • 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_home
      • TextTabBarView
      • TextTabBarView 아래 추천 content 전용 세로 NestedScrollView 또는 동등한 scroll container
      • 추천 content 내부 섹션별 컨테이너와 가로 RecyclerView
      • 추천 content 내부 사업자 정보 영역
    • 제외:
      • ViewPager2
      • FragmentStateAdapter
      • 랭킹, 팔로잉용 별도 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는 생성하지 않음
    • 검증: 앱 실행 시 상단 bar와 tab이 표시되고 text resource가 적용된다. 좌우 swipe로 tab 전환이 발생하지 않는다.

Phase 6: 섹션 adapter와 재사용 위젯 바인딩

Phase 6까지는 실제 API/ViewModel 연동 전 단계이므로, 실제 기기에서 UI 배치와 섹션 표시 형태를 확인할 수 있도록 Fragment 또는 adapter 호출부에 샘플 데이터를 임시 주입할 수 있다. 샘플 데이터는 Phase 9의 실제 HomeRecommendationViewModel observe/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 == trueAudioContentTag.Point
      • price == 0이면 AudioContentTag.Free
      • AudioContentTag.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 호출하지 않고 버튼 상태 유지.

Phase 7: FeedCommunityView 추천 페이지 확장

  • Task 7.1: FeedItem.Community 추천 필드 확장

    • 수정: app/src/main/java/kr/co/vividnext/sodalive/v2/widget/feed/FeedItem.kt
    • 추가 후보:
      • imageUrl: String?
      • price: Int
      • existOrdered: Boolean
      • showKeyword: 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, radius 14dp, 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() 호출
      • recommendationStateLiveData observe 후 각 섹션 bind
      • isLoading은 기존 LoadingDialog 또는 홈 화면 패턴 확인 후 적용
      • toastLiveDataBaseFragment.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.ktnetworkModule/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_diagnosticskotlin-lsp 미설치로 실행되지 않아 Gradle compile/test/ktlint 결과로 보완했다.
  • 2026-06-02: 백엔드 activity type code가 대소문자와 무관하게 들어와도 매핑되도록 RecommendedActivityTypeTestlive, 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.ktHomeRecommendationViewModel import와 viewModel { HomeRecommendationViewModel(get()) } 등록을 추가했다. lsp_diagnosticskotlin-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, chatTalkRoomModule unresolved가 발생했으나 해당 파일이 존재하고 tracked 상태임을 확인했으며, --rerun-tasks 재실행 후 성공해 증분 캐시 문제로 분리했다. ktlint 최초 실행에서는 HomeRecommendationMappers.kt의 긴 줄 2건이 실패해 줄바꿈 수정 후 재실행으로 성공했다.