feat(home): 최근 활동 LIVE 라우팅을 추가한다

This commit is contained in:
2026-07-30 16:42:33 +09:00
parent a1aa9c2243
commit f600d10e8b
10 changed files with 366 additions and 8 deletions

View File

@@ -793,7 +793,106 @@
- 검증 기록:
- 2026-07-12: `HomeMainFragmentSourceTest``홈 추천 최근 데뷔와 AI 캐릭터 섹션 타이틀은 chevron을 숨긴다`를 먼저 추가해 기존 구현에서 `HomeMainFragmentSourceTest.kt:40` assertion 실패로 RED를 확인했다. 이후 `HomeMainFragment.setUpSectionTitles()`에서 `viewHomeRecentDebutTitle`, `viewHomeAiCharacterTitle``showMore = true`를 제거해 기본 `false` 정책을 적용했다.
### Phase 16: 방금 활동한 크리에이터 LIVE 라우팅
**Phase 결과:** `방금 활동한 크리에이터``LIVE` item을 터치하면 `targetId` 유무에 따라 기존 공통 라이브 룸 진입 또는 크리에이터 채널 이동이 실행된다.
**선행 조건:** `prd.md``2026-07-30 변경: 최근 활동 LIVE 라우팅` 요구사항 승인과 서버의 필수 양수 `HomeActiveCreatorItem.creatorId: Long` 계약 확정.
**Phase 완료 조건:** `P16-T1``P16-GATE` 완료, Task와 `Verification Log`에 실제 검증 결과 누적.
#### Task 16.1: LIVE route와 공통 액션 연결
**Goal 실행 `P16-T1`:** 최근 활동 `LIVE` item이 유효한 `targetId > 0L`가 있으면 라이브 룸으로 진입하고, `targetId == null && creatorId > 0L`이면 크리에이터 채널로 이동하며, 잘못된 `targetId` 또는 `creatorId`에서는 이동하지 않는다.
- **시작 조건:** Phase 16 선행 조건 충족.
- **완료 증거:** RED/GREEN 체크박스 완료, focused test와 직접 영향 회귀 성공, 문서 검증 기록 누적.
- **범위 밖:** `LiveActionCoordinator`, `CreatorAction`, `V2AccessGuard`의 공통 정책 변경과 다른 activity type 라우팅 변경.
**Files:**
- Modify: `app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/data/HomeRecommendationModels.kt`
- Modify: `app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/HomeRecommendationUiModels.kt`
- Modify: `app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/HomeRecommendationMappers.kt`
- Modify: `app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt`
- Test: `app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragmentLayoutTest.kt`
- Test: `app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragmentLoginGuardSourceTest.kt`
- Modify: `docs/agent-guides/build-test-style.md`
- Modify: `docs/20260601_메인_홈_추천_UI와_API_연동/plan-task.md`
**Interfaces:**
- Consumes: `HomeActiveCreatorItem(activityType, targetId, creatorId)`, `LiveActionCoordinator.enterLiveRoom(roomId: Long)`, `CreatorActionCommand.Profile(creatorId: Long)`.
- Produces: `HomeRecommendationRecentlyActiveCreatorUiModel.creatorId: Long`, `HomeRecommendationRecentlyActiveCreatorRoute.LiveRoom(roomId: Long)`, `HomeRecommendationRecentlyActiveCreatorRoute.CreatorChannel(creatorId: Long)`.
- [x] **RED:** `HomeMainFragmentLayoutTest``HomeMainFragmentLoginGuardSourceTest`에 다음 실패 계약을 추가한다.
- `HomeActiveCreatorItem.creatorId``HomeRecommendationRecentlyActiveCreatorUiModel.creatorId`로 보존된다.
- `LIVE + targetId > 0L``HomeRecommendationRecentlyActiveCreatorRoute.LiveRoom(targetId)`를 반환한다.
- `LIVE + targetId == null + creatorId > 0L``HomeRecommendationRecentlyActiveCreatorRoute.CreatorChannel(creatorId)`을 반환한다.
- `LIVE + targetId == null + creatorId <= 0L``null`을 반환한다.
- `HomeMainFragment.onRecentActivityClick()``LiveRoom``liveActionCoordinator.enterLiveRoom(route.roomId)`으로, `CreatorChannel``handleCreatorAction(CreatorActionCommand.Profile(route.creatorId))`로 전달한다.
- 기존 `LIVE_REPLAY`, `AUDIO`, `COMMUNITY`, unknown, invalid `targetId` 기대값은 유지한다.
- [x] **RED 확인:** 아래 focused test를 실행해 `creatorId`, `LiveRoom`, `CreatorChannel` 미정의 또는 기존 `LIVE -> null` 기대값 불일치로 실패하는지 확인한다.
```bash
./gradlew :app:testDebugUnitTest \
--tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest" \
--tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLoginGuardSourceTest"
```
- [x] **GREEN:** RED를 통과시키는 최소 구현을 작성한다.
- DTO와 최근 활동 UI model에 필수 `creatorId: Long`을 추가하고 mapper에서 그대로 전달한다.
- 최근 활동 route에 `LiveRoom(roomId)``CreatorChannel(creatorId)`을 추가한다.
- `CreatorActivityType.Live``targetId > 0L`이면 `LiveRoom(targetId)`, `targetId == null`이면 `creatorId.takeIf { it > 0L }`에 대해서만 `CreatorChannel(creatorId)`을 반환하고, `targetId <= 0L`이면 fallback 없이 `null`을 반환한다.
- Fragment는 `LiveRoom`에 기존 `LiveActionCoordinator.enterLiveRoom()`을 사용하고 `CreatorChannel`에 기존 `CreatorActionCommand.Profile`을 사용한다.
- 홈 전용 로그인·성인 콘텐츠 분기를 새로 만들지 않는다.
- `build-test-style.md`에 위 두 home test class를 함께 실행하는 Phase 16 focused test 예시를 추가한다.
- [x] **GREEN 확인:** RED 확인과 같은 focused test를 다시 실행해 route, mapper, Fragment 공통 액션 연결이 모두 성공하는지 확인한다.
- [x] **REFACTOR:** 이번 Task가 만든 중복만 정리하고 아래 직접 영향 회귀와 품질 검증 결과를 Task 검증 기록 및 `Verification Log`에 누적한다. 전체 unit test는 공통 access/action 구현을 변경하지 않고 home route 소비만 추가하므로 생략하며, 대신 home focused test와 기존 live/creator action 회귀를 실행한다.
```bash
./gradlew :app:testDebugUnitTest \
--tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest" \
--tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLoginGuardSourceTest" \
--tests "kr.co.vividnext.sodalive.v2.live.action.*" \
--tests "kr.co.vividnext.sodalive.v2.creator.action.*"
./gradlew :app:compileDebugKotlin
./gradlew :app:ktlintCheck
git diff --check
```
### 완료 조건
- [x] `HomeActiveCreatorItem.creatorId`가 DTO에서 UI model까지 필수 `Long`으로 보존된다.
- [x] `LIVE`의 두 route와 invalid `creatorId` no-op이 자동 테스트로 검증된다.
- [x] 라이브 룸 route가 `LiveActionCoordinator`를 사용해 기존 로그인·본인인증·콘텐츠 보기 설정 정책을 우회하지 않는다.
- [x] 다른 activity type의 route 회귀 테스트가 성공한다.
- [x] 사용자 직접 지시가 없으므로 커밋하지 않는다.
### 검증 방법
#### Phase 16 Gate
**Goal 실행 `P16-GATE`:** Phase 16 route 분기, 공통 접근 흐름 재사용, 직접 영향 회귀를 최종 판정한다.
- **시작 조건:** `P16-T1` 체크박스와 검증 기록 완료.
- **완료 증거:** Task 16.1 REFACTOR 명령이 모두 성공하고 아래 수동 대조를 완료한다.
- **범위 밖:** Gate 통과를 위한 test 삭제·완화, 공통 access/action 로직 수정, 관련 없는 홈 코드 정리.
수동 대조:
- [x] `targetId > 0L``LIVE` route가 `LiveActionCoordinator.enterLiveRoom(targetId)`에 연결된다.
- [x] `targetId == null && creatorId > 0L``LIVE` route가 `CreatorActionCommand.Profile(creatorId)`에 연결된다.
- [x] `targetId == null && creatorId <= 0L`에서 액션이 실행되지 않는다.
- [x] Git diff가 Phase 16 Files와 승인된 PRD·test guide 범위 안에 있고 커밋이 생성되지 않았다.
검증 기록:
- 2026-07-30: 사용자의 `진행`은 production 구현이 아니라 `plan-task.md` 반영을 의미한다는 설명에 따라 Phase 16 구현을 중단했다. 설명을 받기 전에 `HomeMainFragmentLayoutTest``creatorId` DTO/UI model 보존, `LIVE + targetId``LiveRoom`, `LIVE + targetId == null``CreatorChannel`, `creatorId <= 0L` no-op RED 계약을 추가했고, `HomeMainFragmentLoginGuardSourceTest`에 최근 활동 route가 기존 Live/Creator Action을 사용하는 계약을 추가했다. 사용자가 이미 작성된 코드는 삭제하지 않도록 요청해 두 테스트 변경은 유지한다. focused test 명령은 실행 중 사용자 중단으로 종료되어 성공·실패 출력이 없으므로 `RED 확인`은 미완료 상태로 남긴다. `git diff --name-only` 기준 변경은 PRD, 계획 문서, 위 두 테스트 파일뿐이며 `app/src/main` production 코드는 변경되지 않았다. 커밋은 생성하지 않았다.
- 2026-07-30: Phase 16 구현을 재개해 기존 RED 계약을 실행했다. focused RED는 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest" --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLoginGuardSourceTest"`에서 `HomeActiveCreatorItem.creatorId`, `HomeRecommendationRecentlyActiveCreatorUiModel.creatorId`, `LiveRoom`, `CreatorChannel` 미정의 컴파일 실패로 확인했다. GREEN 구현으로 `HomeActiveCreatorItem.creatorId`를 DTO에 추가하고 최근 활동 UI model까지 보존했으며, `CreatorActivityType.Live` route를 `targetId > 0L`이면 `LiveRoom(roomId)`, `targetId == null && creatorId > 0L`이면 `CreatorChannel(creatorId)`, 그 외에는 `null`로 분기했다. 리뷰에서 `targetId <= 0L`일 때 creator fallback이 실행될 수 있는 차단 이슈가 확인되어 `targetId = 0L/-1L + creatorId > 0L` RED 테스트를 추가했고, `CreatorActivityType.Live``targetId == null`일 때만 creator fallback을 허용하도록 보완했다. `HomeMainFragment.onRecentActivityClick()``LiveRoom``liveActionCoordinator.enterLiveRoom(route.roomId)`로, `CreatorChannel``handleCreatorAction(CreatorActionCommand.Profile(route.creatorId))`로 전달해 공통 접근 정책을 재사용한다. focused GREEN, 직접 영향 회귀(`HomeMainFragmentLayoutTest`, `HomeMainFragmentLoginGuardSourceTest`, `v2.live.action.*`, `v2.creator.action.*`), `./gradlew :app:compileDebugKotlin`, `./gradlew :app:ktlintCheck`, `git diff --check`가 모두 성공했다. `ktlintCheck``.editorconfig disabled_rules` deprecation warning과 Gradle deprecation warning은 기존 경고다. `./gradlew :app:installDebug`는 SM-G960N 기기에 설치 성공했고, `adb shell monkey -p kr.co.vividnext.sodalive.debug -c android.intent.category.LAUNCHER 1`로 debug 앱 런처 실행을 확인했다. 실제 추천 LIVE item 터치는 서버 데이터/로그인 상태가 필요한 경로라 이번 검증에서는 자동 route test와 source 계약으로 대체했다. 커밋은 생성하지 않았다.
## Verification Log
- 2026-07-30: Phase 16 방금 활동한 크리에이터 LIVE 라우팅 검증으로 focused RED/GREEN과 직접 영향 회귀를 수행했다. RED는 `creatorId`, `LiveRoom`, `CreatorChannel` 미정의 컴파일 실패로 확인했고, GREEN 후 focused home tests와 `v2.live.action.*`, `v2.creator.action.*` 회귀, `compileDebugKotlin`, `ktlintCheck`, `git diff --check`가 모두 통과했다. 리뷰에서 `targetId <= 0L`일 때 creator fallback이 실행될 수 있는 차단 이슈가 확인되어 `0L/-1L` 회귀 테스트와 null 전용 fallback 분기를 추가했고, 재검증과 재리뷰에서 blocking finding 없음으로 승인받았다. 수동 표면 확인으로 `adb devices`에서 `2cec640c34017ece device`를 확인하고 `installDebug` 및 launcher monkey 실행을 성공시켰다. 실제 LIVE item 터치는 추천 데이터 조건이 필요해 자동 route/source 테스트로 대체했다.
- 2026-07-12: Phase 15 추천 섹션 타이틀 chevron 숨김 변경 검증으로 `HomeMainFragmentSourceTest``홈 추천 최근 데뷔와 AI 캐릭터 섹션 타이틀은 chevron을 숨긴다`를 추가했고, 구현 전 `HomeMainFragmentSourceTest.kt:40` assertion 실패로 RED를 확인했다. `HomeMainFragment.setUpSectionTitles()`에서 `viewHomeRecentDebutTitle`, `viewHomeAiCharacterTitle``showMore = true`를 제거한 뒤 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentSourceTest" --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest" --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest"`, `./gradlew :app:mergeDebugResources :app:compileDebugKotlin :app:ktlintCheck`, `git diff --check`가 통과했다. `ktlintCheck``.editorconfig disabled_rules` deprecation warning은 기존 설정 경고다. `./gradlew :app:testDebugUnitTest` 전체 실행은 `CreatorChannelActivitySourceTest > 팬Talk 섹션은 Figma ListComment layout과 bind로 렌더링한다`, `CreatorChannelHomeViewModelTest > 채널 후원 성공은 기존 후원 API를 호출하고 홈을 다시 로드한다` 실패 후 타임아웃됐으며, 실패 영역은 이번 변경 파일과 무관한 `v2.creator.channel` 범위다. `adb devices`는 처음 1대를 표시했으나 `:app:installDebug` 시점에는 `No connected devices!`로 실패했고 이후 `adb devices`가 빈 목록을 반환해 실기기 수동 확인은 수행하지 못했다.
- 2026-07-12: `genreCreators` UI 미표시 변경 검증으로 targeted RED/GREEN 테스트를 수행했다. 리뷰에서 PRD 앞부분의 장르별 크리에이터 표시/모두 팔로우 문구와 `HomeRecommendationUiState.Content.isEmpty``genreCreators.groups` 포함이 차단 이슈로 확인되어, PRD 문구를 미표시 정책으로 정리하고 `isEmpty`는 실제 표시 섹션만 기준으로 판단하도록 수정했다. `home recommendation empty state ignores hidden genre creators` 테스트는 수정 전 `HomeMainFragmentLayoutTest.kt:180` assertion 실패로 RED를 확인했고, 수정 후 GREEN 전환을 확인했다. 추가 재검토에서 plan-task 과거 Task 6.4/6.12와 코드/테스트에 남은 `genreCreators` follow-all 및 pager UI 활성 계약이 차단 이슈로 확인되어, 과거 Task 문구는 현재 미사용 정책으로 정리하고 `HomeMainFragment`의 genre follow-all 연결, `HomeRecommendationViewModel`의 genre follow 완료 상태 갱신, 활성 UI/follow-all 테스트 계약을 제거했다. 이후 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLayoutTest" :app:mergeDebugResources :app:compileDebugKotlin :app:ktlintCheck`를 실행해 BUILD SUCCESSFUL을 확인했다. `ktlintCheck` 최초 재실행은 테스트 파일 불필요한 빈 줄로 실패했고 해당 줄만 제거한 뒤 재실행해 성공했다. `git diff --check` 출력 없음도 확인했다. `ktlintCheck`에서는 기존 `.editorconfig disabled_rules` deprecation warning만 출력됐고 lint 실패는 없었다. `adb devices` 결과 연결된 기기/에뮬레이터가 없어 실기기 수동 확인은 수행하지 못했다.
- 2026-07-10: Phase 13 코드 리뷰 및 검증을 재수행했다. 리뷰 범위는 최근 활동 COMMUNITY route가 `targetId``postId`로 해석해 `CreatorChannelCommunityDetailActivity.newIntent(context, postId)`를 생성하는지, 인기 커뮤니티 item이 `FeedItem.Community.postId` 기반으로 상세 Activity를 여는지, 기존 `CreatorCommunityAllActivity`/커뮤니티 목록 extra 제거 여부, 로그인 가드 전 invalid return 유지 여부다. 코드 리뷰 결과 blocking finding은 없었다. 검증으로 Phase 13 targeted test, `HomeMainFragmentLayoutTest` 전체, `./gradlew :app:compileDebugKotlin`, `./gradlew :app:ktlintCheck`, `git diff --cached --check`가 모두 통과했고, `rg`로 v2 home production 코드에 기존 커뮤니티 목록 라우팅 참조가 남지 않았음을 확인했다.