Files
sodalive-android/docs/20260611_크리에이터_채널_홈_탭/plan-task.md

200 KiB

크리에이터 채널 홈 탭 구현 계획/TASK

For agentic workers: 구현 시 superpowers:subagent-driven-development 또는 superpowers:executing-plans를 사용해 task 단위로 진행한다. 각 단계는 체크박스(- [ ])로 추적하고, 완료 즉시 - [x]로 갱신한다.

Goal: GET /api/v2/creator-channels/{creatorId}/home 응답을 기반으로 크리에이터 채널 신규 페이지의 상단 구성과 탭 컨텐츠를 표시한다.

Architecture: 신규 화면은 kr.co.vividnext.sodalive.v2.creator.channel 하위에 Activity, ViewModel, data/model/ui 패키지를 두고 기존 Retrofit + RxJava3 + ApiResponse<T> + Koin 패턴을 따른다. RecommendedActivityType은 홈 추천 전용 이름을 제거해 공용 CreatorActivityType으로 이동하고, 홈 추천과 크리에이터 채널 홈이 같은 타입을 참조하게 한다. UI는 Android XML Views/ViewBinding 기반으로 구성하고, 홈 탭 외 다른 탭 상세 화면은 이번 범위에서 연결하지 않는다.

Tech Stack: Kotlin, Android XML Views, ViewBinding, RecyclerView/NestedScroll, Retrofit, Gson, RxJava3, Koin, JUnit4/Robolectric local unit test.


전제와 성공 기준

  • PRD: docs/20260611_크리에이터_채널_홈_탭/prd.md
  • Figma 전체 페이지: 296:14890
  • 크리에이터 이미지 영역: 296:14892
  • title-bar 상태별 Figma:
    • 팔로우 상태가 아님: 296:14287
    • 팔로우 중 + 알림 받기 중: 296:14288
    • 팔로우 중 + 알림 받기 중이 아님: 296:14289
  • 이번 범위는 크리에이터 채널 전체 구성과 탭에 한정한다.
  • tab-bar 목록은 , 라이브, 오디오, 시리즈, 커뮤니티, 팬Talk, 후원 순서를 따른다.
  • 라이브, 오디오, 시리즈, 커뮤니티, 팬Talk, 후원 탭의 상세 컨텐츠와 pagination은 구현하지 않는다.
  • 홈 API는 GET /api/v2/creator-channels/{creatorId}/home을 사용한다.
  • 팔로우/알림 변경은 기존 UserRepository.creatorFollow() API 사용 패턴을 재사용한다.
  • Phase 11 이후 팔로잉 상태의 알림 끄기/팔로우 취소는 CreatorFollowNotifyFragment를 띄우지 않고 즉시 API를 호출하는 방식으로 보정한다.
  • 대화하기TalkApi.createChatRoom 호출 후 반환된 chatRoomIdChatRoomActivity, DM 보내기DmChatRoomActivity.newIntentByCreatorId()로 이동한다.
  • title-bar black 전환 기준은 title-bar와 tab-bar의 실제 거리 및 프로필 이미지가 절반 이상 사라졌는지를 함께 사용한다.
  • 구현 완료 후 최소 다음 명령을 실행한다.
    • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.common.*"
    • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*"
    • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*"
    • ./gradlew :app:mergeDebugResources
    • ./gradlew :app:compileDebugKotlin
    • ./gradlew :app:ktlintCheck

Figma 참조 필요 Phase

  • Phase 1: 부분 참조
    • 구현 범위 확인 시 PRD의 Figma 노드 기준만 확인한다.
    • 실제 치수/레이어 구현 판단은 하지 않는다.
  • Phase 2: Figma 참조 불필요
    • CreatorActivityType 공용화는 서버 타입/기존 홈 추천 타입 정리 작업이다.
  • Phase 3: Figma 참조 불필요
    • API/DTO/Repository는 서버 계약과 기존 네트워크 패턴만 따른다.
  • Phase 4: 부분 참조
    • CreatorChannelHomeSection 순서와 section 표시 여부를 Figma 296:14890 홈 구성 기준으로 맞출 때 참조한다.
    • title-bar 아이콘 상태 자체는 PRD와 리소스명으로 검증 가능하지만, 우측 액션 배치 우선순위는 Figma 상태별 노드 296:14287, 296:14288, 296:14289를 확인한다.
  • Phase 5: 필수 참조
    • activity_creator_channel_home.xml, title-bar overlay, 크리에이터 이미지 영역, 버튼 영역 보존/중앙 정렬, tab-bar 배치, 홈 section item layout은 Figma 296:14890, 296:14892, 296:14287, 296:14288, 296:14289를 기준으로 구현한다.
  • Phase 6: 필수 참조
    • sticky tab-bar 위치, title-bar와 tab-bar가 가까워지는 시점, 프로필 이미지가 절반 이상 사라지는 기준을 실제 화면 배치와 비교해야 하므로 Figma 296:14890296:14892를 참조한다.
  • Phase 7: 부분 참조
    • 팔로우/알림 API 연결은 Figma가 필요 없지만, tab-bar 7개 항목의 시각 표시와 title-bar 아이콘 click target 배치는 Figma 기준을 확인한다.
  • Phase 8: 필수 참조
    • 수동 화면 검증은 Figma와 실제 구현 화면을 비교해 PRD Metrics를 확인한다.
  • Phase 10: 부분 참조
    • TabLayout + ViewPager2 + 탭별 Fragment 전환은 PRD의 Future Tab Architecture Decision과 기존 AndroidX/Material 사용 패턴을 기준으로 한다.
  • Phase 11: 부분 참조
    • title-bar 닉네임, tab-bar typography, 더보기 BottomSheet, 팔로우/알림 직접 액션은 PRD와 기존 구현 패턴을 기준으로 한다.
    • tab-bar item font/size는 Figma 296:14894를 확인한다.
  • Phase 12: 필수 참조
    • 후원 empty UI는 Figma 290:8820, 활동 영역은 Figma 296:15001, 홈 컨텐츠 보정은 Figma 296:14895를 기준으로 한다.
  • Phase 13: 필수 참조
    • 크리에이터 본인 페이지 Floating Button 기본 상태는 Figma 665:19221, 확장/dim 상태는 Figma 665:19352를 기준으로 한다.
  • Phase 14: 필수 참조
    • 최종 수동 검증은 Figma 296:14890, 296:14894, 296:14895, 290:8820, 296:15001, 665:19221, 665:19352를 함께 대조한다.

파일 구조

  • 생성: app/src/main/java/kr/co/vividnext/sodalive/v2/common/CreatorActivityType.kt
    • 기존 RecommendedActivityType을 대체하는 공용 활동 타입을 정의한다.
  • 수정/삭제 후보: app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/RecommendedActivityType.kt
    • 공용 타입 이동 후 기존 파일은 제거하거나 호환 alias가 반드시 필요한 경우 최소 범위로 남긴다.
  • 수정: app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/HomeRecommendationMappers.kt
    • RecommendedActivityType 참조를 CreatorActivityType으로 변경한다.
  • 수정: app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/HomeRecommendationUiModels.kt
    • 최근 활동 크리에이터 UI 모델의 타입을 공용 CreatorActivityType으로 변경한다.
  • 수정: app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/RecommendedActivityTypeTest.kt
    • 테스트명을 유지하거나 CreatorActivityTypeTest로 이동해 공용 타입 검증으로 변경한다.
  • 생성: app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeActivity.kt
    • 크리에이터 채널 홈 화면, intent 진입, edge-to-edge/inset, title/tab scroll, click 연결을 담당한다.
  • 생성: app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeViewModel.kt
    • 홈 API 호출, 팔로우/알림 변경, loading/error/content 상태를 관리한다.
  • 생성: app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/data/CreatorChannelHomeApi.kt
    • GET /api/v2/creator-channels/{creatorId}/home endpoint를 정의한다.
  • 생성: app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/data/CreatorChannelHomeModels.kt
    • PRD의 서버 DTO를 Android DTO로 정의한다.
  • 생성: app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/data/CreatorChannelHomeRepository.kt
    • 홈 API, 기존 크리에이터 팔로우 API, 기존 TalkApi.createChatRoom 호출을 ViewModel에 제공한다.
  • 생성: app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/model/CreatorChannelHomeUiModels.kt
    • 화면 상태, tab 항목, header/action/home section UI model을 정의한다.
  • 생성: app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/model/CreatorChannelHomeMappers.kt
    • API 응답을 UI model로 변환한다.
  • 생성: app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/model/CreatorChannelTitleBarState.kt
    • 팔로우/알림 조합별 title-bar 아이콘 상태와 버튼 표시 상태를 순수 모델로 정의한다.
  • 생성: app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/model/CreatorChannelScrollState.kt
    • title-bar black 전환과 tab-bar sticky 기준을 순수 함수로 계산한다.
  • 생성: app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt
    • 홈 탭 section 목록을 RecyclerView로 표시한다.
  • 생성 후보: app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelTabAdapter.kt
    • 기존 TextTabBarView로 7개 탭 표시가 어렵거나 Figma tab-bar와 맞지 않을 때만 추가한다.
  • 생성: app/src/main/res/layout/activity_creator_channel_home.xml
    • 크리에이터 이미지 영역, title-bar, tab-bar, 홈 컨텐츠 RecyclerView를 포함한 화면 레이아웃이다.
  • 생성: app/src/main/res/layout/item_creator_channel_home_*.xml
    • 홈 탭 섹션별 item layout을 필요한 만큼 추가한다.
  • 수정: app/src/main/AndroidManifest.xml
    • CreatorChannelHomeActivity를 등록한다.
  • 수정: app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt
    • 신규 API, Repository, ViewModel을 Koin에 등록한다.
  • 테스트 생성/수정:
    • 생성: app/src/test/java/kr/co/vividnext/sodalive/v2/common/CreatorActivityTypeTest.kt
    • 생성: app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeMapperTest.kt
    • 생성: app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelTitleBarStateTest.kt
    • 생성: app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelScrollStateTest.kt
    • 생성: app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeViewModelTest.kt
    • 생성: app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.kt

Phase 1: 기존 구조 확인과 작업 경계 고정

  • Task 1.1: 기존 v2 홈/채팅/팔로우 구조 확인

    • 확인:
      • 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/user/UserRepository.kt
      • app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/CreatorFollowNotifyFragment.kt
      • app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatRoomActivity.kt
      • app/src/main/java/kr/co/vividnext/sodalive/chat/talk/TalkApi.kt
      • app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/CreateChatRoomRequest.kt
      • app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/CreateChatRoomResponse.kt
      • app/src/main/java/kr/co/vividnext/sodalive/chat/character/detail/detail/CharacterDetailViewModel.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/chat/dm/DmChatRoomActivity.kt
      • app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt
    • 검증:
      • REST는 Retrofit + RxJava3 + ApiResponse<T> 패턴을 따른다.
      • AI 채팅 이동은 TalkApi.createChatRoom(CreateChatRoomRequest(characterId)) 호출 후 CreateChatRoomResponse.chatRoomId를 받아 ChatRoomActivity.newIntent(context, roomId)로 이동하는 패턴을 따른다.
      • DM 이동은 DmChatRoomActivity.newIntentByCreatorId(context, creatorId)를 사용할 수 있음을 확인한다.
      • 팔로우/알림 변경은 UserRepository.creatorFollow(creatorId, follow, notify, token)를 재사용할 수 있음을 확인한다.
  • Task 1.2: 구현 제외 범위 재확인

    • 확인:
      • docs/20260611_크리에이터_채널_홈_탭/prd.md
    • 제외:
      • 라이브, 오디오, 시리즈, 커뮤니티, 팬Talk, 후원 탭 상세 화면
      • 홈 탭 pagination
      • 신규 팔로우/알림 API
      • ChatRoomActivity, DmChatRoomActivity 내부 동작 변경
      • 별도 analytics/logging
    • 검증:
      • 이후 Phase의 모든 Task가 위 제외 범위를 침범하지 않는지 확인한다.

Phase 2: CreatorActivityType 공용화

  • Task 2.1: 공용 활동 타입 RED 테스트 작성

    • 생성:
      • app/src/test/java/kr/co/vividnext/sodalive/v2/common/CreatorActivityTypeTest.kt
    • 수정:
      • app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/RecommendedActivityTypeTest.kt
    • 작업:
      • LIVE, LIVE_REPLAY, AUDIO, COMMUNITY가 대소문자 무시로 파싱되는지 검증한다.
      • 각 타입의 label resource가 기존 RecommendedActivityType과 동일한지 검증한다.
      • 알 수 없는 code는 null을 반환하는지 검증한다.
      • 대소문자 무시 파싱은 홈 추천 등 클라이언트 helper 호환성 검증이며, 크리에이터 채널 홈 API의 서버 enum 계약은 대문자 code만 내려오는 것으로 본다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.common.CreatorActivityTypeTest"
    • 기대 결과:
      • 공용 타입 미구현으로 RED 실패한다.
  • Task 2.2: CreatorActivityType 생성 및 홈 추천 참조 변경

    • 생성:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/common/CreatorActivityType.kt
    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/HomeRecommendationMappers.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/HomeRecommendationUiModels.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragmentLayoutTest.kt
    • 삭제 후보:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/RecommendedActivityType.kt
    • 작업:
      • 기존 enum 값과 code, labelResId를 그대로 유지해 CreatorActivityType을 생성한다.
      • HomeRecommendationRecentlyActiveCreatorUiModel.activityType 타입을 CreatorActivityType?으로 변경한다.
      • HomeRecommendationMappers.kt의 parser helper 이름은 toCreatorActivityTypeLabelRes()로 변경하거나, 기존 테스트 호환을 위해 같은 파일 안에서 최소 alias만 유지한다.
      • 홈 추천 테스트의 import와 enum 참조를 CreatorActivityType으로 변경한다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.common.CreatorActivityTypeTest"
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*"
    • 기대 결과:
      • 공용 타입 테스트와 기존 홈 추천 테스트가 PASS한다.

Phase 3: 크리에이터 채널 홈 API/DTO/Repository 추가

  • Task 3.1: API DTO와 endpoint 정의

    • 생성:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/data/CreatorChannelHomeApi.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/data/CreatorChannelHomeModels.kt
    • 작업:
      • PRD의 CreatorChannelHomeResponse와 하위 DTO를 모두 @Keep, @SerializedName 기반 data class로 추가한다.
      • CreatorChannelCreatorResponse에는 creatorId: LongcharacterId: Long?를 모두 추가한다.
      • CreatorChannelScheduleResponse.type은 공용 CreatorActivityType을 사용한다.
      • 백엔드 CreatorActivityType 원본 enum은 LIVE, AUDIO, COMMUNITY, LIVE_REPLAY 대문자 code를 내려주므로 DTO에서 공용 enum을 직접 사용하는 것을 정상 계약으로 본다.
      • 이후 코드리뷰에서는 별도 서버 계약 변경 근거가 없는 한 type 대소문자 불일치 대응 또는 Gson enum TypeAdapter 부재를 문제로 보지 않는다.
      • Retrofit endpoint는 @GET("/api/v2/creator-channels/{creatorId}/home")로 정의한다.
      • 반환 타입은 Single<ApiResponse<CreatorChannelHomeResponse>>를 사용한다.
    • 검증 명령:
      • ./gradlew :app:compileDebugKotlin
    • 기대 결과:
      • 신규 DTO와 API가 컴파일된다.
  • Task 3.2: Repository 추가

    • 생성:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/data/CreatorChannelHomeRepository.kt
    • 작업:
      • getHome(creatorId: Long, token: String)에서 홈 API를 호출한다.
      • 기존 UserRepository를 생성자 인자로 받아 followCreator(creatorId, follow, notify, token)를 얇게 위임한다.
      • 기존 TalkApi를 생성자 인자로 받아 createChatRoom(characterId, token)에서 CreateChatRoomRequest(characterId)TalkApi.createChatRoom을 호출한다.
      • token 문자열은 기존 ViewModel 패턴과 맞춰 ViewModel에서 "Bearer ${SharedPreferenceManager.token}"로 만든다.
    • 검증 명령:
      • ./gradlew :app:compileDebugKotlin
    • 기대 결과:
      • Repository가 기존 DI 패턴과 충돌 없이 컴파일된다.
  • Task 3.3: Koin DI 등록

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt
    • 작업:
      • CreatorChannelHomeApi, CreatorChannelHomeRepository, CreatorChannelHomeViewModel import를 추가한다.
      • networkModulesingle { ApiBuilder().build(get(), CreatorChannelHomeApi::class.java) }를 추가한다.
      • 기존 networkModuleTalkApi 등록을 재사용한다.
      • repositoryModulefactory { CreatorChannelHomeRepository(api = get(), userRepository = get(), talkApi = get()) }를 추가한다.
      • viewModelModuleviewModel { CreatorChannelHomeViewModel(get()) }를 추가한다.
      • 참고: Phase 3 현재 구현에서는 CreatorChannelHomeViewModel 클래스가 Phase 4 산출물이므로 컴파일을 깨지 않기 위해 ViewModel DI 등록은 Phase 4로 보류하고, API/Repository 등록만 완료했다.
    • 검증 명령:
      • ./gradlew :app:compileDebugKotlin
    • 기대 결과:
      • Koin 등록과 import가 컴파일된다.

Phase 4: UI 모델/매퍼/ViewModel 구현

  • Task 4.1: 홈 응답 매퍼 RED 테스트 작성

    • 생성:
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeMapperTest.kt
    • 작업:
      • creator.characterId, creator.isFollow, creator.isNotify, creator.isAiChatAvailable, creator.isDmAvailable가 UI model에 그대로 반영되는지 검증한다.
      • tab 목록이 , 라이브, 오디오, 시리즈, 커뮤니티, 팬Talk, 후원 순서인지 검증한다.
      • currentLive, latestAudioContent가 null이면 해당 홈 section이 생성되지 않는지 검증한다.
      • 빈 list는 crash 없이 빈 section 또는 hidden section 정책으로 매핑되는지 검증한다.
      • SNS URL이 빈 문자열이면 해당 SNS item이 숨김 또는 disabled 상태로 매핑되는지 검증한다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeMapperTest"
    • 기대 결과:
      • UI model/mapper 미구현으로 RED 실패한다.
  • Task 4.2: UI model과 mapper 구현

    • 생성:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/model/CreatorChannelHomeUiModels.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/model/CreatorChannelHomeMappers.kt
    • 작업:
      • CreatorChannelHomeUiState.Loading, Content, Empty, Error를 정의한다.
      • CreatorChannelTab.Home, Live, Audio, Series, Community, FanTalk, Donation을 정의한다.
      • CreatorChannelHeaderUiModelcreatorId, characterId, nickname, profileImageUrl, followerCount, isFollow, isNotify, isAiChatAvailable, isDmAvailable을 둔다.
      • 홈 section은 Figma 순서에 맞춰 sealed interface CreatorChannelHomeSection으로 정의한다.
      • CreatorChannelHomeResponse.toUiContent() 매퍼를 구현한다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeMapperTest"
    • 기대 결과:
      • 매퍼 테스트가 PASS한다.
  • Task 4.3: title-bar 상태 순수 모델 테스트와 구현

    • 생성:
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelTitleBarStateTest.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/model/CreatorChannelTitleBarState.kt
    • 작업:
      • isFollow=false이면 follow icon은 ic_new_follow, bell icon은 없음으로 계산한다.
      • isFollow=true && isNotify=true이면 follow icon은 ic_new_following, bell icon은 ic_bar_bell_colored로 계산한다.
      • isFollow=true && isNotify=false이면 follow icon은 ic_new_following, bell icon은 ic_bar_bell로 계산한다.
      • 상태 변경 중에는 중복 클릭 방지를 위한 isActionEnabled=false 상태를 표현한다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelTitleBarStateTest"
    • 기대 결과:
      • title-bar 상태 테스트가 PASS한다.
  • Task 4.4: ViewModel RED 테스트와 구현

    • 생성:
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeViewModelTest.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeViewModel.kt
    • 작업:
      • loadHome(creatorId)creatorId > 0일 때만 홈 API를 호출한다.
      • API 성공 시 CreatorChannelHomeUiState.Content를 발행한다.
      • API 실패 또는 exception 시 Error와 unknown error toast를 발행한다.
      • follow(follow, notify)는 기존 팔로우 API를 호출하고 성공 시 로컬 header의 isFollow, isNotify를 갱신한다.
      • createChatRoom(characterId)characterId > 0일 때만 TalkApi.createChatRoom 위임 API를 호출하고, 성공 시 ChatRoomActivity 이동에 사용할 chatRoomId 이벤트를 발행한다.
      • 팔로우/알림 변경 중에는 중복 요청을 막는다.
      • 채팅방 생성 중에는 중복 요청을 막는다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeViewModelTest"
    • 기대 결과:
      • ViewModel 테스트가 PASS한다.

Phase 5: 레이아웃과 홈 탭 UI 연결

  • Task 5.1: 화면 layout 생성

    • 생성:
      • app/src/main/res/layout/activity_creator_channel_home.xml
    • 작업:
      • root는 CoordinatorLayout, ConstraintLayout, NestedScrollView/RecyclerView 중 기존 sticky 구현에 가장 적합한 구조를 선택한다.
      • 크리에이터 이미지 영역은 status bar 영역까지 확장 가능하게 상단에 배치한다.
      • title-bar는 이미지 위 overlay로 배치하고 ic_new_bar_back, ic_new_more를 사용한다.
      • follow, following, bell icon view를 title-bar 우측에 배치한다.
      • 대화하기, DM 보내기 버튼 영역은 버튼이 없어도 높이를 보존할 수 있는 container로 만든다.
      • tab-bar는 7개 긴 라벨이 가로 폭을 초과해도 표시되도록 HorizontalScrollView + 동적 TextView container로 만든다.
      • 각 tab 이름은 하드코딩 문자열이 아니라 CreatorChannelTab.labelResIdvalues, values-en, values-ja string resource를 사용한다.
      • 홈 컨텐츠는 RecyclerView 또는 기존 섹션 패턴에 맞는 container로 둔다.
    • 검증 명령:
      • ./gradlew :app:mergeDebugResources
    • 기대 결과:
      • 신규 layout과 drawable 참조가 resource merge를 통과한다.
  • Task 5.2: 홈 섹션 Adapter와 item layout 추가

    • 생성:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt
      • app/src/main/res/layout/item_creator_channel_home_live.xml
      • app/src/main/res/layout/item_creator_channel_home_latest_audio.xml
      • app/src/main/res/layout/item_creator_channel_home_donation.xml
      • app/src/main/res/layout/item_creator_channel_home_notice.xml
      • app/src/main/res/layout/item_creator_channel_home_schedule.xml
      • app/src/main/res/layout/item_creator_channel_home_audio.xml
      • app/src/main/res/layout/item_creator_channel_home_series.xml
      • app/src/main/res/layout/item_creator_channel_home_community.xml
      • app/src/main/res/layout/item_creator_channel_home_fantalk.xml
      • app/src/main/res/layout/item_creator_channel_home_introduce.xml
      • app/src/main/res/layout/item_creator_channel_home_activity.xml
      • app/src/main/res/layout/item_creator_channel_home_sns.xml
    • 작업:
      • 모든 section을 한 번에 과하게 완성하지 말고, API 필드를 화면에 표시할 최소 텍스트/이미지 영역부터 연결한다.
      • 기존 AudioContentCardView, SeriesContentCardView, FeedAdapter, LiveThumbnail* 위젯을 재사용할 수 있는 section은 우선 재사용한다.
      • 빈 list 또는 null section은 adapter item으로 추가하지 않는다.
    • 검증 명령:
      • ./gradlew :app:mergeDebugResources
      • ./gradlew :app:compileDebugKotlin
    • 기대 결과:
      • section adapter와 item layout이 컴파일된다.
  • Task 5.3: Activity 생성 및 ViewModel observe 연결

    • 생성:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeActivity.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeActivitySourceTest.kt
    • 수정:
      • app/src/main/AndroidManifest.xml
    • 작업:
      • EXTRA_CREATOR_IDnewIntent(context, creatorId)를 추가한다.
      • 7개 tab은 content.tabs를 순회하며 getString(tab.labelResId)로 생성한다.
      • creatorId <= 0이면 API 호출 없이 finish한다.
      • onCreate에서 ViewModel observe, adapter, tab-bar, title-bar click listener를 연결한다.
      • onCreate 또는 onStart에서 viewModel.loadHome(creatorId)를 호출한다.
      • Manifest에 Activity를 등록한다.
      • Source test에서 HorizontalScrollView 탭 구조, string resource 기반 탭명, 채팅/DM 이동 계약, Manifest 등록, CreatorFollowNotifyFragment 미참조를 검증한다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest"
      • ./gradlew :app:compileDebugKotlin
    • 기대 결과:
      • intent extra, invalid creatorId 처리, Manifest 등록 검증이 PASS한다.
  • Task 5.4: title-bar와 이미지 영역 bind 구현

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeActivity.kt
    • 작업:
      • creator.profileImageUrl, nickname, followerCount를 이미지 영역에 표시한다.
      • CreatorChannelTitleBarState에 따라 ic_new_follow, ic_new_following, ic_bar_bell_colored, ic_bar_bell을 표시한다.
      • title-bar 초기 배경은 투명 overlay로 시작한다.
      • 뒤로가기는 finish()로 처리한다.
      • 더보기는 기존 프로필/크리에이터 더보기 메뉴 패턴을 확인해 최소 연결하거나, 기존 패턴이 명확하지 않으면 click handler만 분리하고 후속 구현 대상으로 남긴다.
    • 검증 명령:
      • ./gradlew :app:compileDebugKotlin
    • 기대 결과:
      • header/title bind가 컴파일된다.
  • Task 5.5: 대화하기/DM 버튼 표시와 이동 연결

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeActivity.kt
    • 작업:
      • isAiChatAvailable=false이거나 characterId == null이면 대화하기 버튼을 숨긴다.
      • isDmAvailable=false이면 DM 보내기 버튼을 숨긴다.
      • 두 버튼 중 하나만 보일 때는 버튼 container 안에서 가운데 정렬한다.
      • 두 버튼이 모두 숨김이어도 버튼 영역 container 높이는 유지한다.
      • 대화하기는 ViewModel의 createChatRoom(characterId)를 호출한다.
      • 채팅방 생성 성공 이벤트의 chatRoomId를 받아 ChatRoomActivity.newIntent(context, roomId)로 이동한다.
      • 채팅방 생성 실패 시 기존 unknown error toast 패턴을 따른다.
      • DM 보내기DmChatRoomActivity.newIntentByCreatorId(context, creatorId)로 이동한다.
    • 검증 명령:
      • ./gradlew :app:compileDebugKotlin
    • 기대 결과:
      • 버튼 표시 조건과 AI 채팅/DM 이동이 컴파일된다.
  • Task 5.6: Phase 5 코드 리뷰 지적 title-bar capsule 구조 수정

    • 수정:
      • app/src/main/res/layout/activity_creator_channel_home.xml
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeActivity.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeActivitySourceTest.kt
    • 생성:
      • app/src/main/res/drawable/bg_creator_channel_follow_capsule.xml
      • app/src/main/res/drawable/bg_creator_channel_following_capsule.xml
    • 작업:
      • Figma 296:14287의 미팔로우 상태는 follow icon + 팔로우 텍스트가 하나의 capsule 안에 표시되도록 구성한다.
      • Figma 296:14288, 296:14289의 팔로우 상태는 흰색 원형 capsule 안 follow icon, 별도 bell icon, 별도 more icon 구조로 표시되도록 구성한다.
      • 기존 tv_followiv_follow가 배경 없이 나란히 놓인 구조를 제거한다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest"
      • ./gradlew :app:mergeDebugResources
      • ./gradlew :app:compileDebugKotlin
    • 기대 결과:
      • title-bar 상태별 capsule 구조 source 계약과 리소스/컴파일이 PASS한다.
  • Task 5.7: Phase 5 코드 리뷰 지적 홈 섹션 데이터 보존 수정

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt
      • app/src/main/res/values/strings.xml
      • app/src/main/res/values-en/strings.xml
      • app/src/main/res/values-ja/strings.xml
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeActivitySourceTest.kt
    • 작업:
      • 모든 section을 tv_section_title/tv_primary/tv_secondary/iv_thumbnail 공통 카드 하나로 동일 처리하던 바인딩을 section별 bind* 함수로 분리한다.
      • 오디오/시리즈/커뮤니티/SNS 등 list section은 firstOrNull() 또는 단일 joinToString() 축약으로 주요 데이터를 버리지 않고 여러 항목 텍스트를 줄 단위로 보존한다.
      • 활동 section은 debutDateUtc, liveCount, liveDurationHours, liveContributorCount, audioContentCount, seriesCount를 모두 resource format으로 표시한다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest"
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*"
      • ./gradlew :app:ktlintCheck
    • 기대 결과:
      • section별 데이터 보존 source 계약, creator channel 테스트, ktlint가 PASS한다.
  • Task 5.8: Phase 5 코드 리뷰 Findings 반영

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeActivity.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeActivitySourceTest.kt
    • 작업:
      • 시리즈 가로 타일 row는 화면 밖으로 잘리지 않도록 가로 스크롤 가능한 컨테이너에 넣는다.
      • SNS 버튼은 CreatorChannelSnsUiItem.url을 사용해 외부 링크 intent를 실행할 수 있게 한다.
      • 일정 타입은 서버 code가 아니라 CreatorActivityType.labelResId 기반 다국어 label로 표시한다.
      • 크리에이터 채널 홈 화면은 어두운 헤더 위 status bar icon 가독성을 위해 light status bar를 끈다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest"
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*"
      • ./gradlew :app:mergeDebugResources
      • ./gradlew :app:compileDebugKotlin
      • ./gradlew :app:ktlintCheck
      • git diff --check
    • 기대 결과:
      • Phase 5 코드 리뷰 Findings 4건이 모두 source 계약과 빌드/테스트에서 PASS한다.
  • Task 5.9: Phase 5 추가 리뷰 반영

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeActivity.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeViewModel.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeActivitySourceTest.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeViewModelTest.kt
    • 작업:
      • SNS 버튼은 고정 52dp가 아니라 52dp를 최대값으로 두고, 디바이스 width가 402dp보다 작으면 52 * width / 402 비율로 축소한다.
      • toast 이벤트는 화면 재생성 시 중복 표시되지 않도록 CreatorChannelEvent로 한 번만 소비되게 한다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest"
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeViewModelTest"
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*"
      • ./gradlew :app:compileDebugKotlin
      • ./gradlew :app:ktlintCheck
    • 기대 결과:
      • SNS 버튼 크기 비율 계산과 toast 단발 이벤트 계약이 PASS한다.
  • Task 5.10: Phase 5 코드 리뷰 Finding 1/2와 SNS 아이콘 정책 반영

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/model/CreatorChannelHomeUiModels.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/model/CreatorChannelHomeMappers.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt
      • app/src/main/res/values/strings.xml
      • app/src/main/res/values-en/strings.xml
      • app/src/main/res/values-ja/strings.xml
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeActivitySourceTest.kt
    • 작업:
      • 활동 섹션의 데뷔 row는 데뷔 label과 debutDateUtc(dDay) 형식 value를 resource format으로 표시한다.
      • 활동 섹션의 count/hour/person/content/series 값은 단위가 포함된 resource format으로 표시한다.
      • 오디오 콘텐츠 섹션은 각 항목을 세로로 쌓지 않고 단일 가로 스크롤 row로 표시한다.
      • SNS는 텍스트 버튼이 아니라 ic_sns_로 시작하는 drawable icon을 사용하는 원형 아이콘 버튼으로 표시한다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest"
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*"
      • ./gradlew :app:mergeDebugResources
      • ./gradlew :app:compileDebugKotlin
      • ./gradlew :app:ktlintCheck
      • git diff --check
    • 기대 결과:
      • 활동 섹션 단위 표시, 오디오 가로 스크롤, SNS 아이콘 source 계약과 빌드/테스트가 PASS한다.
  • Task 5.11: Phase 5 SNS 순서/URL 안전성/마지막 여백 리뷰 반영

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/model/CreatorChannelHomeMappers.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeMapperTest.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeActivitySourceTest.kt
    • 작업:
      • SNS 매핑 순서를 Figma 296:14890 기준 Instagram, YouTube, X, Kakao Open Chat, Fancimm 순서로 맞춘다.
      • blank가 아니더라도 유효하지 않은 SNS URL은 UI item에서 제외한다.
      • SNS 링크 클릭 시 resolveActivity()로 열 수 있는 intent만 실행한다.
      • 작은 화면 SNS 버튼 비율 축소 정책은 유지하되, 마지막 아이콘 뒤 trailing marginEnd만 제거한다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeMapperTest"
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest"
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*"
      • ./gradlew :app:compileDebugKotlin
      • ./gradlew :app:ktlintCheck
      • git diff --check
    • 기대 결과:
      • SNS 순서, URL 안전성, 마지막 margin source 계약과 빌드/테스트가 PASS한다.

Phase 5R: 탭 바 아래 홈 컨텐츠 Figma Component 기준 재구성

2026-06-15 사용자 요청으로 추가된 후속 재구성 Phase다. 기존 Task 5.2에서 만든 탭 바 아래 홈 섹션 UI는 삭제 대상으로 보고, Figma 296:14895에 있는 component 성격의 구조를 섹션별 Task로 다시 구성한다. 이번 문서 수정 단계에서는 구현하지 않는다.

  • Task 5R.0: 기존 홈 섹션 동적 조립 UI 제거 계획 확정

    • 수정 예정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt
      • app/src/main/res/layout/item_creator_channel_home_*.xml
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeActivitySourceTest.kt
    • 작업:
      • 확인 결과 CreatorChannelHomeSectionAdapterbind* 함수에서 addHeroCard, addAudioCard, createContentTile, addFeedCard, addScheduleRow, addDonationCard, addCommentCard, addTextCard, addActivityRow, createSnsButton 등으로 view를 코드에서 직접 생성하고 있으므로 Phase 5R 섹션별 Task에서 삭제 대상으로 확정한다.
      • 확인 결과 12개 item_creator_channel_home_*.xml은 동일한 tv_section_title/ll_section_items 컨테이너만 갖는 구조를 공유하므로 Phase 5R 재구성에서는 이 공통 컨테이너 구조를 재사용하지 않는다.
      • adapter는 getItemViewType(), onCreateViewHolder(), ViewHolder.bind()에서 섹션 타입을 선택하고 해당 XML/ViewBinding 또는 재사용 가능한 Android View에 데이터를 전달하는 역할로 축소한다.
      • 실제 UI 구성은 섹션별 XML/ViewBinding 또는 재사용 가능한 Android View로 옮기며, adapter 내부에서 LinearLayout, TextView, ImageView, HorizontalScrollView를 조합해 화면 구조를 만드는 패턴은 제거한다.
      • 재사용 후보로 AudioContentCardView, SeriesContentCardView, FeedAdapter, FeedCommunityView, LiveThumbnailSimpleView, LiveThumbnailDetailView, view_section_title.xml을 확인했으며, 각 섹션 Task에서 Figma 요구와 맞는지 먼저 판정한다.
      • Figma 296:14895에는 화보 섹션이 있으나 현재 홈 API 응답에는 화보 데이터가 없으므로 이번 재구성 범위에서 제외한다.
    • 검증 명령:
      • 문서 단계에서는 실행하지 않는다.
    • 기대 결과:
      • 기존 구현을 어떤 기준으로 제거하고 어떤 단위로 재구성할지 문서에 명확히 남는다.
    • 확인 근거:
      • CreatorChannelHomeSectionAdapter.kt는 현재 섹션별 bind*에서 코드 생성 helper를 호출해 실제 UI를 조립한다.
      • item_creator_channel_home_live.xml을 포함한 섹션 layout은 tv_section_titlell_section_items 중심의 동일 컨테이너 구조다.
      • view_section_title.xml과 v2 widget/feed/live thumbnail 계열 컴포넌트는 재사용 후보로 확인했다.
    • 검증 기록:
      • 2026-06-15: 문서 확정 Task라 빌드/테스트는 실행하지 않았다. rg와 파일 확인으로 삭제 대상 helper, 공통 컨테이너 layout, 재사용 후보 컴포넌트를 확인했다.
  • Task 5R.1: 현재 라이브 섹션 재구성

    • 수정 예정:
      • CreatorChannelHomeSectionAdapter.kt
      • item_creator_channel_home_live.xml
      • 필요 시 현재 라이브 전용 View/layout
    • Figma 기준:
      • 296:14897의 현재 라이브 섹션
      • 최상단 현재 라이브는 SectionTitle 없이 374dp x 78dp cyan gradient pill card로 표시한다.
    • 작업:
      • currentLive가 null이면 섹션을 표시하지 않는다.
      • item_creator_channel_home_live.xml은 기존 tv_section_title/ll_section_items 공통 컨테이너를 제거하고 현재 라이브 전용 layout id로 구성한다.
      • 라이브 제목, 시작 시간, 유료 가격 capsule, 성인 상태가 있으면 Figma 라이브 카드 구조에 맞춰 표시한다.
      • 기존 LiveThumbnail* 계열 위젯은 원형 프로필/썸네일 기반 구조라 296:14897의 pill card와 맞지 않아 재사용하지 않는다.
    • 검증 기준:
      • adapter가 addHeroCard 동적 helper로 라이브 카드를 만들지 않고 item_creator_channel_home_live.xml의 전용 view id를 bind한다.
    • 검증 기록:
      • 2026-06-15: Figma 296:14897을 확인해 현재 라이브가 SectionTitle/썸네일 없는 374dp x 78dp cyan gradient pill card임을 반영했다. RED로 CreatorChannelHomeActivitySourceTest에 live 전용 layout/bind 계약을 추가해 기존 구현 실패를 확인했고, 구현 후 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest", ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck, git diff --check가 PASS했다. ktlintCheck.editorconfig disabled_rules deprecation 경고와 Kotlin deprecation warning은 기존 경고로 이번 변경과 무관하다.
  • Task 5R.2: 최신 오디오 섹션 재구성

    • 수정 예정:
      • CreatorChannelHomeSectionAdapter.kt
      • item_creator_channel_home_latest_audio.xml
      • 필요 시 오디오 list row 전용 View/layout
    • Figma 기준:
      • 296:14898의 최신 오디오 Contents 변형 card
      • 최상단 최신 오디오는 SectionTitle 없이 gray 900 card 안에 88dp 썸네일, Point 태그, New label, 제목, duration을 표시한다.
    • 작업:
      • latestAudioContent가 null이면 섹션을 표시하지 않는다.
      • Figma card 구조에 맞춰 이미지, Point 태그, New label, 제목, duration을 표시한다.
      • 기존 AudioContentCardView는 Point 태그 구성은 유사하지만 세로 카드 구조라 296:14898과 맞지 않아 재사용하지 않고 전용 layout을 만든다.
    • 검증 기준:
      • 최신 오디오는 addAudioCard 같은 코드 생성 helper 없이 item_creator_channel_home_latest_audio.xml의 전용 view id를 bind한다.
    • 검증 기록:
      • 2026-06-15: Figma 296:14898을 확인해 최신 오디오가 SectionTitle 없는 Contents 변형 card이며 기존 AudioContentCardView와 UI 구성이 다름을 반영했다. RED로 CreatorChannelHomeActivitySourceTest에 최신 오디오 전용 layout/bind 계약을 추가해 기존 구현 실패를 확인했고, 구현 후 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest", ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck, git diff --check가 PASS했다. ktlintCheck.editorconfig disabled_rules deprecation 경고와 Kotlin deprecation warning은 기존 경고로 이번 변경과 무관하다.
      • 2026-06-15: docs/agent-guides/code-style.md의 radius clipping 규칙에 따라 item_creator_channel_home_latest_audio.xmlandroid:clipToOutline 속성을 제거하고, CreatorChannelLatestAudioThumbnailView에서 clipToOutline = trueViewOutlineProvider.setRoundRect(...)를 함께 설정하도록 수정했다. ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest", ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck, git diff --check가 PASS했다.
  • Task 5R.3: 후원 섹션 재구성

    • 수정 예정:
      • CreatorChannelHomeSectionAdapter.kt
      • item_creator_channel_home_donation.xml
      • 필요 시 후원 row 전용 View/layout
    • Figma 기준:
      • 296:14895의 list/comment 계열 스타일
      • 공통 제목은 SectionTitle
    • 작업:
      • channelDonations가 empty이면 섹션을 표시하지 않는다.
      • 후원자 프로필, 닉네임, 후원 메시지, can 수량을 표시한다.
      • 비밀 후원은 기존 채널 후원 UI 정책을 확인해 닉네임/프로필 노출 방식을 맞춘다.
    • 검증 기준:
      • 후원 항목은 섹션 전용 row layout 또는 기존 후원 item layout 재사용으로 렌더링된다.
    • 검증 기록:
      • 2026-06-15: Figma 296:14908을 확인해 후원 섹션이 SectionTitle, 가로 스크롤 후원 카드 row, ic_new_donation 후원하기 버튼 구조임을 반영했다. CreatorChannelHomeActivitySourceTest에 후원 전용 layout/row bind, can 수량별 헤더 배경색, 402dp 기준 최대 374dp/작은 화면 비율 축소, 최대 8개 표시, 빈 메시지 fallback 다국어 계약을 RED로 추가한 뒤 구현했다. 후원 메시지가 blank이면 %1$d캔을 후원하였습니다. 형식의 다국어 string을 표시하고, can 배경색은 150 #E2E2E2, 51100 #73FF01, 101~499 #00EAFF, 500 이상 #FF4C3C로 매핑했다. 비밀 후원은 기존 채널 후원 UI 정책 확인 결과 닉네임/프로필을 숨기지 않으므로 동일하게 노출한다. ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*", ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck, git diff --check가 PASS했다. ktlintCheck.editorconfig disabled_rules deprecation 경고와 Kotlin/Java deprecation warning은 기존 경고로 이번 변경과 무관하다.
      • 2026-06-15: 후속 수정으로 item_creator_channel_home_donation_row.xml의 XML android:clipToOutline을 제거하고 CreatorChannelDonationCardView custom view에서 clipToOutline = trueViewOutlineProvider.setRoundRect(..., R.dimen.radius_14)를 설정하도록 변경했다. 또한 Figma 구조에 맞춰 후원하기 버튼 참조 기준을 child tv_donation_button이 아니라 parent layout_donation_button으로 고정하고 관련 source test 계약을 갱신했다.
  • Task 5R.4: 공지 섹션 재구성

    • 수정 예정:
      • CreatorChannelHomeSectionAdapter.kt
      • item_creator_channel_home_notice.xml
      • 필요 시 공지 row/feed 전용 View/layout
    • Figma 기준:
      • 296:14915의 공지 섹션 구조
      • 공통 제목은 SectionTitle
      • 공지는 ic_pin + Notice label, 프로필 42dp, 작성자/날짜, 본문, 선택 이미지 썸네일을 가진 feed card로 표시한다.
      • 공지 item UI width는 디바이스 width 402dp 기준 최대 346dp이며, 402dp 미만에서는 같은 비율로 축소한다.
    • 작업:
      • notices가 empty이면 섹션을 표시하지 않는다.
      • 공지는 1개 고정이 아니라 최대 3개까지 가로 row에 나열한다.
      • 공지 item width는 346 * deviceWidth / 402 비율로 계산하되 402dp 이상에서는 346dp로 고정한다.
      • 공지 본문, 날짜, 이미지가 있으면 이미지 영역을 표시한다.
      • 유료/잠금 상태 표현이 필요한 경우 Figma Lock 구조와 API price 값을 연결한다.
    • 검증 기준:
      • 공지 섹션은 공통 텍스트 카드가 아니라 공지 전용 layout으로 렌더링된다.
    • 검증 기록:
      • 2026-06-15: Figma 296:14915를 확인해 공지 섹션이 SectionTitle, ic_pin Notice label, 프로필/작성자/날짜, 본문, 선택 썸네일을 가진 가로 feed card 구조임을 반영했다. 사용자 피드백에 따라 공지는 1개가 아니라 최대 3개까지 HorizontalScrollView row에 나열하고, 공지 item width는 디바이스 width 402dp 기준 최대 346dp이며 402dp 미만에서는 346 * deviceWidth / 402 비율로 축소하도록 구현했다. RED로 CreatorChannelHomeActivitySourceTest에 공지 전용 layout/row bind, 최대 3개 제한, 마지막 카드 trailing margin 제거, 이미지 null/blank 시 썸네일 숨김, radius clipping custom view, 346dp width 계산 계약을 추가했고 기존 구현이 row layout/custom thumbnail view 부재 및 374dp width 계산으로 실패함을 확인했다. 구현 후 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest.공지 섹션은 최대 3개 Figma feed card를 가로 row로 렌더링한다", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest.공지 컴포넌트 width는 402dp 기준 최대 346dp이고 작은 화면에서는 비율 축소한다", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*", ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck, git diff --check가 PASS했다. ktlintCheck.editorconfig disabled_rules deprecation 경고와 Kotlin/Gradle deprecation warning은 기존 경고로 이번 변경과 무관하다.
  • Task 5R.5: 일정 섹션 재구성

    • 수정 예정:
      • CreatorChannelHomeSectionAdapter.kt
      • item_creator_channel_home_schedule.xml
      • 필요 시 일정 row 전용 View/layout
    • Figma 기준:
      • 296:14895의 list row 구조
      • 공통 제목은 SectionTitle
    • 작업:
      • schedules가 empty이면 섹션을 표시하지 않는다.
      • 일정 타입은 CreatorActivityType.labelResId로 표시한다.
      • 일정 제목과 일시를 Figma row 구조에 맞춘다.
    • 검증 기준:
      • 일정은 addScheduleRow 동적 생성 없이 전용 row bind로 렌더링된다.
    • 검증 기록:
      • 2026-06-15: Figma 296:14947을 확인해 일정 섹션이 SectionTitle, 351dp feed card, 53dp calendar 영역, 타입 tag, 로컬 시간 텍스트를 가진 세로 3개 row 구조임을 반영했다. 사용자 추가 요구에 따라 scheduledAtUtc는 UTC로 파싱한 뒤 디바이스 Timezone 기준 날짜/요일/시간으로 표시한다. 스케줄은 scheduledAtUtc가 가장 가까운 순으로 정렬해 최대 3개만 매핑한다. 스케줄 item 클릭은 콘텐츠(AUDIO, LIVE_REPLAY)는 AudioContentDetailActivity로, 라이브(LIVE)는 예약 라이브를 고려해 LiveRoomActivity 직접 진입이 아니라 LiveRoomDetailFragment 표시로 연결했다. RED로 CreatorChannelHomeMapperTestCreatorChannelHomeActivitySourceTest에 정렬/최대 3개, 전용 layout/row bind, Timezone 변환, 상세 이동 계약을 추가했고, 기존 구현이 formatCreatorChannelSchedule* 미구현으로 실패함을 확인했다. 구현 후 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeMapperTest.스케줄은 scheduledAtUtc가 가까운 순으로 최대 3개만 매핑한다"와 일정 source/timezone/navigation 테스트 3건이 PASS했다. 최종 검증으로 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*", ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck, git diff --check가 PASS했다. ktlintCheck.editorconfig disabled_rules deprecation 경고와 Kotlin/Gradle deprecation warning은 기존 경고로 이번 변경과 무관하다.
      • 2026-06-15: 후속 확인에서 Figma 296:14953의 왼쪽 timeline indicator가 누락되어 있음을 확인하고 추가 구현했다. item_creator_channel_home_schedule.xmlll_schedule_timeline column을 추가하고, CreatorChannelHomeSectionAdapter에서 실제 표시 스케줄 수만큼 dot을 만들며 dot 사이 line 개수는 scheduleCount - 1개로 계산한다. 첫 dot은 Figma처럼 soda_400, 나머지 dot과 line은 gray_700으로 표시한다. RED로 CreatorChannelHomeActivitySourceTest에 timeline dot/line 동적 생성 계약을 추가해 calculateCreatorChannelScheduleTimelineLineCount 미구현 실패를 확인했고, 구현 후 해당 테스트와 ./gradlew :app:mergeDebugResources가 PASS했다.
  • Task 5R.6: 오디오 컨텐츠 섹션 재구성

    • 수정 예정:
      • CreatorChannelHomeSectionAdapter.kt
      • item_creator_channel_home_audio.xml
      • 필요 시 Contents audio variant 대응 View/layout
    • Figma 기준:
      • 296:14895의 오디오 컨텐츠 섹션
      • Figma Contents(type=audio, size=s) 또는 해당 섹션의 88dp list row 구조
    • 작업:
      • audioContents가 empty이면 섹션을 표시하지 않는다.
      • 각 오디오 항목은 이미지, 제목, 시리즈명/시간, 유료/무료/포인트/first/original 상태를 Figma tag 정책에 맞춰 표시한다.
      • 기존 AudioContentCardView 재사용 여부를 먼저 판정하고, 요구와 다르면 전용 Android View를 만든다.
    • 검증 기준:
      • 오디오 컨텐츠는 adapter 내부 createContentTile이 아니라 component/layout bind로 표시된다.
    • 검증 기록:
      • 2026-06-15: Figma 296:14958을 확인해 오디오 컨텐츠 섹션이 SectionTitle, 88dp 썸네일, 16sp title, 14sp secondary text를 가진 item row이며, 아이템 최대 width가 402dp 기준 346dp인 구조임을 반영했다. 사용자 요구에 따라 최대 9개만 표시하고, 섹션은 RecyclerView + GridLayoutManager로 구성했다. AudioContentCardView는 요구사항과 달라 재사용하지 않고 CreatorChannelHomeAudioContentCardView 전용 Android View와 item_creator_channel_home_audio_content.xml을 추가했다. item 내부는 썸네일 + 텍스트 컬럼의 단순 행 구조라 사용자 피드백에 따라 GridLayout이 아니라 LinearLayout으로 구성하고, 목록 grid는 GridLayoutManager로 유지했다. 아이템 클릭은 AudioContentDetailActivityConstants.EXTRA_AUDIO_CONTENT_ID로 이동하도록 연결했다. RED로 CreatorChannelHomeActivitySourceTest에 오디오 전용 layout/View, 최대 9개, 346dp width 비율 계산, GridLayoutManager, 상세 이동 계약을 추가했고, 최초 실행에서 calculateCreatorChannelAudioItemWidthDp 미구현으로 실패함을 확인했다. 구현 후 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*", ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck, git diff --check가 PASS했다. compileDebugKotlin 중 Kotlin daemon cache/파일 경합으로 fallback compile이 발생했으나 최종 빌드는 성공했다. ktlintCheck.editorconfig disabled_rules deprecation 경고와 Kotlin/Gradle deprecation warning은 기존 경고로 이번 변경과 무관하다.
  • Task 5R.7: 시리즈 섹션 재구성

    • 수정 예정:
      • CreatorChannelHomeSectionAdapter.kt
      • item_creator_channel_home_series.xml
      • 필요 시 Contents series variant 대응 View/layout
    • Figma 기준:
      • 296:14895의 시리즈 섹션
      • Figma Contents(type=series, size=m)
    • 작업:
      • series가 empty이면 섹션을 표시하지 않는다.
      • 시리즈 썸네일은 163dp x 230dp 비율과 radius 14dp를 따른다.
      • 백엔드에서 내려오지 않는 isPopular, isComplete, publishedDaysOfWeek는 표시하지 않고, 현재 응답에서 화면 표시가 가능한 coverImageUrl, isOriginal만 표시한다.
      • item click에 필요한 seriesId는 row click callback으로 전달 가능한 구조를 둔다.
      • 기존 SeriesContentCardView 또는 시리즈 카드 layout을 재사용할 수 있는지 먼저 확인한다.
    • 검증 기준:
      • 시리즈 섹션은 Figma Contents 구조에 대응하는 View/layout으로 렌더링된다.
    • 검증 기록:
      • 2026-06-15: Figma 296:14970을 확인해 시리즈 섹션이 SectionTitle, 163dp x 230dp Contents(type=series, size=m) 썸네일 카드 row 구조임을 반영했다. 사용자 추가 설명에 따라 CreatorChannelSeriesResponse에서 현재 화면에 쓰는 값은 coverImageUrl, isOriginal이고 터치 시 필요한 값은 seriesId로 범위를 축소했다. RED로 CreatorChannelHomeActivitySourceTest에 시리즈 전용 layout/custom view, radius clipping custom view, 402dp 기준 163dp width 비율 계산, 백엔드 미전송 필드 미사용 계약을 추가했고, 최초 실행에서 기존 adapter의 publishedDaysOfWeek 참조로 compileDebugKotlin 실패함을 확인했다. 구현 후 focused source test와 creator channel 전체 테스트가 PASS했다.
      • 2026-06-15: reviewer gate에서 작은 화면에서 adapter row width는 146dp로 줄지만 내부 썸네일 XML은 163dp x 230dp 고정이라 클리핑/비율 불일치가 발생할 수 있다는 FAIL을 받았다. RED로 calculateCreatorChannelSeriesCardHeightDp 미구현 컴파일 실패를 확인한 뒤, CreatorChannelHomeSeriesCardView.setThumbnailSize(widthDp, heightDp)와 높이 비율 계산을 추가해 thumbnail width/height를 함께 조정했다. 수정 후 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*", ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck, git diff --check가 PASS했다.
      • 2026-06-15: 사용자 후속 확인에서 item_creator_channel_home_series_content.xml의 오리지널 태그가 Figma 296:14973과 다르다는 지적을 반영했다. 기존 단일 ic_content_tag_original 이미지를 제거하고 layout_series_original_tag 70dp x 24dp 컨테이너 안에 iv_series_original_icontv_series_original_text(Only)를 배치했다. CreatorChannelHomeSeriesCardView는 새 태그 컨테이너 visibility를 series.isOriginal로 토글하도록 변경했다.
  • Task 5R.8: 커뮤니티 섹션 재구성

    • 수정 예정:
      • CreatorChannelHomeSectionAdapter.kt
      • item_creator_channel_home_community.xml
      • 필요 시 커뮤니티 feed 전용 View/layout
    • Figma 기준:
      • 296:14895Feed 구조
    • 작업:
      • communities가 empty이면 섹션을 표시하지 않는다.
      • 프로필 42dp 원형 이미지, 작성자, 작성 시간, 본문, 이미지, 잠금 overlay, 좋아요/댓글 reaction을 표시한다.
      • 기존 FeedCommunityView 또는 FeedAdapter 재사용 여부를 먼저 확인한다.
      • Figma의 전체보기 capsule 버튼을 표시하되, 이동 대상이 없는 경우 click listener는 후속 범위로 분리한다.
    • 검증 기준:
      • 커뮤니티는 단순 addFeedCard가 아니라 Figma Feed 구조를 가진 View/layout으로 렌더링된다.
    • 검증 기록:
      • 2026-06-15: Figma 296:14982를 확인해 커뮤니티 섹션이 SectionTitle(hasRightIcon=false), 374dp feed card 최대 3개, 42dp 프로필, 작성자/날짜, 본문, 선택 이미지, 유료 잠금 overlay, 댓글/좋아요 reaction, 전체보기 capsule 버튼 구조임을 반영했다. RED로 CreatorChannelHomeActivitySourceTest에 커뮤니티 전용 layout/row/custom view, 최대 3개, 402dp 기준 374dp width 비율 계산, addFeedCard 제거 계약을 추가했고, 구현 후 focused source test와 creator channel 전체 테스트가 PASS했다.
      • 2026-06-15: reviewer gate에서 imageUrl이 없는 게시글도 236dp 이미지 컨테이너가 남는 문제와 잠긴 유료 이미지가 그대로 loadUrl 되는 privacy leak 가능성으로 FAIL을 받았다. RED로 layout_community_thumbnail visibility, hasCommunityImage, isCommunityLocked, 잠김 이미지 미로드/clear 계약을 추가한 뒤, bindCommunityRow()에서 이미지 컨테이너는 이미지가 있거나 잠김 상태일 때만 보이게 하고, 잠긴 상태에서는 썸네일을 숨기고 setImageDrawable(null)로 초기화하도록 수정했다. 수정 후 focused source test와 creator channel 전체 테스트, 리소스/컴파일/ktlint/diff check가 PASS했다.
      • 2026-06-15: 사용자 후속 확인에서 FeedCommunityView와 새로 만든 CreatorChannelCommunityCardView가 동일 UI이며, 실제로는 FeedCommunityViewitem_creator_channel_home_community_row.xml와 동일하게 고쳐 재사용해야 한다는 지적을 반영했다. view_feed_community.xml을 커뮤니티 row 구조에 맞춰 keyword row 제거, 본문 5줄, 이미지 컨테이너 236dp 고정, bg_creator_channel_community_price/ic_bar_cash, reaction gray_400, root match_parent 구조로 수정했다. CreatorChannelHomeSectionAdapterR.layout.view_feed_community를 inflate하고 FeedItem.Community로 변환해 FeedCommunityView를 바인딩하도록 변경했으며, 더 이상 필요 없는 CreatorChannelCommunityCardView, CreatorChannelCommunityThumbnailView, item_creator_channel_home_community_row.xml는 참조 제거 후 삭제했다.
      • 2026-06-15: 사용자 후속 확인에서 tv_feed_community_pricedrawableStart 방식은 Figma처럼 가격과 아이콘 간격을 정확히 표현하기 어렵다는 지적을 반영했다. 가격 capsule을 LinearLayout 안의 별도 ImageView(ic_bar_cash)TextView(tv_feed_community_price) 구조로 바꾸고, 텍스트에 layout_marginStart=@dimen/spacing_6을 지정해 아이콘/가격 간격을 명시했다. 미구매 유료 커뮤니티 이미지 blur는 원본 보호 관점에서 클라이언트 blur보다 서버가 비가역 preview/blur 이미지를 별도 URL로 내려주는 방식이 더 안전하다고 판단했다.
      • 2026-06-15: 사용자 후속 요청으로 서버가 미구매 유료 커뮤니티 게시글의 imageUrl을 blur 처리하지 않고 내려줄 가능성에 대비해 클라이언트에서도 blur를 한 번 더 적용하도록 변경했다. 기존 커뮤니티 목록 CreatorCommunityAdapter에서 사용하던 BlurTransformation(context, 25f, 2.5f) 패턴을 확인했고, 크리에이터 채널 홈과 홈 추천의 FeedCommunityView 이미지 바인딩에도 같은 transformation을 적용했다. 이제 미구매 유료 게시글도 imageUrl을 로드하되 이미지 위에 lock overlay를 유지하고, 구매하지 않은 상태에서는 클라이언트 blur fallback을 적용한다.
  • Task 5R.9: 팬Talk 섹션 재구성

    • 수정 예정:
      • CreatorChannelHomeSectionAdapter.kt
      • item_creator_channel_home_fantalk.xml
      • 필요 시 ListComment 대응 View/layout
    • Figma 기준:
      • 296:14895ListComment
    • 작업:
      • fanTalk.latestFanTalk가 null이고 totalCount도 0이면 섹션을 표시하지 않는다.
      • 전체 label과 total count를 표시한다.
      • 최신 팬Talk의 프로필 28dp 원형 이미지, 댓글 본문 2줄 말줄임, chevron-down 아이콘을 표시한다.
    • 검증 기준:
      • 팬Talk는 addCommentCard가 아니라 ListComment 대응 View/layout으로 렌더링된다.
    • 검증 기록:
      • 2026-06-15: Figma 296:14989를 확인해 팬Talk 섹션이 SectionTitle, 374dp ListComment card, 전체 label과 total count, 28dp 프로필, 2줄 말줄임 본문, 18dp chevron-down 구조임을 반영했다. RED로 CreatorChannelHomeActivitySourceTest에 팬Talk 전용 layout/custom view, 402dp 기준 374dp width 비율 계산, addCommentCard 제거 계약을 추가했고, 구현 후 focused source test와 creator channel 전체 테스트가 PASS했다. 전체 label은 기존 다국어 string screen_chat_filter_all을 재사용했다.
      • 2026-06-15: reviewer gate에서 latestFanTalk == null 리바인드 시 이전 ViewHolder의 프로필/본문이 남을 수 있다는 FAIL을 받았다. RED로 layout_fantalk_latest_row, null 시 row 숨김, 본문 빈 문자열, placeholder 초기화 계약을 추가한 뒤, bindFanTalk()에서 최신 팬Talk 유무에 따라 row visibility와 값을 명시적으로 초기화했다. 수정 후 focused source test와 creator channel 전체 테스트, 리소스/컴파일/ktlint/diff check가 PASS했다.
      • 2026-06-15: 사용자 후속 요청으로 팬Talk가 없을 때 표시할 empty UI Figma 304:17362를 반영했다. 기존에는 totalCount=0, latestFanTalk=null이면 FanTalk section을 생성하지 않았지만, empty card 표시를 위해 mapper가 항상 FanTalk section을 포함하도록 변경했다. item_creator_channel_home_fantalk.xml에는 layout_fantalk_empty를 추가하고, 당신의 첫 응원을\n기다리고 있어요! 문구와 ic_new_fantalk_plus 아이콘, 응원 남기기 흰색 capsule 버튼을 배치했다. bindFanTalk()는 최신 팬Talk가 있으면 total/latest row를 표시하고 empty UI를 숨기며, 없으면 total/latest row를 숨기고 empty UI를 표시하도록 변경했다.
  • Task 5R.10: 소개 섹션 재구성

    • 수정 예정:
      • CreatorChannelHomeSectionAdapter.kt
      • item_creator_channel_home_introduce.xml
    • Figma 기준:
      • 296:14895의 소개 본문 텍스트 영역
      • SectionTitle(hasRightIcon=false)
    • 작업:
      • introduce가 blank이면 섹션을 표시하지 않는다.
      • 소개 본문은 카드 배경 없이 16sp regular, white로 표시하고, 고정 362dp 폭 대신 match_parent와 좌우 20dp padding을 사용한다.
    • 검증 기준:
      • 소개 섹션은 addTextCard 같은 어두운 카드 배경을 사용하지 않는다.
    • 검증 기록:
      • 2026-06-15: Figma 296:14998을 확인해 소개 섹션이 SectionTitle(hasRightIcon=false)와 카드 배경 없는 16sp regular white 본문 텍스트 구조임을 반영했다. RED로 CreatorChannelHomeActivitySourceTest에 소개 전용 layout/bind 계약을 추가해 기존 구현이 실패함을 확인했고, 구현 후 item_creator_channel_home_introduce.xml에서 공통 ll_section_items를 제거하고 tv_introduce_body 전용 bind로 변경했다. 후속 수정으로 본문 폭은 고정 362dp가 아니라 match_parent와 좌우 @dimen/spacing_20 padding을 사용하도록 source 계약을 갱신했다. ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest"가 PASS했다.
  • Task 5R.11: 활동 섹션 재구성

    • 수정 예정:
      • CreatorChannelHomeSectionAdapter.kt
      • item_creator_channel_home_activity.xml
    • Figma 기준:
      • 296:14895의 활동 label/value row 목록
      • SectionTitle(hasRightIcon=false)
    • 작업:
      • 배경 카드 없이 label/value row를 세로로 나열한다.
      • 데뷔, 라이브 총 진행 수, 라이브 누적 진행 시간, 라이브 누적 참여자, 오디오, 시리즈를 표시한다.
      • Figma에는 화보 row가 있으나 현재 API 응답에 화보 count가 없으므로 이번 범위에서는 표시하지 않는다.
    • 검증 기준:
      • 활동 row는 bg_round_corner_16_7_222222 같은 row 배경을 사용하지 않는다.
    • 검증 기록:
      • 2026-06-15: Figma 296:15001을 확인해 활동 섹션이 SectionTitle(hasRightIcon=false)와 카드 배경 없는 label/value 16sp row 목록임을 반영했다. 화보 row는 현재 API 응답에 count가 없어 제외하고, 데뷔/라이브 총 진행 수/라이브 누적 진행 시간/라이브 누적 참여자/오디오/시리즈 6개 row만 전용 TextView id로 바인딩했다. 후속 수정으로 row container 폭은 고정 362dp가 아니라 match_parent와 좌우 @dimen/spacing_20 padding을 사용하도록 source 계약을 갱신했다. RED로 CreatorChannelHomeActivitySourceTest에 활동 전용 layout/bind 계약을 추가해 기존 구현이 실패함을 확인했고, 구현 후 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest"가 PASS했다.
  • Task 5R.12: SNS 섹션 재구성

    • 수정 예정:
      • CreatorChannelHomeSectionAdapter.kt
      • item_creator_channel_home_sns.xml
      • 필요 시 SNS 대응 View/layout
    • Figma 기준:
      • 296:14895SNS
    • 작업:
      • sns 매핑 결과가 empty이면 섹션을 표시하지 않는다.
      • SNS 제목은 Figma처럼 18sp bold title 영역을 사용한다.
      • 아이콘 순서는 Instagram, YouTube, X, Kakao Open Chat, Fancimm을 유지한다.
      • 각 아이콘은 디바이스 width가 402dp 이상이면 최대 52dp로 표시하고, 402dp 미만에서는 좌우 20dp padding과 16dp gap 4개를 제외한 남은 폭을 5개 아이콘에 균등 배분해 표시한다.
      • URL은 기존 안전성 정책처럼 유효한 http/https URL만 사용하고, 열 수 있는 intent만 실행한다.
    • 검증 기준:
      • SNS는 adapter 내부 계산/조립이 아니라 SNS 대응 View/layout으로 렌더링된다. 단, 작은 화면에서는 5개 아이콘이 잘리지 않도록 실제 가용 폭 기준으로 크기를 축소한다.
    • 검증 기록:
      • 2026-06-15: Figma 296:15022를 확인해 SNS 섹션이 18sp bold title과 최대 52dp 원형 icon row, 16dp gap 구조임을 반영했다. URL 매핑 순서와 http/https 유효 URL 필터, resolveActivity() 확인 후 실행하는 안전 정책은 유지했다. RED로 CreatorChannelHomeActivitySourceTest에 SNS 전용 layout/icon row 계약을 추가해 기존 구현이 실패함을 확인했고, 구현 후 item_creator_channel_home_sns.xmlitem_creator_channel_home_sns_icon.xml 기반 bind로 변경했다. 후속 수정으로 SNS row는 match_parent와 좌우 @dimen/spacing_20 padding을 사용하고, 아이콘 크기는 402dp 이상 52dp, 402dp 미만에서는 (deviceWidth - 40dp padding - 64dp gaps) / 5로 계산해 5개 아이콘이 작은 화면에서 잘리지 않도록 했다. ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest"가 PASS했다.
      • 2026-06-15: 코드 리뷰에서 roundToInt() 반올림으로 screenWidthDp=322 같은 경계값에서 5개 아이콘 총합이 가용 폭을 초과할 수 있음을 확인했다. SNS 아이콘 크기 계산을 minOf(52, (width - 40 - 64).coerceAtLeast(0) / 5) 정수 나눗셈으로 변경하고, 322dp 경계값 source test를 추가했다.
      • 2026-06-15: reviewer gate에서 클릭 가능한 SNS 아이콘이 contentDescription 없이 렌더링되는 접근성 blocking issue를 확인했다. CreatorChannelSnsUiItem.labelbutton.contentDescription에 연결하고, item_creator_channel_home_sns_icon.xml@null contentDescription을 제거했으며 source 계약을 추가했다.

Phase 6: sticky tab-bar와 scroll 상태 구현

  • Task 6.1: scroll 상태 계산 RED 테스트 작성

    • 생성:
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelScrollStateTest.kt
    • 작업:
      • title-bar와 tab-bar의 실제 거리가 기준 이하이고 프로필 이미지가 절반 이상 사라졌을 때 black 전환이 true인지 검증한다.
      • 둘 중 하나라도 만족하지 않으면 black 전환이 false인지 검증한다.
      • tab-bar sticky top은 status bar 높이와 title-bar 높이를 합산해 계산되는지 검증한다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelScrollStateTest"
    • 기대 결과:
      • scroll 상태 모델 미구현으로 RED 실패한다.
    • 검증 기록:
      • 2026-06-15: CreatorChannelScrollStateTest를 추가하고 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelScrollStateTest"를 실행해 Unresolved reference 'CreatorChannelScrollState' 컴파일 오류로 RED 실패를 확인했다.
  • Task 6.2: scroll 상태 계산 모델 구현

    • 생성:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/model/CreatorChannelScrollState.kt
    • 작업:
      • shouldUseBlackTitleBar(titleBarBottom: Int, tabBarTop: Int, profileImageVisibleHeight: Int, profileImageTotalHeight: Int): Boolean을 추가한다.
      • 실제 거리 조건은 tabBarTop <= titleBarBottom 또는 기존 layout에서 측정 가능한 최소 gap 기준으로 구현한다.
      • 프로필 이미지 절반 이상 사라짐은 profileImageVisibleHeight <= profileImageTotalHeight / 2로 계산한다.
      • sticky top 계산 helper는 statusBarHeight + titleBarHeight를 반환한다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelScrollStateTest"
    • 기대 결과:
      • scroll 상태 테스트가 PASS한다.
    • 검증 기록:
      • 2026-06-15: CreatorChannelScrollState를 추가해 title-bar/tab-bar 거리 조건과 프로필 이미지 절반 이상 사라짐 조건을 함께 계산하고, sticky top은 statusBarHeight + titleBarHeight로 계산하도록 구현했다. 병렬 Gradle 실행 중 :app:kspDebugUnitTestKotlin에서 zip END header not found가 한 번 발생했으나, 동시 실행으로 인한 빌드 산출물 경합으로 보고 단일 실행으로 재검증한다.
      • 2026-06-15: 단일 재실행으로 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelScrollStateTest"BUILD SUCCESSFUL로 PASS했다.
  • Task 6.3: Activity scroll listener 연결

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeActivity.kt
    • 작업:
      • system bar inset을 읽어 이미지 영역이 status bar 뒤까지 확장되도록 적용한다.
      • title-bar content에는 status bar inset만큼 top padding 또는 margin을 적용해 터치 영역을 보존한다.
      • scroll listener에서 tab-bar sticky 위치와 title-bar black 배경을 갱신한다.
      • tab-bar가 sticky 된 이후에는 홈 컨텐츠만 계속 스크롤되도록 header/tab translate 또는 parent scroll range를 조정한다.
    • 검증 명령:
      • ./gradlew :app:compileDebugKotlin
    • 수동 확인:
      • 상단에서 이미지가 status bar 영역까지 표시된다.
      • 스크롤 시 tab-bar가 title-bar 아래에 고정된다.
      • 프로필 이미지가 절반 이상 사라지고 tab-bar가 title-bar에 가까워지면 title-bar가 black으로 전환된다.
    • 검증 기록:
      • 2026-06-15: CreatorChannelHomeActivityNestedScrollView.setOnScrollChangeListener를 연결하고, horizontalTabScrollView.translationY로 tab-bar를 statusBarHeight + titleBarHeight 아래에 고정하며, CreatorChannelScrollState.shouldUseBlackTitleBar(...) 결과에 따라 title-bar 배경을 Color.BLACK/Color.TRANSPARENT로 전환하도록 구현했다. 기존 v2 inset 관례에 맞춰 ViewCompat.requestApplyInsets(binding.titleBarContainer)도 추가했다. Figma 296:14890, 296:14892 스크린샷으로 상단 header/status bar/title/tab 배치를 확인했다.
      • 2026-06-15: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest", ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck, git diff --check가 모두 BUILD SUCCESSFUL 또는 출력 없음으로 PASS했다. ktlintCheck.editorconfig disabled_rules deprecation 경고와 Gradle deprecation warning은 기존 경고로 이번 변경과 무관하다.
      • 2026-06-15: reviewer gate에서 horizontal_tab_scroll_viewrv_home_sections보다 먼저 선언된 sibling이라 translationY sticky 상태에서 RecyclerView 컨텐츠에 가려질 수 있다는 FAIL을 받았다. horizontal_tab_scroll_viewandroid:elevation="1dp"를 추가하고 CreatorChannelHomeActivitySourceTest에 elevation source 계약을 추가했다.
      • 2026-06-15: elevation 보강 후 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelScrollStateTest", ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck, git diff --check가 모두 BUILD SUCCESSFUL 또는 출력 없음으로 PASS했다.

Phase 7: 팔로우/알림 변경과 탭 동작 연결

  • Task 7.1: 팔로우/알림 click 흐름 연결

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeActivity.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeViewModel.kt
    • 작업:
      • 미팔로우 상태에서 follow icon 클릭 시 viewModel.follow(follow = true, notify = true)를 호출한다.
      • 팔로우 중 상태에서 follow/following icon 클릭 시 CreatorFollowNotifyFragment를 띄운다.
      • 알림 모두 받기, 알림 받지 않기, 언팔로우 선택은 각각 기존 follow=true/notify=true, follow=true/notify=false, follow=false/notify=false 조합으로 호출한다.
      • 요청 중에는 title-bar follow/bell click을 막는다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeViewModelTest"
      • ./gradlew :app:compileDebugKotlin
    • 기대 결과:
      • 팔로우/알림 상태 변경 테스트와 컴파일이 PASS한다.
    • 검증 기록:
      • 2026-06-15: RED로 CreatorChannelHomeViewModelTestisFollowInProgressLiveData 진행 상태 계약을 추가해 Unresolved reference 'isFollowInProgressLiveData' 컴파일 실패를 확인했다. 구현 후 CreatorChannelHomeViewModel에 팔로우 요청 진행 상태 LiveData를 노출하고, CreatorChannelHomeActivity에서 layout_follow_capsule/iv_bell 클릭을 onFollowActionClicked()로 연결했다. 미팔로우 상태는 viewModel.follow(follow = true, notify = true)를 직접 호출하고, 팔로우 중 상태는 CreatorFollowNotifyFragment를 표시해 알림 모두 받기, 알림 받지 않기, 언팔로우를 각각 true/true, true/false, false/false 조합으로 호출한다. 요청 중에는 CreatorChannelTitleBarState.from(..., isInProgress = true) 기반으로 follow/bell click을 비활성화한다. ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest"./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeViewModelTest"가 PASS했다.
  • Task 7.2: tab-bar 7개 항목 표시와 홈 외 탭 클릭 정책 적용

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeActivity.kt
      • app/src/main/res/layout/activity_creator_channel_home.xml
    • 생성 후보:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelTabAdapter.kt
    • 작업:
      • tab-bar에 , 라이브, 오디오, 시리즈, 커뮤니티, 팬Talk, 후원을 표시한다.
      • 기본 선택은 이다.
      • 홈 외 탭 클릭 시 상세 화면을 로드하지 않는다.
      • 홈 외 탭 클릭 정책은 구현 시점에 최소 동작으로 둔다.
        • 선택 상태만 바꾸지 않고 유지하거나,
        • 선택은 가능하되 컨텐츠 전환은 하지 않는 방식 중 기존 tab 컴포넌트 동작과 가장 충돌이 적은 방식을 선택한다.
    • 검증 명령:
      • ./gradlew :app:compileDebugKotlin
    • 수동 확인:
      • 7개 탭이 가로 폭을 초과해도 표시/스크롤이 가능하다.
      • 홈 외 탭을 눌러도 crash가 발생하지 않는다.
    • 검증 기록:
      • 2026-06-15: RED로 CreatorChannelHomeActivitySourceTestselectedTab 기반 홈 기본 선택과 홈 외 탭 no-op 정책 계약을 추가했다. 구현 후 tab 생성은 CreatorChannelTab.Home을 기본 선택으로 유지하고, 각 tab view click은 onTabClicked(tab)로 연결했다. 이번 범위에서 홈 외 상세 컨텐츠는 구현하지 않으므로 tab != CreatorChannelTab.Home이면 즉시 return하여 선택 상태와 홈 컨텐츠를 유지한다. 기존 index == 0 고정 source test는 Phase 7 정책에 맞게 tab == selectedTab 계약으로 갱신했다. ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest"가 PASS했다.
  • Task 7.3: 기존 크리에이터 채널 진입점을 신규 화면으로 전환

    • 확인:
      • app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/UserProfileActivity.kt
      • 기존 코드에서 UserProfileActivityIntent로 여는 호출부 전체
      • 신규 CreatorChannelHomeActivity.newIntent(context, creatorId) 계약
    • 작업:
      • 현재 크리에이터 채널 확인을 위해 기존 UserProfileActivity로 이동하던 크리에이터 채널 진입 로직을 CreatorChannelHomeActivity로 이동하도록 변경한다.
      • creatorId를 이미 가지고 있는 호출부는 CreatorChannelHomeActivity.newIntent(context, creatorId)를 사용한다.
      • 호출부가 creatorId가 아닌 다른 식별자만 가지고 있으면 추측 변환하지 말고 해당 호출부는 문서에 남기고 제외한다.
      • UserProfileActivity 자체 삭제나 내부 동작 변경은 하지 않는다.
      • 신규 화면 수동 확인 목적의 진입점 전환에 한정하고, 기존 프로필 화면의 다른 기능/딥링크/알림 진입 정책은 변경하지 않는다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest"
      • ./gradlew :app:compileDebugKotlin
    • 수동 확인:
      • 앱에서 기존 크리에이터 채널 진입 경로를 탭하면 CreatorChannelHomeActivity가 열린다.
      • 전달된 creatorId로 홈 API가 호출되고 신규 크리에이터 채널 화면이 표시된다.
    • 기대 결과:
      • 기존 크리에이터 채널 확인 경로가 신규 크리에이터 채널 홈 화면으로 연결된다.
    • 검증 기록:
      • 2026-06-15: UserProfileActivity 진입 호출부를 확인한 결과, Phase 7 범위에서는 v2/main/home의 홈 추천/랭킹/크리에이터 카드처럼 이미 creatorId를 직접 보유한 확정 진입점만 신규 화면으로 전환했다. HomeRecommendationBannerRoute.CreatorCreatorChannelHomeActivity.newIntent(context, creatorId)를 반환하도록 변경하고, HomeMainFragment.openCreatorProfile(creatorId)CreatorChannelHomeActivity.newIntent(requireContext(), creatorId)를 사용하도록 변경했다. 딥링크/알림/기존 프로필 화면 내부와 같이 정책 범위가 넓거나 다른 식별자 의미가 섞일 수 있는 호출부는 변경하지 않았다. ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest"가 PASS했다.
      • 2026-06-15: 사용자 피드백에 따라 Task 7.3 의도를 재확인했고, 기존 크리에이터 채널인 UserProfileActivity로 이동하던 프로덕션 진입점을 신규 CreatorChannelHomeActivity로 전환하는 것이 요구사항임을 확인했다. RED로 CreatorChannelHomeActivitySourceTestapp/src/main/java에서 UserProfileActivity::class.javaUserProfileActivity import가 남으면 실패하는 검증을 추가했고, 기존 구현에서 실패함을 확인했다. 이후 딥링크/메인/홈/라이브/탐색/검색/팔로잉/알림설정/마이페이지/오디오 콘텐츠/시리즈/오디션/라이브 상세의 기존 채널 진입점을 모두 CreatorChannelHomeActivity.newIntent(..., creatorId)로 전환했다. 수정 후 동일 RED 테스트가 PASS했고, rgapp/src/main/java에 외부 UserProfileActivity 직접 진입점이 남지 않음을 확인했다.
      • 2026-06-15: 후속 검증으로 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest", ./gradlew :app:compileDebugKotlin, git diff --check가 PASS했다. rg -n "Intent\([^\n]*UserProfileActivity|UserProfileActivity::class\.java|import kr\.co\.vividnext\.sodalive\.explorer\.profile\.UserProfileActivity" app/src/main/java는 match 없이 종료되어 프로덕션 직접 진입점이 제거되었음을 확인했다. ./gradlew :app:ktlintCheckaudio_content 패키지명 underscore 기존 규칙 위반 4건(AudioContentNewAllActivity.kt, AudioContentAllByThemeActivity.kt, AudioContentDetailActivity.kt, SeriesDetailActivity.kt)으로 실패했다. 패키지명 변경은 범위 밖이고 전역 ktlint rule 변경은 기존 전체 lint 부채를 노출해 범위를 크게 늘리므로 적용하지 않았다.
      • 2026-06-15: 코드 리뷰에서 AuditionRoleDetailActivity의 지원자 닉네임 클릭은 GetAuditionRoleApplicantItem.memberId만 보유하고 creatorId/크리에이터 여부를 판별할 수 없어 신규 크리에이터 채널 홈으로 이동하면 잘못된 ID로 홈 API를 호출할 수 있음을 확인했다. RED로 CreatorChannelHomeActivitySourceTest에 오디션 지원자 memberId 프로필은 기존 UserProfileActivity로 이동한다는 계약을 추가해 실패를 확인했고, AuditionRoleDetailActivity의 해당 경로만 UserProfileActivity로 복구했다. 현재 API 응답만으로는 이 클릭에서 크리에이터 여부를 분기할 수 없으므로, 크리에이터 지원자만 신규 화면으로 보내려면 서버 응답에 creatorId 또는 isCreator 등 판별 필드가 추가되어야 한다.
      • 2026-06-15: 후속 검증으로 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest.오디션 지원자 memberId 프로필은 기존 UserProfileActivity로 이동한다", ./gradlew :app:compileDebugKotlin, git diff --check가 PASS했다.

Phase 8: 최종 검증과 문서 기록

  • Task 8.1: 단위 테스트 실행

    • 실행:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.common.*"
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*"
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*"
    • 기대 결과:
      • 신규 공용 타입, 크리에이터 채널 홈, 기존 홈 추천 관련 테스트가 모두 BUILD SUCCESSFUL로 통과한다.
    • 검증 기록:
      • 2026-06-15: Phase 8 최종 검증으로 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.common.*", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*"를 순차 실행했다. 세 명령 모두 BUILD SUCCESSFUL로 통과했다.
  • Task 8.2: 리소스/컴파일/린트 검증

    • 실행:
      • ./gradlew :app:mergeDebugResources
      • ./gradlew :app:compileDebugKotlin
      • ./gradlew :app:ktlintCheck
    • 기대 결과:
      • 모든 명령이 BUILD SUCCESSFUL로 통과한다.
    • 검증 기록:
      • 2026-06-15: Phase 8 최종 검증으로 ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck를 순차 실행했다. 세 명령 모두 BUILD SUCCESSFUL로 통과했다. ktlintCheck.editorconfig disabled_rules deprecation 경고와 Gradle deprecation warning은 기존 경고로 이번 변경과 무관하다.
  • Task 8.3: 수동 화면 검증

    • 확인:
      • 크리에이터 이미지가 OS status bar 영역까지 표시된다.
      • title-bar 좌측 ic_new_bar_back, 우측 ic_new_more가 표시된다.
      • 팔로우/알림 상태별 아이콘 조합이 PRD와 일치한다.
      • 대화하기, DM 보내기 버튼 표시 조합별 레이아웃이 유지된다.
      • tab-bar가 title-bar 아래에 sticky 되고 title-bar black 전환 기준이 동작한다.
      • 홈 API 응답의 각 section이 홈 탭에 표시된다.
    • 기대 결과:
      • PRD Metrics 항목을 모두 만족한다.
    • 검증 기록:
      • 2026-06-15: Figma 296:14890, 296:14892, 296:14287, 296:14288, 296:14289 스크린샷을 확인해 전체 화면, 크리에이터 이미지 영역, 팔로우 상태별 title-bar 기준을 재확인했다. 구현 근거로 activity_creator_channel_home.xml의 status bar 뒤 header/overlay title-bar/tab-bar/RecyclerView 구조, CreatorChannelHomeActivity.kt의 title-bar 상태 bind/버튼 표시 조합/sticky tab/title-bar black 전환, CreatorChannelTitleBarState.kt, CreatorChannelScrollState.kt, CreatorChannelHomeSectionAdapter.kt, CreatorChannelHomeActivitySourceTest.kt를 대조했다.
      • 2026-06-15: 실제 기기 표면 검증을 위해 adb devices에서 연결 기기 2cec640c34017ece가 한 차례 표시됨을 확인하고 ./gradlew :app:assembleDebug를 실행해 BUILD SUCCESSFUL을 확인했다. 이어서 adb install -r "app/build/outputs/apk/debug/app-debug.apk"를 실행했으나 설치 시점에 adb: no devices/emulators found로 실패했고, 재확인한 adb devices에서도 연결 기기가 없어 실제 전면 화면 캡처와 스크롤/클릭 육안 검증은 완료하지 못했다. 기기 재연결 후 이 Task를 이어서 확인해야 한다.
  • Task 8.4: 검증 기록 누적

    • 수정:
      • docs/20260611_크리에이터_채널_홈_탭/plan-task.md
      • docs/20260611_크리에이터_채널_홈_탭/prd.md
    • 작업:
      • 실행한 테스트/빌드/린트 명령과 결과를 검증 기록에 누적한다.
      • 실패 후 수정한 명령이 있다면 실패 기록을 삭제하지 않고 후속 성공 기록을 추가한다.
    • 기대 결과:
      • 문서 하단에 구현 후 검증 이력이 남는다.
    • 검증 기록:
      • 2026-06-15: Phase 8.1, 8.2의 성공 기록과 Phase 8.3의 Figma/source 대조 및 실제 기기 연결 차단 기록을 plan-task.mdprd.md에 누적했다. 기존 검증 기록은 삭제하거나 덮어쓰지 않았다.

Phase 9: 크리에이터 채널 컨테이너 Activity 이름 정리

  • Task 9.1: 컨테이너 이름 변경 범위 문서화

    • 수정:
      • docs/20260611_크리에이터_채널_홈_탭/prd.md
      • docs/20260611_크리에이터_채널_홈_탭/plan-task.md
    • 작업:
      • 채널 화면 컨테이너는 CreatorChannelActivity, layout은 activity_creator_channel.xml, binding은 ActivityCreatorChannelBinding으로 정리한다.
      • 홈 탭 전용 CreatorChannelHomeViewModel, CreatorChannelHomeUiState, CreatorChannelHomeSectionAdapter, item_creator_channel_home_* 이름은 유지한다.
    • 검증 기록:
      • 2026-06-15: 사용자 요청에 따라 컨테이너 이름 변경 범위를 문서에 추가했다. 구현 전 CreatorChannelHomeActivity 참조 위치를 확인해 Manifest, 진입점, source test, layout binding 참조가 영향 범위임을 확인했다.
  • Task 9.2: Activity/Layout/Binding 이름 변경

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt
      • app/src/main/res/layout/activity_creator_channel.xml
      • app/src/main/AndroidManifest.xml
      • 크리에이터 채널 진입점 import/call site
    • 작업:
      • CreatorChannelHomeActivityCreatorChannelActivity로 변경한다.
      • activity_creator_channel_home.xmlactivity_creator_channel.xml로 변경해 generated binding을 ActivityCreatorChannelBinding으로 정리한다.
      • CreatorChannelActivity.newIntent() 계약과 EXTRA_CREATOR_ID는 유지한다.
    • 검증 기록:
      • 2026-06-15: app/src/mainapp/src/test 기준 rg "CreatorChannelHomeActivity|ActivityCreatorChannelHomeBinding|activity_creator_channel_home" 결과 남은 참조가 없음을 확인했다.
  • Task 9.3: 테스트 이름과 source assertion 정리

    • 수정:
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragmentLayoutTest.kt
    • 작업:
      • Activity source test 파일/클래스와 source path assertion을 새 이름으로 변경한다.
      • 홈 추천/진입점 테스트가 CreatorChannelActivity를 검증하도록 변경한다.
    • 기대 결과:
      • source test와 홈 route 테스트가 새 컨테이너 이름을 기준으로 통과한다.
  • Task 9.4: 이름 변경 검증

    • 실행:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest"
      • ./gradlew :app:mergeDebugResources
      • ./gradlew :app:compileDebugKotlin
      • ./gradlew :app:ktlintCheck
      • git diff --check
    • 기대 결과:
      • 모든 명령이 BUILD SUCCESSFUL 또는 출력 없음으로 통과한다.
    • 검증 기록:
      • 2026-06-15: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*", ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, git diff --check를 실행해 모두 BUILD SUCCESSFUL 또는 출력 없음으로 통과했다.
      • 2026-06-15: ./gradlew :app:ktlintCheckaudio_content 패키지명의 underscore 규칙 위반으로 실패했다. 실패 파일은 AudioContentNewAllActivity.kt, AudioContentAllByThemeActivity.kt, AudioContentDetailActivity.kt, SeriesDetailActivity.kt이며, 이번 변경은 해당 파일의 CreatorChannelActivity import/call site rename만 포함한다. 패키지 구조 변경은 범위 외라 수정하지 않았다. .editorconfig disabled_rules deprecation 경고와 Gradle deprecation warning은 기존 경고로 이번 변경과 무관하다.

Phase 10: TabLayout + ViewPager2 + 탭별 Fragment 컨테이너 전환

PRD Future Tab Architecture Decision 반영 Phase다. 후속 라이브, 오디오, 시리즈, 커뮤니티, 팬Talk, 후원 탭은 API/목록/UI가 독립적이므로, 기존 단일 Activity 내부 커스텀 tab/홈 RecyclerView 구조를 탭별 Fragment를 담는 컨테이너 구조로 바꾼다.

  • Task 10.1: 컨테이너 전환 source test와 구조 경계 고정

    • 수정:
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.kt
    • 확인:
      • app/src/main/res/layout/activity_creator_channel.xml
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt
      • 기존 프로젝트의 TabLayout, ViewPager2, FragmentStateAdapter 사용 사례
    • 작업:
      • activity_creator_channel.xmlTabLayoutViewPager2가 존재해야 한다는 source test를 추가한다.
      • CreatorChannelActivityFragmentStateAdapter 또는 전용 pager adapter를 사용한다는 source test를 추가한다.
      • CreatorChannelActivity가 홈 API/홈 section adapter를 직접 소유하지 않고 홈 탭 Fragment로 위임한다는 source test를 추가한다.
      • 기존 커스텀 HorizontalScrollView tab-bar 또는 동적 tab TextView 생성 로직은 제거 대상으로 고정한다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"
    • 기대 결과:
      • 구현 전에는 기존 단일 Activity tab 구조 때문에 RED 실패한다.
    • 검증 기록:
      • 2026-06-16: 기존 프로젝트 사용 사례를 확인한 결과 TabLayout은 여러 화면에서 XML <com.google.android.material.tabs.TabLayout>TabLayout.OnTabSelectedListener 조합으로 쓰이고, ViewPager2fragment_character_gallery_viewer.xmlCharacterGalleryViewerDialogFragment에서 제한적으로 쓰인다. 현재 production/test 코드에는 FragmentStateAdapter, TabLayoutMediator 사용 사례가 없어 Phase 10 컨테이너 전환에서 신규 도입될 구조 경계로 source test에 고정했다.
      • 2026-06-16: CreatorChannelActivitySourceTestactivity_creator_channel.xmlTabLayout/ViewPager2를 가져야 하고 기존 HorizontalScrollView/tab_container/rv_home_sections 구조를 제거해야 한다는 RED source test를 추가했다. 또한 CreatorChannelActivityFragmentStateAdapter 또는 CreatorChannelPagerAdapterbinding.viewPager.adapter를 설정하고, 홈 탭 구현을 CreatorChannelHomeFragment로 위임하며 CreatorChannelHomeViewModel/CreatorChannelHomeSectionAdapter/viewModel.loadHome(creatorId)/동적 tab TextView 생성 로직을 직접 소유하지 않아야 한다는 RED source test를 추가했다.
      • 2026-06-16: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"를 실행해 Phase 10 컨테이너 layout은 TabLayout과 ViewPager2를 가진다CreatorChannelActivitySourceTest.kt:78에서, Phase 10 Activity는 pager adapter를 사용하고 홈 탭 구현을 Fragment로 위임한다CreatorChannelActivitySourceTest.kt:94에서 실패하는 RED를 확인했다. 실패 원인은 현재 구현이 아직 HorizontalScrollView 기반 커스텀 tab-bar와 Activity 직접 홈 API/section adapter 소유 구조이기 때문이며, 이는 Task 10.1의 기대 결과와 일치한다.
  • Task 10.2: 홈 탭을 CreatorChannelHomeFragment로 분리

    • 생성:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeFragment.kt
      • app/src/main/res/layout/fragment_creator_channel_home.xml
    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt
      • app/src/main/res/layout/activity_creator_channel.xml
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.kt
    • 작업:
      • 홈 API observe, 홈 section RecyclerView, 홈 section adapter, 홈 탭 스크롤 컨텐츠를 CreatorChannelHomeFragment로 이동한다.
      • CreatorChannelHomeViewModel, CreatorChannelHomeUiState, CreatorChannelHomeSectionAdapter, item_creator_channel_home_* 이름은 홈 탭 전용 역할이므로 유지한다.
      • CreatorChannelActivity는 공통 header/title bar/tab container와 Activity-level navigation만 담당한다.
      • creatorId는 Activity에서 Fragment argument로 전달한다.
      • Fragment는 creatorId > 0일 때 viewModel.loadHome(creatorId)를 호출한다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"
      • ./gradlew :app:mergeDebugResources
      • ./gradlew :app:compileDebugKotlin
    • 수동 확인:
      • 홈 탭 기본 진입 시 기존 홈 컨텐츠가 동일하게 표시된다.
    • 검증 기록:
      • 2026-06-16: RED로 CreatorChannelActivitySourceTest를 Task 10.2 책임 분리에 맞게 갱신했다. Activity가 CreatorChannelHomeViewModel/CreatorChannelHomeSectionAdapter/viewModel.loadHome(creatorId)를 직접 소유하지 않고, CreatorChannelHomeFragmentARG_CREATOR_ID, newInstance(creatorId), CreatorChannelHomeViewModel by viewModel(), CreatorChannelHomeSectionAdapter, viewModel.homeStateLiveData.observe(viewLifecycleOwner), creatorId > 0L guard, viewModel.loadHome(creatorId)를 소유해야 한다는 source 계약을 추가했다. 구현 전 실행한 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"는 새 Fragment/layout 부재와 기존 Activity 직접 소유 구조 때문에 9개 테스트가 실패해 RED를 확인했다.
      • 2026-06-16: fragment_creator_channel_home.xml을 추가해 홈 section RecyclerView(rv_home_sections)를 이동하고, activity_creator_channel.xml에는 공통 header/title 영역과 TabLayout(tab_layout), ViewPager2(view_pager) 컨테이너만 남겼다. CreatorChannelHomeFragmentcreatorId argument를 받아 홈 API observe, 홈 section adapter, follow/chat ViewModel 액션, schedule/audio callback forwarding을 담당하도록 추가했다. CreatorChannelActivity는 header/title bind, follow sheet, DM/AI chat room navigation, schedule/audio navigation, 최소 Home 1-page FragmentStateAdapter만 담당하도록 정리했다.
      • 2026-06-16: GREEN 검증으로 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest", ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, git diff --check가 모두 PASS했다. compileDebugKotlin의 Kotlin/Gradle deprecation warning은 기존 경고로 이번 변경과 무관하다. 실제 기기 수동 확인은 이번 Task 10.2 검증 명령 범위에 포함되지 않아 실행하지 않았으며, 홈 탭 기본 진입 육안 확인은 Phase 10.4 또는 Phase 14 수동 검증에서 이어서 확인한다.
      • 2026-06-16: reviewer gate에서 NestedScrollView 내부 ViewPager2wrap_content 측정 리스크를 blocking issue로 확인했다. ViewPager2 초기 높이를 1dp로 두고, CreatorChannelHomeFragment가 홈 section submit 후 onCreatorChannelHomeContentChanged()를 호출하면 Activity가 현재 page view를 UNSPECIFIED height로 측정해 binding.viewPager.updateLayoutParams { height = measuredHeight }로 갱신하도록 보정했다. 이 계약을 CreatorChannelActivitySourceTest에 추가했고, 재검증으로 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest", ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck, git diff --check가 모두 PASS했다. 병렬 Gradle 실행 중 Kotlin incremental cache 경합 로그가 있었지만 fallback compile 후 최종 BUILD SUCCESSFUL로 종료했다.
  • Task 10.3: 탭별 placeholder Fragment와 pager adapter 추가

    • 생성:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelPagerAdapter.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelPlaceholderFragment.kt
      • 필요 시 app/src/main/res/layout/fragment_creator_channel_placeholder.xml
    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/model/CreatorChannelHomeUiModels.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt
    • 작업:
      • pager adapter는 , 라이브, 오디오, 시리즈, 커뮤니티, 팬Talk, 후원 7개 탭 순서를 유지한다.
      • CreatorChannelHomeFragment를 생성한다.
      • 나머지 6개 탭은 이번 범위에서 API/목록/UI를 구현하지 않고 placeholder Fragment를 연결한다.
      • placeholder Fragment는 후속 탭 상세 화면 구현 전까지 crash 없이 비어 있는 상태를 표시하거나 최소 빈 화면으로 유지한다.
      • 후속 탭별 Fragment 후보 이름은 PRD와 동일하게 CreatorChannelLiveFragment, CreatorChannelAudioFragment, CreatorChannelSeriesFragment, CreatorChannelCommunityFragment, CreatorChannelFanTalkFragment, CreatorChannelDonationFragment로 둔다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"
      • ./gradlew :app:compileDebugKotlin
    • 검증 기록:
      • 2026-06-16: RED로 CreatorChannelActivitySourceTestCreatorChannelPagerAdapter, CreatorChannelPlaceholderFragment, fragment_creator_channel_placeholder.xml source 계약을 추가했다. 구현 전 실행한 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"CreatorChannelPagerAdapter/placeholder 파일 부재와 Activity의 기존 1-page inline FragmentStateAdapter 구조 때문에 3개 테스트가 실패해 RED를 확인했다.
      • 2026-06-16: CreatorChannelPagerAdapter를 추가해 CreatorChannelTab.entries 7개 순서를 유지하고, HomeCreatorChannelHomeFragment.newInstance(creatorId), 나머지 6개 탭은 CreatorChannelPlaceholderFragment.newInstance(tab)을 반환하도록 구현했다. CreatorChannelPlaceholderFragmentfragment_creator_channel_placeholder.xml은 후속 탭 상세 구현 전까지 crash 없는 최소 빈 화면 역할만 하도록 추가했다.
  • Task 10.4: TabLayoutMediator 연결과 sticky/header 동작 재검증

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt
      • app/src/main/res/layout/activity_creator_channel.xml
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.kt
    • 작업:
      • TabLayoutMediatorTabLayoutViewPager2를 연결한다.
      • 탭 label은 기존 CreatorChannelTab.labelResId를 사용한다.
      • tab item font/size는 Phase 11에서 보정할 수 있도록 custom tab view 또는 TabLayout textAppearance 적용 지점을 명확히 둔다.
      • 공통 header/title bar/sticky 기준이 ViewPager2 전환 후에도 유지되는지 확인한다.
      • 기존 수동 onTabClicked(tab) no-op 정책은 ViewPager2 placeholder 연결 정책으로 대체한다.
      • ViewPager2 swipe 전환 허용 여부는 PRD Open Question에 맞춰 구현 계획에서 확정하되, 기본은 사용자 입력 swipe를 허용하지 않거나 기존 탭 클릭 UX와 충돌이 적은 방식으로 둔다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"
      • ./gradlew :app:mergeDebugResources
      • ./gradlew :app:compileDebugKotlin
    • 수동 확인:
      • 7개 탭이 TabLayout에 표시된다.
      • 홈 탭 컨텐츠가 Fragment 안에서 표시된다.
      • 홈 외 탭 선택 시 crash가 없고 placeholder가 표시된다.
      • 공통 header와 sticky title/tab 동작이 깨지지 않는다.
    • 검증 기록:
      • 2026-06-16: CreatorChannelActivity의 inline 1-page adapter와 수동 TabLayout.addTab() 호출을 제거하고, binding.viewPager.adapter = CreatorChannelPagerAdapter(this, creatorId)TabLayoutMediator(binding.tabLayout, binding.viewPager)를 연결했다. tab label은 CreatorChannelTab.entries[position].labelResId에서 가져오며, 기존 Task 10.2의 ViewPager2 동적 높이 보정은 page 변경 시에도 실행되도록 ViewPager2.OnPageChangeCallback을 등록했다. Activity destroy 시 tabLayoutMediator.detach()unregisterOnPageChangeCallback()을 호출해 mediator/callback을 정리한다.
      • 2026-06-16: GREEN 검증으로 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest", ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck, git diff --check가 모두 PASS했다. ktlintCheck.editorconfig disabled_rules deprecation warning과 Gradle deprecation warning은 기존 경고로 이번 변경과 무관하다. 실제 기기 수동 확인은 수행하지 못했으며, 7개 탭 표시/placeholder 선택/스크롤 동작 육안 검증은 Phase 14 최종 수동 검증에서 이어서 확인한다.
      • 2026-06-16: 후속 리뷰에서 CreatorChannelHomeFragment가 Fragment property adapter를 유지하면서 RecyclerView.adapter를 해제하지 않는 view tree leak 가능성, TabLayout sticky translation 제거로 tab-bar가 스크롤과 함께 사라지는 문제, 홈 Fragment view 파괴 시 homeActionDelegate가 null이 되어 공통 follow/bell/chat 액션이 no-op이 될 수 있는 문제를 확인했다. RED로 CreatorChannelActivitySourceTestbinding.rvHomeSections.adapter = null, binding.tabLayout.translationY = tabTranslationY.toFloat(), val tabBarTop = headerHeight - scrollY + tabTranslationY, binding.viewPager.offscreenPageLimit = CreatorChannelTab.entries.size - 1 계약을 추가했고, 구현 전 3개 테스트 실패를 확인했다. 수정 후 CreatorChannelHomeFragment.onDestroyView()에서 adapter를 null로 해제하고, Activity scroll 계산에 TabLayout sticky translation을 복구했으며, 홈 Fragment delegate가 탭 전환만으로 사라지지 않도록 ViewPager2.offscreenPageLimit을 6으로 설정했다. 재검증으로 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest", ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck, git diff --check가 모두 PASS했다.
      • 2026-06-16: 실제 확인 중 ViewPager2가 동작하지 않는 것처럼 보인다는 피드백을 받아 binding.viewPager.isUserInputEnabled = true로 swipe 입력을 허용하고, 홈 외 placeholder 화면이 1dp/숨김 텍스트라 전환이 보이지 않던 문제를 막기 위해 fragment_creator_channel_placeholder.xml 높이를 160dp로 조정하고 placeholder text를 표시하도록 변경했다. CreatorChannelActivitySourceTest에 swipe 허용과 visible placeholder 계약을 갱신했으며, 최초 검증 중 KSP cache corruption으로 한 차례 실패했지만 재실행 후 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest", ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck, git diff --check가 모두 PASS했다.

Phase 11: 상단 상태/탭/액션 후속 보강

2026-06-16 PRD 보강분을 반영하는 Phase다. title-bar sticky 닉네임, tab-bar typography, 더보기 BottomSheet, 팔로우/알림 직접 액션, 본인 페이지 상단 액션 정책을 한 묶음으로 처리한다.

  • Task 11.1: title-bar sticky 닉네임과 tab-bar typography 보정

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt
      • app/src/main/res/layout/activity_creator_channel.xml
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.kt
    • Figma 기준:
      • tab-bar item text: Figma 296:14894
    • 작업:
      • title-bar가 black 배경으로 전환된 상태에서 뒤로가기 버튼 우측에 creator.nickname을 표시한다.
      • title-bar가 이미지 overlay 상태로 복귀하면 닉네임을 숨긴다.
      • 닉네임 TextView의 font/textSize/color/ellipsize/maxLines는 app/src/main/res/layout/view_title_bar_default.xmltv_title_bar_title와 동일하게 맞춘다.
      • 긴 닉네임은 우측 액션 영역과 겹치지 않도록 1줄 말줄임 처리한다.
      • tab-bar item 텍스트는 선택/비선택 상태 모두 Figma 296:14894 기준 Pretendard Variable Medium, 16sp 상당 크기, line-height 1.45, letterSpacing 0을 유지한다.
      • 선택 상태에서만 font/size가 달라지는 구현이 있으면 제거하고 색상/indicator로만 선택 상태를 구분한다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"
      • ./gradlew :app:mergeDebugResources
      • ./gradlew :app:compileDebugKotlin
    • 검증 기록:
      • 2026-06-16: sticky black title-bar 닉네임과 CreatorChannelTabText tab textAppearance 계약을 CreatorChannelActivitySourceTest에 추가하고 구현했다. CreatorChannelActivitySourceTest, mergeDebugResources, compileDebugKotlin PASS.
  • Task 11.2: 더보기 BottomSheet와 팔로우/알림 직접 액션 보정

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeViewModel.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeViewModelTest.kt
    • 확인:
      • app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/UserProfileActivity.kt
      • 기존 UserProfileActivity.showOptionMenu()user_profile_option_menu, user_profile_option_menu_2 분기
      • 기존 BottomSheetDialog 또는 프로젝트 내 유사 BottomSheet 메뉴 구현
    • 작업:
      • 더보기 버튼 터치 시 기존 UserProfileActivity.showOptionMenu()와 동일한 의미의 차단/차단 해제, 사용자 신고, 프로필 신고 액션을 BottomSheet로 표시한다.
      • 팔로우하지 않은 상태의 layout_follow_capsule 터치 시 기존 크리에이터 팔로우 API를 follow=true, notify=true로 바로 호출한다.
      • 팔로잉 상태에서 iv_bell 터치 시 BottomSheet 없이 follow=true, notify=false API를 바로 호출하고 성공 후 알림 꺼짐 아이콘으로 변경한다.
      • 팔로잉 상태에서 layout_follow_capsule 터치 시 BottomSheet 없이 follow=false, notify=false API를 바로 호출하고 완료/오류 토스트를 표시한다.
      • 팔로우/알림 요청 중에는 중복 터치로 같은 API가 중복 호출되지 않게 한다.
      • 기존 CreatorFollowNotifyFragment를 띄우는 흐름이 남아 있으면 이번 요구에 맞게 제거한다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeViewModelTest"
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"
      • ./gradlew :app:compileDebugKotlin
    • 검증 기록:
      • 2026-06-16: 더보기 BottomSheet, 차단/사용자 신고/프로필 신고 연결, 팔로우/알림 직접 액션을 구현했다. CreatorChannelHomeViewModelTest, CreatorChannelActivitySourceTest, compileDebugKotlin PASS.
      • 2026-06-16: 리뷰에서 isBlock=true 상태의 사용자 차단해제 메뉴가 실제로는 차단 API를 호출하는 문제가 발견되어, BottomSheet callback을 block/unblock으로 분리하고 UserRepository.memberUnBlock() 위임 및 성공 시 header.isBlock=false 상태 갱신을 추가했다.
      • 2026-06-16: 후속 API 계약 확인 결과 크리에이터 채널 홈에서는 차단된 사용자가 서버 예외 처리로 진입하지 못하므로 CreatorChannelCreatorResponse.isBlock, CreatorChannelHeaderUiModel.isBlock, BottomSheet 차단해제 분기, unblockUser() 경로를 제거했다. 더보기 BottomSheet는 진입 가능한 채널에서 차단/사용자 신고/프로필 신고만 표시한다.
      • 2026-06-16: 팔로잉 알림 꺼짐 상태에서 종 아이콘을 다시 누르면 follow=true, notify=!header.isNotify 조합으로 알림 설정 API가 호출되도록 수정했다. 팔로우 취소 성공 시 creator_channel_unfollow_success 다국어 토스트를 표시한다.
      • 2026-06-16: 로딩 중 대화하기, DM 보내기, 팔로우, 더보기 버튼이 먼저 보여 혼란스럽다는 피드백을 반영해 각 버튼의 XML 기본 visibility를 gone으로 변경하고, 홈 API 로딩 완료 후 bindHeader()/bindTitleBar()에서 필요한 버튼만 표시하도록 유지했다.
  • Task 11.3: 크리에이터 본인 페이지 상단 액션 정책 추가

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/data/CreatorChannelHomeModels.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/model/CreatorChannelHomeUiModels.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/model/CreatorChannelHomeMappers.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/model/CreatorChannelTitleBarState.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeMapperTest.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelTitleBarStateTest.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.kt
    • 확인:
      • 홈 API에 isOwner 또는 동등한 필드가 제공되는지 확인한다.
      • API 필드가 없으면 로그인 사용자 정보와 creator.creatorId/연결 식별자를 대조할 수 있는 기존 저장소/세션 정보를 확인한다.
    • 작업:
      • 크리에이터 본인 여부를 UI model에 포함한다.
      • 본인 페이지에서는 title-bar의 팔로우/팔로잉 capsule, 알림 아이콘, 더보기 아이콘을 표시하지 않는다.
      • 본인 페이지에서는 더보기 BottomSheet 또는 차단/신고 액션에 진입할 수 없게 한다.
      • 본인 페이지가 아닌 경우 기존 팔로우/더보기 동작은 유지한다.
      • 본인 여부 판정에 API 필드가 필요하지만 제공되지 않는 경우, 구현을 막지 말고 해당 필드 추가 필요성을 Task 검증 기록에 남긴다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeMapperTest"
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelTitleBarStateTest"
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"
      • ./gradlew :app:compileDebugKotlin
    • 검증 기록:
      • 2026-06-16: 홈 API DTO에 선택 필드 isOwner, isBlock 기본값을 추가하고 UI model/mapper로 전달했다. 본인 페이지에서는 title-bar 팔로우 capsule, 알림, 더보기를 숨기고 더보기 진입을 차단하도록 구현했다. CreatorChannelHomeMapperTest, CreatorChannelActivitySourceTest, compileDebugKotlin PASS.
      • 2026-06-16: 후속 API 계약 확인 결과 CreatorChannelCreatorResponse.isOwner도 서버 응답에 없으므로 DTO 필드를 제거했다. 본인 여부는 SharedPreferenceManager.userId == creator.creatorId로 계산하며, toUiContent(currentMemberId: Long) 파라미터를 통해 mapper에서 CreatorChannelHeaderUiModel.isOwner를 만든다.
  • Task 11.4: 본인 페이지 DM 확인하기 진입 추가

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt
      • app/src/main/java/kr/co/vividnext/sodalive/main/MainActivity.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/chat/ChatMainFragment.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/chat/model/ChatRoomFilter.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.kt
      • 필요 시 메인/채팅 탭 source test
    • 확인:
      • MainActivity의 bottom tab 선택 구조
      • ChatMainFragment의 필터 선택 구조
      • ChatRoomFilter.DM
    • 작업:
      • 본인 페이지에서는 대화하기 버튼을 표시하지 않는다.
      • 본인 페이지에서는 DM 보내기 대신 DM 확인하기 버튼을 표시한다.
      • DM 확인하기 버튼만 표시되어도 버튼은 가운데 정렬되고, 기존 버튼 영역 높이와 여백은 유지한다.
      • DM 확인하기 터치 시 MainActivity로 이동하거나 기존 MainActivity instance를 재사용해 메인 대화 탭을 선택한다.
      • ChatMainFragment는 진입 파라미터를 받아 ChatRoomFilter.DM이 선택된 상태로 표시한다.
      • 기존 타인 페이지의 DM 보내기DmChatRoomActivity.newIntentByCreatorId(context, creatorId) 이동을 유지한다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"
      • ./gradlew :app:compileDebugKotlin
    • 검증 기록:
      • 2026-06-16: 본인 페이지에서 DM 보내기 대신 DM 확인하기를 표시하고 MainV2Activity.newChatDmIntent()로 메인 대화 탭 및 ChatRoomFilter.DM 초기 선택을 전달하도록 구현했다. 기존 MainV2 인스턴스가 이미 채팅 탭인 경우에도 ChatMainFragment.selectFilter()로 DM 필터를 갱신한다. CreatorChannelActivitySourceTest, compileDebugKotlin PASS.
      • 2026-06-16: creator_channel_dm_check_button을 ko/en/ja 리소스에 추가해 본인 페이지 DM 확인하기 버튼 문구를 다국어 처리했다.

Phase 11 후속 검증 로그

  • 2026-06-16: rg -n "isOwner|isBlock|unblockUser|onClickUnblock|newInstance\(isBlocked|toUiContent\(\)" app/src/main/java app/src/test/java로 크리에이터 채널 범위의 제거 대상 참조를 점검했다. 관련 production 코드에는 isBlock/unblockUser 잔여 사용이 없고, 테스트 계약은 제거 여부를 검증하도록 갱신했다.
  • 2026-06-16: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeMapperTest" --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeViewModelTest" --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest" PASS. 중간에 CreatorChannelMoreBottomSheet.ktBundle import 누락으로 compileDebugKotlin이 실패했으나 android.os.Bundle import를 추가해 재검증 통과했다.
  • 2026-06-16: ./gradlew :app:mergeDebugResources :app:compileDebugKotlin :app:ktlintCheck PASS, git diff --check PASS. 중간에 CreatorChannelMoreBottomSheet.kt의 unused R import로 ktlintMainSourceSetCheck가 실패했으나 import 제거 후 재검증 통과했다. .editorconfig disabled_rules deprecation warning과 Gradle deprecation warning은 기존 경고로 이번 변경과 무관하다.
  • 2026-06-16: post-implementation review에서 reportUser()/reportProfile() 실패 시에도 신고 접수 완료 토스트가 표시되는 문제, 차단 성공 토스트 하드코딩, ChatMainFragmentLayoutTest의 기존 loadFirstPage() source 계약 미갱신이 blocking으로 확인되었다. 신고 API success=false/throwable 시 common_error_unknown 토스트로 분기하고, 차단 성공 문구를 creator_channel_block_success ko/en/ja 리소스로 이동했으며, 채팅 탭 source test를 viewModel.loadFirstPage(initialFilter ?: ChatRoomFilter.ALL) 계약으로 갱신했다.
  • 2026-06-16: 리뷰 지적 수정 후 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeMapperTest" --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeViewModelTest" --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest" --tests "kr.co.vividnext.sodalive.v2.main.chat.ChatMainFragmentLayoutTest" PASS, ./gradlew :app:mergeDebugResources :app:compileDebugKotlin :app:ktlintCheck PASS, git diff --check PASS.

Phase 12: 홈 탭 섹션 후속 UI/액션 보강

후원 empty, 최신 콘텐츠 터치, 날짜 표시, 오디오/시리즈/활동 영역의 세부 Figma 정합성을 묶어서 처리한다. 섹션 하나당 Phase를 나누지 않고 관련 홈 컨텐츠 보정 Task로 묶는다.

  • Task 12.1: 후원 empty UI와 최신 콘텐츠/날짜 표시 보강

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/model/CreatorChannelHomeMappers.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt
      • app/src/main/res/layout/item_creator_channel_home_donation.xml
      • app/src/main/res/layout/item_creator_channel_home_latest_audio.xml
      • app/src/main/res/layout/item_creator_channel_home_notice.xml
      • app/src/main/res/layout/item_creator_channel_home_community.xml
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeMapperTest.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.kt
    • Figma 기준:
      • 후원 empty UI: 290:8820
    • 작업:
      • channelDonations가 비어 있으면 후원 섹션을 숨기지 않고 empty 안내 UI를 표시한다.
      • empty card width는 374dp 고정이 아니라 부모 섹션 좌우 여백 안에서 match_parent로 처리한다.
      • empty card는 height 196dp, gray_900 배경, 14dp radius, 처음으로 크리에이터를 / 후원해 보세요!, 흰색 후원하기 capsule을 표시한다.
      • 후원하기 버튼 터치 동작은 기존 후원 플로우/상세 화면 진입점이 있으면 재사용하고, 없으면 후원 API/화면 확정 필요 항목으로 검증 기록에 남긴다.
      • 최신 오디오 row/card 터치 시 latestAudioContent.audioContentId로 기존 AudioContentDetailActivity에 이동한다.
      • 공지/커뮤니티 게시글 날짜는 API dateUtc 원문 대신 기존 앱의 상대 날짜 표시 방식으로 변환한다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeMapperTest"
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"
      • ./gradlew :app:mergeDebugResources
      • ./gradlew :app:compileDebugKotlin
    • 검증 기록:
      • 2026-06-16: Figma 290:8820을 확인해 후원 empty UI가 SectionTitle(후원), 196dp gray_900 card, 24sp bold 2줄 안내 문구, 흰색 후원하기 capsule 구조임을 반영했다. RED로 CreatorChannelHomeMapperTest에서 빈 channelDonationsCreatorChannelHomeSection.Donations(emptyList())를 생성해야 한다는 계약을 추가해 NoSuchElementException 실패를 확인했고, CreatorChannelActivitySourceTest에서 후원 empty layout/string, 최신 오디오 card click, 공지/커뮤니티 상대 시간 formatter 계약 5건 실패를 확인했다.
      • 2026-06-16: mapper는 빈 후원 목록에서도 후원 섹션을 생성하도록 변경했고, item_creator_channel_home_donation.xml에 374dp 고정이 아닌 부모 좌우 여백 내 match_parent empty card를 추가했다. CreatorChannelHomeSectionAdapter는 후원 목록/empty visibility를 전환하고, 최신 오디오 card click을 onAudioContentClick(item.audioContent)로 연결하며, 공지/커뮤니티 dateUtcformatUtcRelativeTimeText(...)로 표시하도록 수정했다. 후원하기 버튼은 후속 보강에서 기존 채널 후원 API와 LiveRoomDonationDialog를 재사용하는 flow로 연결했다.
      • 2026-06-16: 최초 GREEN 검증 중 새 리소스가 존재하지 않는 @dimen/radius_100, @style/Typography.Heading0를 참조해 processDebugResources가 실패했고, 기존 token에 맞춰 100dp radius와 Typography.Heading1로 수정했다. 병렬 Gradle 실행 중 KSP cache NoSuchFileException: app/build/kspCaches/debug/backups가 한 차례 발생해 ./gradlew --stop 후 순차 재실행했다.
      • 2026-06-16: 최종 검증으로 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeMapperTest", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*", ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, git diff --check가 모두 PASS했다. Kotlin/Gradle deprecation warning은 기존 경고로 이번 변경과 무관하다.
      • 2026-06-16: Task 12.1 보강으로 후원 버튼이 LiveRoomDonationDialogUserProfileActivity와 같은 옵션(isLiveDonation=true, messageMaxLength=100, 비밀후원 label, secret mission hint 비활성, screenWidth - 26.7dp)으로 표시하도록 연결하고, 성공 시 기존 채널 후원 API 호출 후 홈을 재조회하도록 RED/GREEN 테스트를 추가했다. 본인 채널은 일반/empty 후원 버튼을 숨기고 empty 문구를 후원 내역이 없습니다로 표시하도록 다국어 리소스와 source 계약을 보강했다.
      • 2026-06-16: RecyclerView rebind 시 후원 row가 중복 추가되지 않도록 donationItems?.removeAllViews()를 추가했고, CreatorChannelActivitySourceTest source contract로 재검증했다.
      • 2026-06-16: 리뷰 보강으로 후원 row 날짜를 UTC 원문 대신 formatUtcRelativeTimeText(...)로 표시하고, 채널 후원 성공 시 SharedPreferenceManager.can 차감 및 진행 중 중복 요청 방지 테스트를 추가했다.
    • 리뷰 후속 하위 작업:
      • RecyclerView viewType은 layoutResId라 서로 다른 viewType 간 listener 누수 가능성은 낮지만, 최신 오디오가 아닌 bind에서도 root click state를 명시적으로 초기화해 명확성과 안전성을 높인다.
      • LiveRoomDonationDialog가 validation/dismiss/charge navigation을 소유하고 UserProfileActivity도 callback-only 패턴을 쓰므로, Activity dismiss 흐름은 변경하지 않는다.
      • 로컬 can 차감은 전체 balance resync가 아니라 최소 안전 장치로 (SharedPreferenceManager.can - can).coerceAtLeast(0)만 적용한다.
  • Task 12.2: 오디오/시리즈 아이템 세부 UI와 터치 액션 보강

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt
      • app/src/main/res/layout/item_creator_channel_home_audio.xml
      • app/src/main/res/layout/item_creator_channel_home_audio_content.xml
      • app/src/main/res/layout/item_creator_channel_home_series.xml
      • 시리즈 card custom view 파일
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.kt
    • Figma 기준:
      • 홈 컨텐츠: 296:14895
      • 시리즈 Contents(type=series, size=m)
    • 작업:
      • 오디오 이미지 위 tv_audio_content_free_tag width를 wrap_content로 수정한다.
      • 오디오 영역은 표시되는 audioContents 개수만큼만 높이를 차지한다.
      • 오디오 콘텐츠가 1개일 때 3개 이상 있을 때와 같은 고정 높이, 빈 슬롯, placeholder 영역을 만들지 않는다.
      • 시리즈 이미지 위 layout_series_original_tag width/height를 wrap_content로 수정한다.
      • 시리즈 original tag margin/padding은 Figma Contents(type=series, size=m) 기준으로 맞춘다.
      • 시리즈 아이템 터치 시 series.seriesId를 사용해 기존 SeriesDetailActivity로 이동한다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"
      • ./gradlew :app:mergeDebugResources
      • ./gradlew :app:compileDebugKotlin
    • 검증 기록:
      • 2026-06-16: Figma 296:14895와 시리즈 Contents(type=series, size=m) 구조를 확인해 오디오 free tag와 시리즈 original tag sizing 기준을 재확인했다. RED로 CreatorChannelActivitySourceTest에 오디오 tv_audio_content_free_tag wrap_content, audio grid span count 동적 보정, 시리즈 original tag wrap_content/padding, 시리즈 상세 이동 계약을 추가했고, 최초 실행은 formatCreatorChannelDebutActivityValue 미구현 컴파일 실패로 RED를 확인했다.
      • 2026-06-16: item_creator_channel_home_audio_content.xml의 free tag width를 wrap_content로 변경하되 minWidth=34dp와 padding을 유지했다. CreatorChannelHomeSectionAdapter는 표시되는 오디오 개수에 맞춰 GridLayoutManager.spanCount = itemCount.coerceIn(1, AUDIO_GRID_SPAN_COUNT)로 보정해 1개 항목에서 3개 row 높이를 예약하지 않게 했다. item_creator_channel_home_series_content.xml의 original tag는 width/height wrap_content, minHeight=24dp, horizontal padding으로 조정하고, CreatorChannelHomeFragment/CreatorChannelActivityCreatorChannelSeriesResponse click forwarding과 SeriesDetailActivity + Constants.EXTRA_SERIES_ID 이동을 연결했다.
      • 2026-06-16: 검증 중 기존 source assertion의 과거 70dp tag width 계약과 줄바꿈 전 문자열 계약이 Phase 12 구현과 충돌해 테스트를 새 계약 기준으로 갱신했다. 이후 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*", ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck, git diff --check가 모두 PASS했다. ktlintCheck.editorconfig disabled_rules deprecation warning과 Gradle deprecation warning은 기존 경고로 이번 변경과 무관하다.
  • Task 12.3: 활동 영역 Figma 정합성과 데뷔 날짜/D+n 버그 수정

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt
      • app/src/main/res/layout/item_creator_channel_home_activity.xml
      • app/src/main/res/values/strings.xml
      • app/src/main/res/values-en/strings.xml
      • app/src/main/res/values-ja/strings.xml
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.kt
    • Figma 기준:
      • 활동 영역: 296:15001
    • 작업:
      • 활동 섹션 제목은 SectionTitle(활동) 기준 Pretendard Variable Bold, 20sp 상당 크기를 따른다.
      • 활동 label/value row는 Pretendard Variable Medium, 16sp 상당 크기, line-height 1.45, letterSpacing 0을 따른다.
      • label 색상은 #939393, value 색상은 white로 맞춘다.
      • label/value 사이 8dp gap, row 간 8dp 간격을 유지한다.
      • activity.debutDateUtc는 원문 ISO 문자열을 그대로 표시하지 않고 yyyy.MM.dd로 변환한다.
      • 데뷔 값은 yyyy.MM.dd(D+n) 형식으로 표시한다. 예: 2026.06.11(D+1).
      • activity.dDay 값이 있으면 날짜 파싱 실패 또는 debutDateUtc 누락 상황에서도 D+n이 누락되지 않게 한다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"
      • ./gradlew :app:mergeDebugResources
      • ./gradlew :app:compileDebugKotlin
    • 검증 기록:
      • 2026-06-16: Figma 296:15001 스크린샷/metadata를 확인해 활동 섹션이 SectionTitle(활동), label/value 16sp medium row, label #939393, value white, label/value 8dp gap, row 간 8dp 구조임을 반영했다. item_creator_channel_home_activity.xml의 각 label/value에 Typography.Body2, lineSpacingMultiplier=1.45, letterSpacing=0, label #939393, value @color/white, label marginEnd=8dp를 적용했다.
      • 2026-06-16: formatCreatorChannelDebutActivityValue(debutDateUtc, dDay, timeZone, locale) helper를 추가해 UTC ISO 날짜를 yyyy.MM.dd로 변환하고 yyyy.MM.dd(D+n) 형식으로 표시하도록 수정했다. debutDateUtc가 null/blank이거나 파싱 실패해도 dDay가 누락되지 않도록 dDay를 fallback으로 반환한다.
      • 2026-06-16: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*", ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck, git diff --check가 모두 PASS했다. 최초 ktlintCheck는 새/기존 source assertion과 adapter 긴 줄로 실패했으나 줄바꿈만 보정한 뒤 재실행해 PASS했다.

Phase 13: 크리에이터 본인 페이지 Floating Button

본인 페이지 전용 홈 탭 FAB와 확장 액션을 추가한다. 상단 액션 정책은 Phase 11에서 처리하고, FAB overlay/animation/버튼 액션은 이 Phase에서 처리한다.

  • Task 13.1: Floating Button 기본/확장 layout 추가

    • 수정:
      • app/src/main/res/layout/activity_creator_channel.xml
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.kt
    • 생성 후보:
      • app/src/main/res/drawable/bg_creator_channel_owner_fab.xml
      • app/src/main/res/drawable/bg_creator_channel_owner_fab_close.xml
    • Figma 기준:
      • 기본 상태: 665:19221
      • 확장/dim 상태: 665:19352
    • 작업:
      • Floating Button은 크리에이터 본인 페이지의 탭에서만 표시한다.
      • 기본 FAB는 우측/하단 safe area를 고려해 14dp inset으로 배치한다.
      • 기본 FAB는 soda/400 배경, 100dp radius, 14dp padding, 38dp icon 영역, shadow를 따른다.
      • FAB 터치 시 전체 화면 dim overlay를 표시한다.
      • dim 색상은 Figma 기준 rgba(0,0,0,0.4)로 적용한다.
      • 확장 상태에서 버튼은 우측 하단 정렬을 유지하고 세로 간격 14dp로 배치한다.
      • 확장 버튼 순서는 위에서부터 커뮤니티 글 올리기, 오디오 콘텐츠 올리기, 라이브 만들기, 닫기다.
      • 아이콘은 순서대로 ic_new_upload_community_post, ic_new_upload_audio, ic_new_create_live, ic_new_x_black을 사용한다.
      • 닫기 버튼은 흰색 배경을 사용하고 터치 시 dim과 확장 버튼을 닫는다.
      • dim 뒤 홈 컨텐츠, tab-bar, title-bar 액션이 잘못 터치되지 않게 한다.
      • dim 영역 터치도 닫기 동작으로 처리할지, 닫기 버튼만 닫기 동작으로 처리할지는 구현 시 기존 앱 overlay UX를 확인해 확정하고 검증 기록에 남긴다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"
      • ./gradlew :app:mergeDebugResources
      • ./gradlew :app:compileDebugKotlin
    • 검증 기록:
      • 2026-06-16: Figma 665:19221, 665:19352와 기존 Activity overlay 구조를 기준으로 본인 홈 탭 전용 FAB 기본/확장 layout을 activity_creator_channel.xml에 추가했다. Activity 루트가 이미 ConstraintLayout overlay 구조이고 CreatorChannelHomeFragment 루트는 단일 RecyclerView이므로 FAB는 Activity에 배치했다. 기본 FAB는 14dp inset, soda_400 capsule 배경, 14dp padding, 38dp icon, elevation을 적용했고, 확장 상태는 #66000000 dim과 icon-only 원형 버튼을 14dp 간격으로 배치했다. dim 영역은 기존 overlay UX에 맞춰 터치 시 닫히도록 확정했다.
      • 2026-06-16: RED로 CreatorChannelActivitySourceTest.Phase 13 owner FAB source는 본인 홈 탭 기본 확장 layout을 가진다를 추가하고 실행해 owner_fab_dim 등 레이아웃 미구현으로 실패함을 확인했다. 구현 후 동일 focused test와 ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, git diff --check가 PASS했다. CreatorChannelActivitySourceTest 전체 실행은 기존 후원 섹션 source 계약(item_creator_channel_home_donation.xml 높이 196dp 기대, 현재 wrap_content) 1건으로 실패했으며 이번 FAB 변경과 무관해 수정하지 않았다.
      • 2026-06-16: ic_new_upload_community_post, ic_new_upload_audio, ic_new_create_live, ic_new_x_black는 기존 drawable-mdpi PNG가 있음을 재확인했고, 처음 잘못 추가했던 동일 이름 vector XML 4개는 제거해 기존 디자인 에셋을 사용하도록 정리했다.
      • 2026-06-16: 사용자 피드백으로 새 Figma 기본 FAB 665:19221, 확장 메뉴 665:19352를 확인한 결과, 확장 상태는 텍스트 pill 버튼이 아니라 66dp 원형 icon-only FAB 4개 구조임을 확인했다. RED로 source test 계약을 갱신해 기존 텍스트 pill 구현 실패를 확인했고, activity_creator_channel.xml의 확장 버튼을 FrameLayout 원형 FAB와 38dp icon으로 보정했다. 커뮤니티/오디오 버튼은 soda_400, 라이브 버튼은 Figma 기준 soda_800, 닫기 버튼은 흰색 배경을 사용한다. 보정 후 focused source test, ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, git diff --check가 PASS했다.
  • Task 13.2: Floating Button Spring animation과 하단 inset 보정

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.kt
    • 작업:
      • FAB 펼침/닫힘 animation은 Spring easing을 사용한다.
      • Spring parameter는 Mass 1, Stiffness 256, Damping 24를 따른다.
      • 확장/닫힘 중 중복 터치로 상태가 꼬이지 않게 한다.
      • navigation bar/gesture inset을 반영해 FAB touch area가 화면 밖으로 밀리지 않도록 한다.
      • 홈 컨텐츠 마지막 영역이 FAB에 가려져 읽기 어려우면 RecyclerView/NestedScroll 하단 padding을 보정한다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"
      • ./gradlew :app:compileDebugKotlin
    • 검증 기록:
      • 2026-06-16: RED로 CreatorChannelActivitySourceTest에 FAB Spring animation, Mass 1, Stiffness 256, Damping 24, animation 중 중복 터치 방지, navigation bar inset 반영, 홈 컨텐츠 하단 padding 보정 source 계약을 추가했다. 구현 전 focused 실행에서 2개 테스트가 실패해 RED를 확인했다.
      • 2026-06-16: CreatorChannelActivityValueAnimator 기반 SpringInterpolator(mass=1f, stiffness=256f, damping=24f)를 추가하고, 펼침/닫힘 중 isOwnerFabAnimating으로 중복 터치를 차단했다. WindowInsetsCompat.Type.navigationBars() bottom inset을 기본 14dp margin에 더해 기본/확장 FAB bottom margin을 갱신하고, ViewPager2 bottom padding을 96dp로 보정했다.
      • 2026-06-16: focused Phase 13 source test, ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck, git diff --check가 PASS했다. ktlintCheck.editorconfig disabled_rules deprecation warning과 Kotlin/Gradle deprecation warning은 기존 경고로 이번 변경과 무관하다.
  • Task 13.3: Floating Button 3개 액션 진입점 연결

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.kt
      • 필요 시 기존 커뮤니티 작성/오디오 업로드/라이브 생성 화면 route 파일
    • 확인:
      • 커뮤니티 글 작성 기존 Activity/Fragment/route
      • 오디오 콘텐츠 업로드 기존 Activity/Fragment/route
      • 라이브 만들기 기존 Activity/Fragment/route
    • 작업:
      • 커뮤니티 글 올리기는 기존 커뮤니티 작성 화면으로 이동한다.
      • 오디오 콘텐츠 올리기는 기존 오디오 콘텐츠 업로드 화면으로 이동한다.
      • 라이브 만들기는 기존 라이브 생성 화면으로 이동한다.
      • 기존 진입점이 없거나 필요한 파라미터가 불명확하면 임의 구현하지 않고 해당 액션은 검증 기록에 “진입점 미확정”으로 남긴다.
      • 각 액션 터치 후에는 FAB 확장 상태를 닫는다.
    • 검증 명령:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"
      • ./gradlew :app:compileDebugKotlin
    • 검증 기록:
      • 2026-06-16: 기존 진입점 조사 결과 CreatorCommunityWriteActivity, AudioContentUploadActivity, LiveRoomCreateActivity는 모두 Manifest에 등록되어 있고 FAB 액션 연결에 필요한 필수 intent extra가 없음을 확인했다. 라이브 생성 화면의 Constants.EXTRA_LIVE_TIME_NOW는 optional이며 기본값 true를 사용한다.
      • 2026-06-16: owner_fab_community_button, owner_fab_audio_button, owner_fab_live_button 클릭 시 각각 커뮤니티 글쓰기, 오디오 콘텐츠 업로드, 라이브 만들기 화면으로 이동하도록 연결했고, 각 액션 직전에 collapseOwnerFab(animate = false)로 확장 상태를 닫도록 구현했다.
      • 2026-06-16: focused Phase 13 source test는 RED 후 GREEN으로 통과했다. ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*"는 104개 중 기존 후원 섹션 source 계약 1건(item_creator_channel_home_donation.xmlandroid:layout_height="196dp"를 포함해야 한다는 assertion)으로 실패했으며 이번 FAB 변경과 무관해 수정하지 않았다. ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck, git diff --check는 PASS했다.

Phase 14: 후속 보강 최종 검증과 문서 기록

  • Task 14.1: 후속 보강 단위/source 테스트 실행

    • 실행:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*"
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*"
    • 기대 결과:
      • 크리에이터 채널 후속 보강 테스트와 기존 홈 진입점 테스트가 BUILD SUCCESSFUL로 통과한다.
  • Task 14.2: 리소스/컴파일/린트 검증

    • 실행:
      • ./gradlew :app:mergeDebugResources
      • ./gradlew :app:compileDebugKotlin
      • ./gradlew :app:ktlintCheck
      • git diff --check
    • 기대 결과:
      • mergeDebugResources, compileDebugKotlin, git diff --check는 통과한다.
      • ktlintCheck가 기존 audio_content 패키지명 underscore 문제로 실패하면, 이번 변경 파일에서 발생한 실패인지 구분해 검증 기록에 남긴다.
  • Task 14.3: 수동 화면 검증

    • 확인:
      • 타인 페이지에서 팔로우/알림/더보기/대화/DM 동작이 PRD와 일치한다.
      • 본인 페이지에서 팔로우/알림/더보기/대화가 제거되고 DM 확인하기와 FAB가 표시된다.
      • DM 확인하기 터치 시 메인 대화 탭과 DM 필터가 선택된다.
      • FAB 기본/확장/dim/닫기/3개 액션이 Figma 665:19221, 665:19352와 일치한다.
      • 후원 empty, 최신 콘텐츠 터치, 상대 날짜, 오디오 높이, 시리즈 original tag, 활동 날짜/D+n이 PRD와 일치한다.
      • sticky title-bar nickname과 tab typography가 Figma/PRD와 일치한다.
    • 기대 결과:
      • 2026-06-16 이후 추가 PRD Metrics를 모두 만족한다.
  • Task 14.4: 검증 기록 누적

    • 수정:
      • docs/20260611_크리에이터_채널_홈_탭/plan-task.md
      • docs/20260611_크리에이터_채널_홈_탭/prd.md
    • 작업:
      • 실행한 테스트/빌드/린트/수동 검증 결과를 문서 하단에 누적한다.
      • 실패 기록은 삭제하지 않고 후속 성공/차단 기록을 추가한다.
    • 기대 결과:
      • 후속 보강 구현과 검증 이력이 문서에 남는다.

Phase 15: 미사용 활동 요약 문자열 리소스 제거

  • Task 15.1: creator_channel_activity_summary 제거
    • 수정:
      • app/src/main/res/values/strings.xml
      • app/src/main/res/values-en/strings.xml
      • app/src/main/res/values-ja/strings.xml
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.kt
    • 작업:
      • 현재 활동 섹션은 label/value row와 개별 단위 format resource를 사용하므로, 사용하지 않는 creator_channel_activity_summary string resource를 모든 locale에서 제거한다.
      • source test에 해당 resource name이 locale string 파일에 남지 않는 계약을 추가한다.
    • 검증:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"
      • ./gradlew :app:mergeDebugResources
      • git diff --check
    • 기대 결과:
      • source test와 리소스 병합이 통과하고 rg -n "creator_channel_activity_summary" app/src/main app/src/test 결과가 검증 의도 외 참조 없음으로 정리된다.
    • 검증 기록:
      • 2026-06-16: RED로 CreatorChannelActivitySourceTestcreator_channel_activity_summary가 locale string 파일에 남지 않는 assertion을 추가하고 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"를 실행해 활동 summary string resource는 label value row 구조에서 사용하지 않는다 실패를 확인했다.
      • 2026-06-16: values, values-en, values-jacreator_channel_activity_summary 정의를 제거했다. 이후 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest", ./gradlew :app:mergeDebugResources, git diff --check가 모두 PASS했다. rg -n "creator_channel_activity_summary" app/src/main app/src/test 결과는 source test의 검증 문자열 2건만 남았다.

Phase 16: 작성/생성 결과 처리와 현재 라이브 시간 표시 버그 수정

  • Task 16.1: 라이브 생성 완료 후 라이브 페이지 이동

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.kt
    • 작업:
      • LiveRoomCreateActivity를 단순 startActivity가 아니라 ActivityResultContracts.StartActivityForResult() launcher로 실행한다.
      • RESULT_OK에서 Constants.EXTRA_ROOM_ID를 읽고, 유효한 roomId이면 LiveRoomActivityConstants.EXTRA_ROOM_ID를 전달해 진입한다.
    • 검증 기록:
      • 2026-06-16: RED로 owner FAB 라이브 생성 결과 처리 source 계약을 추가했고, formatCreatorChannelLiveDateTime 미구현 컴파일 실패와 함께 production 변경 전 실패를 확인했다. 구현은 기존 LiveRoomCreateActivitysetResult(RESULT_OK, EXTRA_ROOM_ID) 계약을 재사용했다.
      • 2026-06-16: 구현 후 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest.owner FAB 라이브 생성 결과는 roomId로 라이브 상세를 연다"를 포함한 신규 focused 테스트 묶음이 PASS했다. ./gradlew :app:compileDebugKotlin, ./gradlew :app:mergeDebugResources, ./gradlew :app:assembleDebug, git diff --check도 PASS했다.
  • Task 16.2: 커뮤니티 게시글 업로드 후 홈 새로고침

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeFragment.kt
      • app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/creator_community/write/CreatorCommunityWriteActivity.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.kt
    • 작업:
      • 커뮤니티 작성 화면 업로드 성공 시 setResult(RESULT_OK) 후 종료한다.
      • 채널 Activity는 커뮤니티 작성 결과가 RESULT_OK이면 HomeFragment delegate의 refreshHome()을 호출한다.
      • HomeFragment는 creatorId > 0L일 때 viewModel.loadHome(creatorId)를 재호출한다.
    • 검증 기록:
      • 2026-06-16: RED로 커뮤니티 작성 완료 결과와 홈 새로고침 source 계약을 추가했다. 구현은 기존 HomeFragment의 최초 로딩 경로인 viewModel.loadHome(creatorId)를 그대로 재사용했다.
      • 2026-06-16: 구현 후 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest.커뮤니티 작성 완료 결과는 홈 Fragment를 새로고침한다"를 포함한 신규 focused 테스트 묶음이 PASS했다. ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*"는 기존 후원 섹션 source 계약 1건(CreatorChannelActivitySourceTest.kt:638, item_creator_channel_home_donation.xml196dp 기대)으로 실패했으며 이번 변경과 무관하다.
  • Task 16.3: 현재 라이브 UTC 시간 로컬 절대 시간 표시

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.kt
    • 작업:
      • 현재 진행 중인 라이브의 beginDateTimeUtc 원문 표시를 중단한다.
      • UTC 문자열을 디바이스 타임존 기준 yyyy.MM.dd HH:mm:ss 형식으로 변환해 표시한다.
    • 검증 기록:
      • 2026-06-16: RED로 Asia/Seoul 기준 2026-06-29T15:00:01Z2026.06.30 00:00:01로 변환되는 테스트를 추가했다. 기존 schedule formatter와 같은 UTC parser를 재사용해 구현했다.
      • 2026-06-16: 구현 후 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest.현재 진행 중인 라이브 시간은 디바이스 timezone 기준 초 단위 날짜 시간으로 표시한다"를 포함한 신규 focused 테스트 묶음이 PASS했다. ./gradlew :app:ktlintCheck는 기존 creator_community 패키지명 underscore 위반 1건만 남아 실패했고, 이번 변경으로 발생한 포맷/문법 오류는 수정 후 ./gradlew :app:compileDebugKotlin PASS로 확인했다.
  • Task 16.4: 라이브 생성 결과와 현재 라이브 카드의 정상 입장 플로우 보강

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeFragment.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.kt
    • 작업:
      • 라이브 생성 완료 결과는 LiveRoomActivity 직접 이동 대신 LiveFragment.enterLiveRoom()과 같은 getRoomDetail()/enterRoom() 입장 플로우를 탄다.
      • 본인 방은 즉시 enterRoom() 후 입장한다.
      • 다른 크리에이터의 무료/이미 결제된 공개 방은 enterRoom() 후 입장한다.
      • 다른 크리에이터의 비공개 방은 비밀번호 다이얼로그를 거쳐 enterRoom() 후 입장한다.
      • 다른 크리에이터의 유료 공개 방은 결제 확인 다이얼로그를 거쳐 enterRoom() 후 입장한다.
      • 크리에이터 채널 홈 최상단 현재 라이브 카드는 같은 enterLiveRoom(live.liveId) 경로로 입장한다.
    • 검증 기록:
      • 2026-06-16: RED로 owner FAB 라이브 생성 결과는 기존 enterLiveRoom 플로우로 입장한다, 현재 라이브 카드는 동일한 enterLiveRoom 플로우로 입장한다 source 계약을 추가했고 기존 구현에서 2개 테스트 실패를 확인했다.
      • 2026-06-16: 구현 후 두 focused 테스트를 재실행해 PASS했다.
  • Task 16.5: 라이브 생성 후 홈 새로고침과 입장 진행/오류 피드백 표시

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.kt
    • 작업:
      • 라이브 생성 완료 결과가 RESULT_OK이면 커뮤니티 게시글 업로드와 동일하게 홈 탭을 새로고침한다.
      • 현재 라이브 카드 터치 후 getRoomDetail()/enterRoom() API 호출 중에는 LoadingDialog를 표시한다.
      • 현재 라이브 입장 API 실패/오류 시 LiveViewModel.toastLiveData를 관찰해 사용자에게 toast를 표시한다.
    • 검증 기록:
      • 2026-06-16: RED로 현재 라이브 입장 API 진행과 오류는 LoadingDialog와 toast로 표시한다 source 계약을 추가했고 기존 구현에서 실패를 확인했다.
      • 2026-06-16: 구현 후 owner FAB 라이브 생성 결과는 기존 enterLiveRoom 플로우로 입장한다, 현재 라이브 입장 API 진행과 오류는 LoadingDialog와 toast로 표시한다, 현재 라이브 카드는 동일한 enterLiveRoom 플로우로 입장한다 focused 테스트를 재실행해 PASS했다. ./gradlew :app:compileDebugKotlin, ./gradlew :app:mergeDebugResources, git diff --check도 PASS했다. 병렬 Gradle 실행 중 compileDebugKotlin 산출물 NoSuchFileException이 한 번 발생했으나 순차 재실행에서 성공했다.
      • 2026-06-16: LiveFragment의 생성 결과 처리와 동일하게 Constants.EXTRA_ROOM_CHANNEL_NAME이 null이 아닐 때만 enterLiveRoom()을 호출하도록 보정했다. source test에 EXTRA_ROOM_CHANNEL_NAME 확인과 channelName != null 계약을 추가했고, focused source test, ./gradlew :app:compileDebugKotlin, git diff --check 순차 재검증이 PASS했다.

Phase 17: 크리에이터 채널 Live 생성 안내와 예약 상세 액션 분리

  • Task 17.1: 크리에이터 채널 Live 로직 coordinator 분리

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt
    • 생성:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelLiveCoordinator.kt
    • 작업:
      • CreatorChannelActivity의 Live 입장, 상세, 결제/비밀번호, 예약/수정/시작/취소 관련 로직을 CreatorChannelLiveCoordinator로 이동한다.
      • Activity는 Live 생성 결과, 현재 라이브 클릭, 일정 라이브 클릭에서 coordinator 호출만 담당한다.
    • 검증 기록:
      • 2026-06-17: CreatorChannelLiveCoordinator를 추가하고 CreatorChannelActivity의 Live 입장, Live 상세, 결제/비밀번호 다이얼로그, LiveRoom 이동 로직을 coordinator로 이동했다. Activity는 liveCoordinator.enterLiveRoom()liveCoordinator.showLiveRoomDetail() 호출만 담당하도록 축소했다.
  • Task 17.2: 예약 라이브 생성 완료 안내 표시

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.kt
    • 작업:
      • 크리에이터 채널에서 예약 라이브 생성 완료 시 라이브가 생성되었습니다. 안내 메시지를 표시한다.
      • LiveRoomCreateActivity의 결과에서 Constants.EXTRA_ROOM_CHANNEL_NAME이 없는 생성 성공을 예약 라이브 생성으로 판단한다.
    • 검증 기록:
      • 2026-06-17: LiveRoomCreateActivity 결과에서 Constants.EXTRA_ROOM_CHANNEL_NAME이 없는 RESULT_OK를 예약 라이브 생성 완료로 판단해 라이브가 생성되었습니다. toast를 표시하도록 구현했다. 즉시 라이브 생성은 기존처럼 channelName != null일 때만 liveCoordinator.enterLiveRoom()으로 입장한다.
      • 2026-06-17: 리뷰에서 사용자 노출 문구 하드코딩 지적이 있어 creator_channel_live_created_message string resource로 분리하고 values, values-en, values-ja에 추가했다.
  • Task 17.3: 일정 섹션 예약 라이브 상세 액션 연결

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelLiveCoordinator.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.kt
    • 작업:
      • 일정 섹션에서 예약 라이브 상세를 열 때 LiveFragment와 동일하게 예약, 수정, 시작, 취소 액션을 연결한다.
      • 예약은 유료/비공개 분기를 거쳐 예약 완료 화면으로 이동한다.
      • 수정은 LiveRoomEditActivity, 시작은 startLive() 후 LiveRoom 입장, 취소는 취소 다이얼로그 후 홈 새로고침으로 연결한다.
    • 검증 기록:
      • 2026-06-17: LiveRoomDetailFragment 콜백에 reservationRoom, modifyLive, startLive, cancelLive를 연결했다. 예약은 유료/비공개 분기 후 LiveReservationCompleteActivity로 이동하고, 수정은 LiveRoomEditActivity, 시작은 startLive() 후 LiveRoom 입장, 취소는 LiveCancelDialog 후 홈 새로고침으로 연결했다.
      • 2026-06-17: source 계약 테스트 3건(owner FAB 라이브 생성 결과는 기존 enterLiveRoom 플로우로 입장한다, 크리에이터 채널 라이브 로직은 coordinator로 분리한다, 일정 라이브 상세는 예약 수정 시작 취소 액션을 연결한다)이 PASS했다. 첫 focused 테스트 실행 중 Kotlin incremental 상태에서 extension import 미해결 컴파일 오류가 한 번 발생했으나, 순차 ./gradlew :app:compileDebugKotlin 재실행과 focused test 재실행이 모두 PASS했다. ./gradlew :app:ktlintCheck, git diff --check도 PASS했다.
      • 2026-06-17: 컨텍스트 마이닝 리뷰에서 현재 라이브 카드 입장 전 로그인/성인 인증 게이트가 누락되었다는 FAIL을 받아, LiveFragment/LiveNowAllActivity와 동일하게 ensureLoginAndAdultAuth(live.isAdult)를 거친 뒤 liveCoordinator.enterLiveRoom()을 호출하도록 보정했다.

Verification Log

  • 2026-06-12: docs/20260611_크리에이터_채널_홈_탭/prd.md, docs/agent-guides/work-plan-docs.md, docs/agent-guides/build-test-style.md, docs/agent-guides/code-style.md를 확인해 계획 문서 작성 규칙과 검증 명령 규칙을 확인했다.

  • 2026-06-12: 기존 HomeRecommendationApi, HomeRecommendationModels, HomeRecommendationRepository, HomeRecommendationViewModel, RecommendedActivityType, HomeRecommendationMappers, HomeRecommendationUiModels, AppDI, ChatRoomActivity, DmChatRoomActivity를 확인해 신규 크리에이터 채널 홈 구현 계획의 파일 경계와 재사용 지점을 정리했다.

  • 2026-06-12: 이번 단계는 구현 계획/TASK 문서 작성만 수행했으며 구현/빌드/테스트는 실행하지 않았다.

  • 2026-06-12: Figma Design 참조가 필요한 Phase를 점검해 Phase 5, Phase 6, Phase 8은 필수 참조, Phase 1, Phase 4, Phase 7은 부분 참조, Phase 2, Phase 3은 참조 불필요로 계획 문서에 명시했다.

  • 2026-06-12: Phase 1 진행으로 HomeRecommendationApi, HomeRecommendationRepository, HomeRecommendationViewModel을 확인해 기존 v2 홈 네트워크가 Retrofit + RxJava3 Single<ApiResponse<T>>Bearer ${SharedPreferenceManager.token} 패턴을 사용함을 재확인했다.

  • 2026-06-12: UserRepository.creatorFollow(creatorId, follow, notify, token)CreatorFollowNotifyFragment의 알림 전체/없음/언팔로우 callback 구조를 확인해 크리에이터 채널 홈의 팔로우/알림 변경에 기존 API와 bottom sheet를 재사용할 수 있음을 확인했다.

  • 2026-06-12: ChatRoomActivitynewIntent(context, roomId) 계약으로 roomId가 필요하고, DmChatRoomActivity.newIntentByCreatorId(context, creatorId)가 존재함을 확인해 계획서의 AI 채팅/DM 이동 경계를 재확인했다.

  • 2026-06-12: TalkApi.createChatRoom, CreateChatRoomRequest(characterId), CreateChatRoomResponse.chatRoomId, CharacterDetailViewModel.createChatRoom(characterId)를 확인해 대화하기characterId 기반 채팅방 생성 후 chatRoomIdChatRoomActivity에 진입해야 함을 확인했다.

  • 2026-06-12: AppDInetworkModule, repositoryModule, viewModelModule 등록 패턴을 확인해 Phase 3 이후 신규 API/Repository/ViewModel 등록 위치와 형태를 확인했다.

  • 2026-06-12: prd.md의 Non-Goals와 Technical Constraints를 확인해 라이브, 오디오, 시리즈, 커뮤니티, 팬Talk, 후원 탭 상세, 홈 pagination, 신규 팔로우/알림 API, 채팅 내부 동작 변경, 별도 analytics/logging을 Phase 1 기준 제외 범위로 유지했다. Phase 1은 문서 확인/체크 갱신만 수행했으며 구현/빌드/테스트는 실행하지 않았다.

  • 2026-06-12: 사용자 추가 요구사항에 따라 CreatorChannelCreatorResponse.characterId: Long?를 PRD/계획에 반영하고, CharacterDetailViewModel.createChatRoom과 동일하게 TalkApi.createChatRoom(CreateChatRoomRequest(characterId)) 호출 후 반환된 chatRoomIdChatRoomActivity에 이동하도록 Phase 3/4/5 작업을 갱신했다. 이번 단계는 문서 수정만 수행했으며 구현/빌드/테스트는 실행하지 않았다.

  • 2026-06-13: Phase 2 RED 테스트로 CreatorActivityTypeTest를 먼저 추가하고 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.common.CreatorActivityTypeTest"를 실행해 CreatorActivityType 미구현으로 실패함을 확인했다.

  • 2026-06-13: RecommendedActivityTypev2/common/CreatorActivityType으로 공용화하고 홈 추천 mapper/model/test 참조를 갱신했다. RecommendedActivityType.kt는 제거했으며 rg -n "RecommendedActivityType|toRecommendedActivityTypeLabelRes" app/src/main app/src/test 결과 남은 참조가 없음을 확인했다.

  • 2026-06-13: Phase 3 RED 테스트로 CreatorChannelHomeModelsTest를 추가해 Gson이 CreatorChannelScheduleResponse.typeCreatorActivityType으로 파싱하고 nullable 필드를 보존하는지 검증하도록 했다. 초기 실행은 CreatorChannelHomeResponseCreatorActivityType 미구현으로 실패했다.

  • 2026-06-13: CreatorChannelHomeApi, CreatorChannelHomeModels, CreatorChannelHomeRepository를 추가하고 AppDICreatorChannelHomeApiCreatorChannelHomeRepository를 등록했다. CreatorChannelHomeViewModel 등록은 Phase 4 클래스가 아직 없으므로 컴파일 유지를 위해 보류했다.

  • 2026-06-13: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.common.*", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creatorchannel.*", ./gradlew :app:compileDebugKotlin, ./gradlew :app:mergeDebugResources, ./gradlew :app:ktlintCheck를 실행해 모두 BUILD SUCCESSFUL을 확인했다.

  • 2026-06-13: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*"는 88개 중 8개가 HomeMainFragmentLayoutTest.kt:1410FileNotFoundException으로 실패했다. 별도 focused 실행인 HomeCreatorActivityTypeLabelResTest와 recent activity route 관련 2개 테스트는 BUILD SUCCESSFUL로 통과해 이번 타입 공용화 변경과 직접 관련된 회귀는 없음을 확인했다.

  • 2026-06-13: reviewer gate를 실행해 Phase 2/3 구현 범위, PRD DTO 일치, stale 참조 제거, DI 등록 범위, 검증 증거에 대해 무조건 승인을 받았다.

  • 2026-06-13: HomeMainFragmentLayoutTest.kt의 source-path helper가 실제 파일 위치와 다른 v2/main/HomeMainFragment.kt를 읽고 있어 FileNotFoundException이 발생함을 확인하고, 실제 위치인 v2/main/home/HomeMainFragment.kt로 수정했다.

  • 2026-06-13: 백엔드 CreatorActivityType 원본 enum이 LIVE, AUDIO, COMMUNITY, LIVE_REPLAY 대문자 상수와 동일한 code를 사용함을 확인해 Android Gson enum 파싱용 별도 TypeAdapter는 추가하지 않기로 판단했다.

  • 2026-06-13: 사용자 추가 요청에 따라 신규 크리에이터 채널 홈 패키지를 kr.co.vividnext.sodalive.v2.creatorchannel에서 kr.co.vividnext.sodalive.v2.creator.channel로 변경하고, 계획 본문의 신규 파일 경로와 테스트 필터를 새 패키지명 기준으로 갱신했다.

  • 2026-06-13: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.common.*" --tests "kr.co.vividnext.sodalive.v2.creator.channel.*" --tests "kr.co.vividnext.sodalive.v2.main.home.*" :app:compileDebugKotlin를 실행해 BUILD SUCCESSFUL을 확인했다.

  • 2026-06-13: 패키지 이동 후 ./gradlew :app:ktlintCheck를 실행해 BUILD SUCCESSFUL을 확인했다.

  • 2026-06-13: 사용자 확인에 따라 백엔드 CreatorActivityType 원본 enum이 LIVE, AUDIO, COMMUNITY, LIVE_REPLAY 대문자 code를 내려주는 계약임을 Phase 2/3 작업 항목에 명시했다. 이후 코드리뷰에서는 별도 서버 계약 변경 근거가 없는 한 크리에이터 채널 홈 DTO의 CreatorActivityType 직접 사용과 Gson enum TypeAdapter 부재를 대소문자 대응 문제로 제기하지 않는다. 이번 단계는 문서 수정만 수행했으며 빌드/테스트는 실행하지 않았다.

  • 2026-06-13: Phase 4 TDD RED로 CreatorChannelHomeMapperTest, CreatorChannelTitleBarStateTest, CreatorChannelHomeViewModelTest를 먼저 추가했다. 각 focused 명령은 CreatorChannelHomeUiModels, CreatorChannelHomeMappers, CreatorChannelTitleBarState, CreatorChannelHomeViewModel 미구현 참조로 compileDebugUnitTestKotlin 실패함을 확인했다.

  • 2026-06-13: Phase 4 GREEN으로 UI state/tab/header/section/SNS 모델, CreatorChannelHomeResponse.toUiContent(), title-bar 상태 모델, CreatorChannelHomeViewModel, AppDI ViewModel 등록을 최소 구현했다. ic_bar_bell_colored는 기존 drawable-mdpi/ic_bar_bell_colored.png가 있어 신규 리소스를 추가하지 않았다.

  • 2026-06-13: Phase 4 검증으로 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeMapperTest", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelTitleBarStateTest", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeViewModelTest", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*", ./gradlew :app:compileDebugKotlin 모두 BUILD SUCCESSFUL을 확인했다. 병렬 Gradle 실행 중 KSP 캐시 StreamCorruptedException이 한 차례 발생해 ./gradlew --stop 후 순차 재실행했다.

  • 2026-06-13: Phase 4 자체 검증 중 CreatorChannelHomeViewModelTestnull data 케이스 assertion이 실제로는 API failure만 검증하고 있음을 확인해 별도 홈 API null data는 Error와 unknown toast를 emit한다 테스트를 추가했다. 이후 ./gradlew :app:ktlintCheck는 unused import와 긴 whenever(...) 라인으로 실패했으며, 테스트 파일 import/line wrapping을 수정했다.

  • 2026-06-13: Phase 4 보강 후 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeViewModelTest", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*", ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck를 재실행해 모두 BUILD SUCCESSFUL을 확인했다. ktlintCheck.editorconfig disabled_rules deprecation 경고는 기존 설정 경고로 이번 변경과 무관하다.

  • 2026-06-13: Phase 4 review-work gate에서 code quality 리뷰어가 chatRoomIdLiveData를 일반 MutableLiveData<Long>로 두면 화면 재생성/재구독 시 채팅방 이동이 반복될 수 있다고 지적해 FAIL했다. 기존 DmChatEvent<T>.consume() 패턴을 참고해 CreatorChannelEvent<T> 소비형 이벤트로 변경하고, chatRoomIdLiveData 테스트에서 첫 번째 consume()chatRoomId, 두 번째 consume()null임을 검증하도록 보강했다.

  • 2026-06-13: 소비형 이벤트 수정 후 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeViewModelTest", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*", ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck를 재실행해 모두 BUILD SUCCESSFUL을 확인했다.

  • 2026-06-13: 추가 코드리뷰에서 팔로우/채팅방 생성 액션 실패도 showUnknownError()를 통해 홈 상태를 Error로 덮어 기존 Content가 사라질 수 있다는 P1 지적을 받았다. 팔로우 실패는 현재 content를 유지하고 unknown toast만 emit한다, 채팅방 생성 실패는 현재 content를 유지하고 unknown toast만 emit한다 테스트를 먼저 추가했고, 기존 구현에서 ClassCastException으로 실패하는 RED를 확인했다.

  • 2026-06-13: 홈 로드 실패는 기존처럼 CreatorChannelHomeUiState.Error를 유지하되, 팔로우/채팅방 생성 액션 실패는 showUnknownErrorToast()만 호출하도록 분리했다. 수정 후 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeViewModelTest"를 실행해 BUILD SUCCESSFUL을 확인했다.

  • 2026-06-13: Phase 5 사용자 추가 요구사항에 맞춰 CreatorChannelTab을 문자열 label 대신 labelResId: Int로 변경하고 values, values-en, values-ja에 7개 탭 및 Phase 5 버튼/섹션 문자열을 추가했다. Production 변경 전 RED로 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeMapperTest"를 실행해 creator_channel_tab_*/labelResId 미구현 컴파일 실패를 확인했다.

  • 2026-06-13: Phase 5 구현으로 activity_creator_channel_home.xml, CreatorChannelHomeActivity, CreatorChannelHomeSectionAdapter, 12개 item_creator_channel_home_* layout, header gradient/button drawable, Manifest 등록, CreatorChannelHomeActivitySourceTest를 추가했다. TextTabBarView는 사용하지 않고 HorizontalScrollView + 동적 TextView로 7개 긴 탭을 가로 스크롤 가능하게 구성했다. Phase 6 sticky scroll/title black 전환과 Phase 7 CreatorFollowNotifyFragment bottom sheet는 구현하지 않았다.

  • 2026-06-13: Phase 5 검증 중 병렬 Gradle 실행에서 KSP incremental cache 충돌(kspCaches/debug/...)이 발생했으나 순차 실행으로 전환해 ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeMapperTest", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest" 모두 BUILD SUCCESSFUL을 확인했다. 이후 ./gradlew :app:ktlintCheckCreatorChannelHomeSectionAdapter.kt의 130자 초과 한 줄로 실패했고, 줄바꿈 수정 후 ./gradlew :app:ktlintCheck, ./gradlew :app:compileDebugKotlin, ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeMapperTest" --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest"가 모두 BUILD SUCCESSFUL로 통과했다. .editorconfig disabled_rules deprecation 경고는 기존 설정 경고로 이번 변경과 무관하다.

  • 2026-06-13: Phase 5 수동 표면 검증으로 ./gradlew :app:assembleDebug 후 연결 기기(adb devices)에 debug APK를 설치했다. adb shell run-as kr.co.vividnext.sodalive.debug am start --user 0 -n kr.co.vividnext.sodalive.debug/kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivity --el extra_creator_id 0--el extra_creator_id 100 실행을 시도했고 AndroidRuntime:E crash 로그는 없었다. 다만 Activity가 exported=false이고 shell/background start 제한이 있어 실제 전면 화면 상호작용은 제한적으로만 확인했다.

  • 2026-06-13: Phase 5 자체 검토 중 대화하기가 숨겨지고 DM 보내기만 표시될 때 XML의 layout_marginStart가 남아 단독 버튼 중앙 정렬이 틀어질 수 있음을 확인했다. CreatorChannelHomeActivitySourceTestupdateActionButtonLayoutmarginStart = if (isChatVisible && isDmVisible) 계약을 먼저 추가했고, ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest"가 해당 assertion에서 실패하는 RED를 확인했다. 이후 Activity에서 버튼 표시 조합별 margin을 조정하도록 수정하고 같은 명령을 재실행해 BUILD SUCCESSFUL을 확인했다.

  • 2026-06-13: Phase 5 보강 후 ./gradlew :app:mergeDebugResources, ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*", ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck를 실행해 모두 BUILD SUCCESSFUL을 확인했다. ktlintCheck.editorconfig disabled_rules deprecation 경고는 기존 설정 경고로 이번 변경과 무관하다.

  • 2026-06-13: Phase 5 review-work gate에서 code quality 리뷰어가 CreatorChannelHomeSectionAdapter의 활동 요약 문자열(Live, Audio, Series) 하드코딩으로 다국어 일관성이 깨진다고 FAIL했고, context mining 리뷰어가 PRD/Figma에 명시된 대화하기/DM 보내기 버튼 아이콘(ic_new_talk, ic_new_dm) 누락으로 FAIL했다.

  • 2026-06-13: 차단 이슈 수정 전 RED로 CreatorChannelHomeActivitySourceTestandroid:drawableStart="@drawable/ic_new_talk", android:drawableStart="@drawable/ic_new_dm", creator_channel_activity_summary resource format 사용, "Live , "Audio , "Series 하드코딩 부재 assertion을 추가했고, ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest"가 2개 assertion 실패로 BUILD FAILED임을 확인했다.

  • 2026-06-13: ic_new_talk, ic_new_dm vector drawable을 추가하고 버튼 XML에 drawableStart를 연결했다. 활동 요약은 creator_channel_activity_summaryvalues, values-en, values-ja에 추가하고 CreatorChannelHomeSectionAdapter에서 context.getString(...)으로 표시하도록 수정했다. 이후 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest", ./gradlew :app:mergeDebugResources, ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*", ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck, ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*", git diff --check를 실행해 모두 성공 또는 출력 없음(git diff --check)을 확인했다.

  • 2026-06-13: Phase 5 코드 리뷰에서 확인된 화보 탭은 사용자 결정에 따라 이번 범위 제외로 확정했으므로 결함으로 보지 않았다. 나머지 3개 Finding에 대해 RED로 CreatorChannelHomeActivitySourceTest에 홈 API Error 상태의 Activity toast 중복 호출 금지, status bar 뒤 header 렌더링을 위한 BaseActivity.shouldApplySystemBarTopInset hook 및 화면 자체 title inset 처리, Figma 기준 tab selected indicator/16sp/110dp 폭 계약 assertion을 추가했다. 기존 구현에서 해당 테스트가 3개 assertion 실패로 BUILD FAILED임을 확인했다.

  • 2026-06-13: BaseActivityshouldApplySystemBarTopInset hook을 추가하고 CreatorChannelHomeActivity에서 false로 override해 header는 status bar 뒤까지 그리고 title-bar만 system bar top inset을 반영하도록 수정했다. 홈 로드 Error 상태는 ViewModel의 unknown toast만 사용하도록 Activity의 showToast(state.message.orEmpty()) 호출을 제거했다. tab은 110dp 폭 LinearLayout 안에 16sp TextViewsoda_400 3dp selected indicator를 구성하도록 변경했다.

  • 2026-06-13: Phase 5 코드 리뷰 수정 검증으로 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*", ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck, git diff --check를 실행했다. 모두 BUILD SUCCESSFUL 또는 출력 없음(git diff --check)을 확인했다. ktlintCheck.editorconfig disabled_rules deprecation 경고는 기존 설정 경고로 이번 변경과 무관하다.

  • 2026-06-13: Phase 5 추가 코드 리뷰 지적 3건(title-bar follow 상태 capsule 불일치, 홈 section item UI 공통 카드 축약, 활동 DTO 주요 필드 미노출)에 대해 Figma 296:14287, 296:14288, 296:14289, 296:14890을 재확인했다. RED로 CreatorChannelHomeActivitySourceTest에 title-bar capsule 구조와 section별 데이터 보존 assertion을 추가했고, 기존 구현에서 title bar source는 Figma 상태별 capsule 구조를 사용한다, section adapter source는 Figma 섹션별 데이터를 공통 카드 하나로 축약하지 않는다 2개 테스트가 실패해 BUILD FAILED임을 확인했다.

  • 2026-06-13: title-bar는 layout_follow_capsule 안에 follow icon/text를 넣고, 팔로우 상태에서는 흰색 원형 capsule 배경과 icon-only 형태로 전환하도록 bg_creator_channel_follow_capsule, bg_creator_channel_following_capsule, CreatorChannelHomeActivity.bindTitleBar()를 수정했다. 홈 section adapter는 section별 bind* 함수로 분리하고 오디오/시리즈/커뮤니티/팬Talk/SNS list 데이터를 줄 단위로 보존했으며, 활동 section은 debutDateUtc, liveCount, liveDurationHours, liveContributorCount, audioContentCount, seriesCount를 모두 다국어 resource format으로 표시하도록 수정했다.

  • 2026-06-13: Phase 5 추가 코드 리뷰 수정 검증으로 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest"를 재실행해 BUILD SUCCESSFUL을 확인했다. 첫 GREEN 시도는 120초 timeout으로 중단됐으나 컴파일 오류 없이 진행 중이었고, timeout을 300초로 늘린 재실행이 성공했다. 이어서 ./gradlew :app:mergeDebugResources, git diff --check, ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*", ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck를 실행해 모두 BUILD SUCCESSFUL 또는 출력 없음(git diff --check)을 확인했다. ktlintCheck.editorconfig disabled_rules deprecation 경고는 기존 설정 경고로 이번 변경과 무관하다.

  • 2026-06-13: 추가 reviewer gate에서 security/QA/code quality는 PASS했으나 goal/context 리뷰가 홈 section layout이 여전히 72dp thumbnail + tv_primary/tv_secondary 공통 카드에 가깝고, list 데이터를 한 TextView에 줄바꿈으로 합쳐 Figma 296:14890의 반복 카드/활동 행/SNS 아이콘 구조를 충분히 만족하지 못한다고 FAIL했다.

  • 2026-06-13: reviewer FAIL 수정으로 12개 item_creator_channel_home_* layout에 ll_section_items 동적 컨테이너를 추가하고, CreatorChannelHomeSectionAdapter가 기존 단일 공통 카드 영역을 숨긴 뒤 section별로 여러 child card/row를 생성하도록 변경했다. 오디오/시리즈/커뮤니티/후원/공지/일정/팬Talk는 항목마다 개별 card를 추가하고, SNS는 52dp 버튼 row를 추가하며, 활동은 dDay/데뷔일 및 라이브 총 진행 수/누적 시간/누적 참여자/오디오 수/시리즈 수를 행 단위로 표시한다.

  • 2026-06-13: 동적 section row 보강 검증으로 CreatorChannelHomeActivitySourceTestll_section_items, sectionItems.addView, addActivityRow, createSnsButton, 줄바꿈 joinToString(separator = "\\n") 금지 assertion을 추가했다. 첫 실행은 기존 활동 요약 source assertion이 새 행 단위 구조와 충돌해 BUILD FAILED였고, 테스트를 활동 지표 label resource 계약으로 갱신한 뒤 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*", ./gradlew :app:mergeDebugResources, git diff --check, ./gradlew :app:compileDebugKotlin, ./gradlew :app:assembleDebug, ./gradlew :app:ktlintCheck가 모두 BUILD SUCCESSFUL 또는 출력 없음(git diff --check)임을 확인했다. ktlintCheck는 줄바꿈/indentation 2차례 실패 후 해당 라인만 수정해 최종 통과했다.

  • 2026-06-13: 후속 reviewer gate에서 context/code quality는 PASS했으나 goal 리뷰가 addCard()가 대부분 섹션을 동일한 72dp 썸네일 가로 카드로 렌더링해 Figma 296:14890의 섹션별 카드/피드/콘텐츠 그리드 구조와 아직 다르다고 FAIL했다.

  • 2026-06-13: 두 번째 reviewer FAIL 수정으로 CreatorChannelHomeSectionAdapter의 공통 addCard()를 제거하고 섹션별 helper로 분리했다. 현재 라이브는 addHeroCard, 오디오/시리즈는 createContentTile 기반 가로 콘텐츠 타일, 커뮤니티는 addFeedCard, 일정은 addScheduleRow, 후원은 addDonationCard, 팬Talk는 addCommentCard, SNS는 createSnsButton, 활동은 addActivityRow를 사용해 섹션별 구조가 같은 72dp 카드 하나로 수렴하지 않도록 했다. CreatorChannelHomeActivitySourceTestaddHeroCard, createContentTile, addFeedCard, addScheduleRow, addDonationCard, addCommentCard 존재와 private fun addCard 부재를 검증하도록 보강했다.

  • 2026-06-13: 섹션별 helper 분리 후 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*", ./gradlew :app:mergeDebugResources, git diff --check, ./gradlew :app:compileDebugKotlin, ./gradlew :app:assembleDebug, ./gradlew :app:ktlintCheck를 재실행했다. 모두 BUILD SUCCESSFUL 또는 출력 없음(git diff --check)을 확인했으며, ktlintCheck는 series tile 인자 indentation 실패를 수정한 뒤 최종 통과했다.

  • 2026-06-13: 섹션별 helper 분리 후 code quality reviewer가 legacy 공통 카드 잔재(tv_primary, tv_secondary, iv_thumbnail, legacyCard, getChildAt(2), CreatorChannelHomeSection.imageUrl())를 차단 이슈로 지적해 FAIL했다. 12개 item_creator_channel_home_* layout에서 legacy 공통 카드 영역을 제거하고 ll_section_items만 남겼으며, adapter에서 legacy field/helper와 unused imageUrl() extension을 제거했다. Source test에는 getChildAt, keepLegacyViewsReferenced, fun CreatorChannelHomeSection.imageUrl 부재와 각 item layout의 legacy id 부재 assertion을 추가했다. 이후 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*", ./gradlew :app:mergeDebugResources, git diff --check, ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck, ./gradlew :app:assembleDebug를 실행해 모두 BUILD SUCCESSFUL 또는 출력 없음(git diff --check)을 확인했다.

  • 2026-06-13: Phase 5 코드 리뷰 Findings 4건(시리즈 가로 row clipping, SNS URL 미사용, schedule type 서버 code 노출, 어두운 header 위 status bar icon 가독성)에 대해 RED로 CreatorChannelHomeActivitySourceTest에 source 계약 assertion을 추가했다. 기존 구현에서 section adapter source는 가로 시리즈와 SNS 링크와 일정 타입 label을 보존한다, creator channel home은 어두운 header 위 status bar icon을 밝게 표시한다 2개 테스트가 실패해 BUILD FAILED임을 확인했다.

  • 2026-06-13: Phase 5 코드 리뷰 Findings 수정으로 CreatorChannelHomeActivity에서 WindowCompat.getInsetsController(window, binding.root).isAppearanceLightStatusBars = false를 설정하고, CreatorChannelHomeSectionAdapter에서 시리즈 row를 HorizontalScrollView로 감싸며 SNS 버튼이 Intent(Intent.ACTION_VIEW, Uri.parse(url))을 실행하도록 변경했다. 일정 row는 schedule.type.code 대신 schedule.type.labelResIdgetString()으로 표시하도록 수정했다.

  • 2026-06-13: Phase 5 코드 리뷰 Findings 수정 검증으로 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*", ./gradlew :app:mergeDebugResources, git diff --check, ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck를 실행해 모두 BUILD SUCCESSFUL 또는 출력 없음(git diff --check)을 확인했다. ktlintCheckCreatorChannelHomeSectionAdapter.kt indentation 1건으로 한 차례 실패했고 해당 라인만 수정한 뒤 재실행해 통과했다. .editorconfig disabled_rules deprecation 경고는 기존 설정 경고로 이번 변경과 무관하다.

  • 2026-06-13: Phase 5 추가 리뷰 반영으로 SNS 버튼 크기를 고정 52dp가 아니라 calculateCreatorChannelSnsButtonSizeDp(screenWidthDp)로 계산하도록 변경했다. 402dp 이상은 52dp, 402dp 미만은 52 * width / 402 비율로 축소한다. CreatorChannelHomeViewModel.toastLiveData는 화면 재생성 시 중복 toast가 표시되지 않도록 CreatorChannelEvent<ToastMessage>로 변경했고 Activity에서 event.consume() 후 표시하도록 수정했다. RED로 CreatorChannelHomeActivitySourceTestCreatorChannelHomeViewModelTest를 실행해 새 계산 함수 및 toast event 소비 계약 미구현 컴파일 실패를 확인했고, 구현 후 두 테스트 모두 BUILD SUCCESSFUL을 확인했다.

  • 2026-06-13: Phase 5 추가 리뷰 반영 최종 검증으로 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*", ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck, git diff --check를 실행해 모두 BUILD SUCCESSFUL 또는 출력 없음(git diff --check)을 확인했다. ktlintCheck.editorconfig disabled_rules deprecation 경고는 기존 설정 경고로 이번 변경과 무관하다.

  • 2026-06-13: Phase 5 코드 리뷰 Finding 1/2와 사용자 SNS 아이콘 정책 반영을 위해 RED로 CreatorChannelHomeActivitySourceTest에 활동 섹션 단위 format, 오디오 단일 가로 스크롤 row, ic_sns_ drawable 기반 ImageView SNS 버튼 계약을 추가했다. 기존 구현에서 4개 assertion이 실패해 BUILD FAILED임을 확인했다.

  • 2026-06-13: Phase 5 코드 리뷰 Finding 1/2와 SNS 아이콘 정책 수정으로 활동 섹션에 데뷔 label 및 단위 포함 value format resource를 추가하고, 오디오 콘텐츠 섹션을 단일 HorizontalScrollView row로 변경했다. SNS는 CreatorChannelSnsUiItem.iconResId를 추가해 ic_sns_instagram, ic_sns_youtube, ic_sns_x, ic_sns_kakao, ic_sns_fancimm 아이콘을 ImageView로 표시하도록 변경했다.

  • 2026-06-13: Phase 5 코드 리뷰 Finding 1/2와 SNS 아이콘 정책 수정 검증으로 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*", ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck, git diff --check를 실행했다. 모두 BUILD SUCCESSFUL 또는 출력 없음(git diff --check)을 확인했다. 첫 테스트 실행은 sandbox의 ~/.gradle lock 파일 접근 제한으로 실패해 승인 후 재실행했다. ktlintCheck.editorconfig disabled_rules deprecation 경고는 기존 설정 경고로 이번 변경과 무관하다.

  • 2026-06-14: Phase 5 SNS 후속 리뷰 반영을 위해 RED로 CreatorChannelHomeMapperTest에 Figma 순서(Instagram, YouTube, X, Kakao Open Chat, Fancimm)와 invalid URL 제외 assertion을 추가하고, CreatorChannelHomeActivitySourceTest에 SNS intent resolveActivity() 확인 및 마지막 아이콘 trailing marginEnd 제거 assertion을 추가했다. 기존 구현에서 CreatorChannelHomeActivitySourceTest는 URL 안전 실행/마지막 margin 2개 assertion 실패로 BUILD FAILED임을 확인했다. 매퍼 테스트는 Android 런타임 의존 없는 검증을 유지하기 위해 java.net.URI 기반 URL helper 계약으로 정리했다.

  • 2026-06-14: Phase 5 SNS 후속 리뷰 수정으로 CreatorChannelHomeMappers에서 SNS 순서를 Figma 기준으로 변경하고, isValidCreatorChannelSnsUrl()http/https scheme과 host가 있는 URL만 UI item으로 매핑하도록 했다. CreatorChannelHomeSectionAdapter는 SNS 클릭 시 Intent.ACTION_VIEW intent를 만든 뒤 resolveActivity(itemView.context.packageManager)가 null이 아닐 때만 실행하고, forEachIndexed로 마지막 SNS 아이콘의 marginEnd를 0으로 조정했다.

  • 2026-06-14: Phase 5 SNS 후속 리뷰 검증으로 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeMapperTest", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*", ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck, git diff --check를 실행했다. 모두 BUILD SUCCESSFUL 또는 출력 없음(git diff --check)을 확인했다. 첫 RED 테스트 시도는 sandbox의 ~/.gradle lock 파일 접근 제한으로 실패해 승인 후 재실행했다. ktlintCheck.editorconfig disabled_rules deprecation 경고는 기존 설정 경고로 이번 변경과 무관하다.

  • 2026-06-15: 사용자 요청에 따라 탭 바 아래 홈 컨텐츠를 전부 삭제 후 Figma 296:14895SectionTitle, Contents, Feed, ListComment, SNS 컴포넌트 기준으로 다시 구성하는 Phase 5R을 추가했다. 각 홈 섹션을 하나의 Task로 분리했고, 현재 API 응답에 없는 화보 섹션은 이번 재구성 구현 범위에서 제외한다고 명시했다. 이번 단계는 문서 수정만 수행했으며 구현/빌드/테스트는 실행하지 않았다.

  • 2026-06-15: Phase 5R.4 공지 섹션 재구성으로 Figma 296:14915 기준 SectionTitle, ic_pin Notice label, 프로필/작성자/날짜, 본문, 선택 썸네일을 가진 공지 전용 가로 feed card를 추가했다. 공지는 최대 3개까지 표시하고, item width는 402dp 기준 최대 346dp 및 작은 화면 비율 축소로 계산한다. RED로 공지 row/custom thumbnail 부재와 기존 374dp width 계산 실패를 확인한 뒤 구현했으며, CreatorChannelHomeActivitySourceTest 공지 단일 테스트 2개, kr.co.vividnext.sodalive.v2.creator.channel.*, :app:mergeDebugResources, :app:compileDebugKotlin, :app:ktlintCheck, git diff --check가 모두 PASS했다. ktlintCheck.editorconfig disabled_rules deprecation 경고는 기존 설정 경고로 이번 변경과 무관하다.

  • 2026-06-15: 코드 리뷰에서 커뮤니티 카드가 setFeedSize(374dp 기준) 호출 후 LinearLayout.LayoutParams.MATCH_PARENT로 덮여 실제 폭 계산이 적용되지 않는다는 지적을 확인했다. CreatorChannelHomeSectionAdapter.bindCommunities()에서 communityWidthDp를 한 번 계산해 FeedSize.rootWidthDp와 row layoutParams.width에 동일하게 적용하도록 수정하고, CreatorChannelHomeActivitySourceTestcommunityWidthDp.dp() 계약을 검증하도록 갱신했다.

  • 2026-06-15: Phase 6 진행으로 CreatorChannelScrollStateTest를 먼저 추가해 CreatorChannelScrollState 미구현 RED 실패를 확인한 뒤, 순수 scroll 상태 모델과 CreatorChannelHomeActivity scroll listener를 구현했다. 검증으로 CreatorChannelScrollStateTest, CreatorChannelHomeActivitySourceTest, :app:mergeDebugResources, :app:compileDebugKotlin, :app:ktlintCheck, git diff --check가 모두 BUILD SUCCESSFUL 또는 출력 없음으로 PASS했다. 병렬 Gradle 실행 중 zip END header not found가 한 차례 있었으나 단일 재실행에서 성공했다.

  • 2026-06-15: 사용자 요청에 따라 기존 UserProfileActivity로 이동하던 크리에이터 채널 진입점을 신규 CreatorChannelHomeActivity로 전환하는 작업을 Phase 7의 Task 7.3으로 추가했다. 이번 단계는 계획 문서 추가만 수행했으며 해당 진입점 전환 구현/빌드/테스트는 아직 실행하지 않았다.

  • 2026-06-15: Phase 6 reviewer gate에서 sticky tab-bar가 RecyclerView보다 앞선 sibling이라 draw order상 컨텐츠에 가려질 수 있다는 blocking issue를 확인했다. horizontal_tab_scroll_viewandroid:elevation="1dp"를 추가해 sticky tab-bar가 홈 컨텐츠 위에 그려지도록 수정하고 source test 계약을 보강했다.

  • 2026-06-15: Phase 6 reviewer gate 차단 이슈 수정 후 CreatorChannelHomeActivitySourceTest, CreatorChannelScrollStateTest, :app:mergeDebugResources, :app:compileDebugKotlin, :app:ktlintCheck, git diff --check를 재실행해 모두 BUILD SUCCESSFUL 또는 출력 없음으로 PASS했다. ktlintCheck.editorconfig disabled_rules deprecation 경고와 Gradle deprecation warning은 기존 경고로 이번 변경과 무관하다.

  • 2026-06-15: Phase 8 최종 단위 테스트로 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.common.*", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*", ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*"를 순차 실행해 모두 BUILD SUCCESSFUL을 확인했다.

  • 2026-06-15: Phase 8 리소스/컴파일/린트 검증으로 ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck를 순차 실행해 모두 BUILD SUCCESSFUL을 확인했다. ktlintCheck.editorconfig disabled_rules deprecation 경고와 Gradle deprecation warning은 기존 경고로 이번 변경과 무관하다.

  • 2026-06-15: Phase 8 수동 화면 검증 준비로 Figma 296:14890, 296:14892, 296:14287, 296:14288, 296:14289 스크린샷을 확인하고, CreatorChannelHomeActivity.kt, activity_creator_channel_home.xml, CreatorChannelTitleBarState.kt, CreatorChannelScrollState.kt, CreatorChannelHomeSectionAdapter.kt, CreatorChannelHomeActivitySourceTest.kt를 대조했다. ./gradlew :app:assembleDebugBUILD SUCCESSFUL이었으나, 설치/실행 시점에 연결 기기가 사라져 adb install -r "app/build/outputs/apk/debug/app-debug.apk"adb: no devices/emulators found로 실패했다. 재확인한 adb devices에도 기기가 없어 실제 전면 화면 캡처와 스크롤/클릭 육안 검증은 미완료로 남겼다.

  • 2026-06-15: Phase 9 이름 변경으로 CreatorChannelHomeActivity/activity_creator_channel_home.xml/ActivityCreatorChannelHomeBindingCreatorChannelActivity/activity_creator_channel.xml/ActivityCreatorChannelBinding으로 정리하고, Manifest와 모든 진입점 및 source test를 새 이름으로 갱신했다. focused source test, 홈 진입점 테스트, 크리에이터 채널 전체 테스트, 리소스 merge, Kotlin compile, git diff --check는 통과했다. ktlintCheck는 기존 audio_content 패키지명 underscore 규칙 위반으로 실패했으며 이번 변경 범위 밖이라 수정하지 않았다.

  • 2026-06-16: PRD에 신규 추가된 요구사항을 바탕으로 plan-task 문서를 보강했다. Phase는 섹션 단위로 과도하게 쪼개지 않고 상단 상태/탭/액션, 홈 탭 섹션 후속 UI/액션, 크리에이터 본인 페이지 Floating Button, 후속 보강 최종 검증으로 묶었으며, 세부 변경은 Task 체크리스트에 배치했다. 이번 단계는 계획 문서 보강만 수행했으며 구현/빌드/테스트는 실행하지 않았다.

  • 2026-06-16: PRD와 plan-task 재대조 중 TabLayout + ViewPager2 + 탭별 Fragment 컨테이너 전환 Phase가 누락되어 있음을 확인하고 Phase 10으로 추가했다. 기존 후속 Phase는 11~14로 밀어 정리했고, 후원하기 버튼 터치 정책, 본인 페이지 DM 확인하기 단독 버튼 정렬/높이 보존, Floating Button dim 영역 닫기 정책 확정 항목도 Task에 보강했다. 이번 단계는 계획 문서 보강만 수행했으며 구현/빌드/테스트는 실행하지 않았다.

  • 2026-06-25: 소개 섹션 본문 Figma 후속 보정 작업을 수행했다. item_creator_channel_home_introduce.xmltv_introduce_body@style/Typography.Body3를 적용해 @font/regular 16sp 계약을 보장하고, 기존 @dimen/spacing_14 title/body gap, @dimen/spacing_20 horizontal padding, match_parent 폭, white text, line-height 1.45, 카드 배경 없음 계약은 유지했다. 회귀 방지는 CreatorChannelActivitySourceTest의 소개 섹션 source assertion으로 추가했다.

  • 2026-06-25: 후속 UI 보정 검증으로 ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest" --tests "kr.co.vividnext.sodalive.v2.main.content.ContentMainFragmentSourceTest" --tests "kr.co.vividnext.sodalive.v2.widget.SeriesContentCardViewTest" --tests "kr.co.vividnext.sodalive.v2.widget.AudioContentCardViewTest", ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck, git diff --check를 실행해 모두 BUILD SUCCESSFUL 또는 출력 없음으로 PASS했다. ktlintCheck.editorconfig disabled_rules deprecation warning과 Gradle deprecation warning은 기존 경고로 이번 변경과 무관하다.

  • 2026-06-25: 실제 화면 수동 검증 가능 여부 확인을 위해 adb devices를 실행했으나 연결된 device/emulator가 없어 전면 화면 육안 검증은 수행하지 못했다. 이번 후속 보정은 source/widget 테스트와 Gradle 리소스/컴파일/스타일 검증으로 확인했다.