refactor(content): 상세 진입을 공통 액션으로 통합한다
This commit is contained in:
@@ -343,7 +343,7 @@
|
||||
- 2026-07-14: Task 1.11에서는 production 코드를 추가 변경하지 않고 기존 source test 클래스 두 곳과 계획 문서만 보강했다.
|
||||
|
||||
### Phase 2: Content 공통 Action
|
||||
- [ ] **Task 2.1: 오디오/시리즈 진입 호출부와 계약 확정**
|
||||
- [x] **Task 2.1: 오디오/시리즈 진입 호출부와 계약 확정**
|
||||
- 확인 예정 파일:
|
||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt`
|
||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/ContentMainFragment.kt`
|
||||
@@ -353,23 +353,56 @@
|
||||
- 검증 기준:
|
||||
- 화면 전용 UI model을 받지 않는 최소 command/result 계약이 정해진다.
|
||||
- Activity result 또는 호출 화면 후처리가 있는 경로는 Content result adapter와 단일 handler 필요 여부가 결정된다.
|
||||
- 확인 결과:
|
||||
- 공개 입력은 `audioContentId` 또는 `seriesId`와 호출부가 이미 알고 있는 성인 콘텐츠 여부만 받는 `AudioDetail`/`SeriesDetail` command로 제한한다. Home/Content/Creator 전용 UI model과 Response는 Action에 전달하지 않는다.
|
||||
- Action 결과는 유효하지 않은 ID의 `Ignored`, Access가 거부된 `Blocked`, 허용된 오디오/시리즈 navigation 결과로 구분한다. `ContentActionHandler`는 허용 결과만 기존 `Constants.EXTRA_AUDIO_CONTENT_ID` 또는 `Constants.EXTRA_SERIES_ID`로 변환한다.
|
||||
- Home banner의 series와 최근 활동의 audio는 성인 여부를 제공하지 않으므로 기존처럼 `AccessRequirement.Login`을 사용한다. Home의 event/creator/link와 community route는 Content Action 범위에 포함하지 않는다.
|
||||
- Content 추천 카드와 전체 탭은 `showAdultBadge`를 알고 있는 경우 이를 전달한다. 댓글/랭킹/원작 series/banner처럼 성인 여부가 없는 경로는 로그인만 확인한다.
|
||||
- Content Overview audio, Creator Channel Home audio, Audio tab, Live replay, Series tab은 성인 여부를 보유하므로 command에 전달한다. Creator Channel schedule audio/live replay와 Home series는 성인 여부가 없어 로그인만 확인한다.
|
||||
- 상세 진입은 모두 일반 `startActivity`이며 `ActivityResultLauncher`, route source extra, 호출 화면 후처리가 없다. 따라서 별도 Content result adapter나 feature composition handler를 추가하지 않는다.
|
||||
- `MainV2Activity`의 audio notification/deeplink/mini player와 series deeplink는 Phase 1에서 route 소비 순서와 boolean 반환 계약을 별도로 고정한 시스템 route이므로, PRD에 합의된 Home/Content/Content Overview/Creator Channel 전환 범위에는 포함하지 않는다.
|
||||
- 검증 기록:
|
||||
- 2026-07-14: `rg`와 대상 source 확인으로 V2 상세 Activity 직접 참조, ID/extra, 성인 여부 보유 여부, Activity result 사용 여부를 대조해 위 command/result 계약과 전환 범위를 확정했다.
|
||||
- 2026-07-14: 격리 worktree에서 변경 전 `./gradlew :app:testDebugUnitTest`를 실행해 전체 debug 단위 테스트가 `BUILD SUCCESSFUL`로 통과하는 기준선을 확인했다. 기존 dependency/manifest/Kotlin deprecation 경고는 있었지만 실패는 없었다.
|
||||
|
||||
- [ ] **Task 2.2: Content Action 순수 계약 테스트 및 구현**
|
||||
- [x] **Task 2.2: Content Action 순수 계약 테스트 및 구현**
|
||||
- 생성 예정 파일:
|
||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/content/action/ContentAction.kt`
|
||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/content/action/ContentActionCommand.kt`
|
||||
- `app/src/test/java/kr/co/vividnext/sodalive/v2/content/action/ContentActionTest.kt`
|
||||
- 검증 대상: invalid ID, audio/series route, 성인 Access 요구사항 전달, 허용/차단 결과.
|
||||
- 검증 기준: feature UI model과 DTO 의존 없이 입력·출력이 테스트된다.
|
||||
- RED 검증 기록:
|
||||
- 2026-07-14: `ContentActionTest`를 먼저 추가하고 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.content.action.ContentActionTest"`를 실행해 `ContentAction`, `ContentActionCommand`, `ContentActionResult`, `ContentActionHandler` 미정의 컴파일 오류와 `BUILD FAILED`를 확인했다.
|
||||
- GREEN 검증 기록:
|
||||
- 2026-07-14: `ContentActionCommand`, `ContentAction`, `ContentActionResult`, `ContentActionHandler`를 최소 구현하고 같은 단일 테스트 명령을 재실행해 7개 테스트와 빌드가 통과했다. Action은 ID/성인 여부와 Access 함수만 입력받고 feature UI model, DTO, Android UI에 의존하지 않는다.
|
||||
|
||||
- [ ] **Task 2.3: Content navigation adapter 구현 및 전체 호출부 전환**
|
||||
- [x] **Task 2.3: Content navigation adapter 구현 및 전체 호출부 전환**
|
||||
- 생성/수정 예정 파일:
|
||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/content/action/ContentActionHandler.kt`
|
||||
- Task 2.1에서 확정한 Home/Content/Overview/Creator Channel 호출 파일
|
||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt`
|
||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/HomeRecommendationUiModels.kt`
|
||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/ContentMainFragment.kt`
|
||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/model/AudioRecommendationsUiModels.kt`
|
||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/ContentOverviewActivity.kt`
|
||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/ui/ContentOverviewAdapter.kt`
|
||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt`
|
||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/audio/CreatorChannelAudioFragment.kt`
|
||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/live/CreatorChannelLiveFragment.kt`
|
||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/series/CreatorChannelSeriesFragment.kt`
|
||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/series/ui/CreatorChannelSeriesAdapter.kt`
|
||||
- 위 호출부 계약을 검증하는 기존 source/layout 테스트
|
||||
- 작업: 기존 extra와 Access UX를 보존하면서 오디오/시리즈 상세 진입을 한 곳으로 통합한다.
|
||||
- 검증 기준: 대상 UI에서 상세 Activity Intent 직접 생성이 제거되고 Content Action을 사용한다.
|
||||
- RED 검증 기록:
|
||||
- 2026-07-14: 기존 source/layout 테스트를 새 Content Action 결선 계약으로 먼저 변경하고 관련 6개 테스트 클래스 207건을 `--rerun-tasks`로 실행했다. 대상 화면의 직접 상세 Intent, series banner Intent, ID-only callback이 남아 있어 예상한 13건이 실패하고 `BUILD FAILED`가 발생함을 확인했다.
|
||||
- GREEN 검증 기록:
|
||||
- 2026-07-14: Home, Content, Content Overview, Creator Channel 호출부를 `handleContentAction`으로 전환하고 대상 feature/model source의 `AudioContentDetailActivity`/`SeriesDetailActivity` 직접 참조를 제거했다. 상세 Activity와 기존 ID extra 생성은 `ContentActionHandler`만 소유한다.
|
||||
- 2026-07-14: Content Overview와 Creator Channel Audio/Live replay/Series tab callback이 기존 UI model의 `showAdultBadge`를 command까지 전달하도록 연결했다. 성인 정보를 제공하지 않는 Home, schedule, Creator Home series 경로는 기존 Login 요구사항을 유지했다.
|
||||
- 2026-07-14: 같은 6개 테스트 클래스 207건을 `--rerun-tasks`로 재실행해 실패, 오류, 스킵 없이 `BUILD SUCCESSFUL`로 통과했다.
|
||||
- 2026-07-14: 결선 GREEN 중 발견한 기존 전체 탭 source assertion은 다른 helper의 `openSeriesDetail(seriesId)` 문자열에 우연히 의존하고 있었다. 실제 계약인 `openSeriesDetail(seriesId, findAllTabSeriesAdultAccess(seriesId))`를 검증하도록 강화한 뒤 단일 테스트와 207건 결선을 다시 통과시켰다.
|
||||
|
||||
- [ ] **Task 2.4: Content Phase 회귀 검증**
|
||||
- [x] **Task 2.4: Content Phase 회귀 검증**
|
||||
- 실행 명령:
|
||||
```bash
|
||||
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.content.action.*"
|
||||
@@ -378,8 +411,16 @@
|
||||
./gradlew :app:compileDebugKotlin
|
||||
./gradlew :app:ktlintCheck
|
||||
git diff --check
|
||||
```
|
||||
```
|
||||
- 수동 확인: Home, Content, Content Overview, Creator Channel에서 audio/series 상세 진입과 성인 차단 UX가 기존과 동일하다.
|
||||
- 검증 기록:
|
||||
- 2026-07-14: `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.content.action.*"`, `--tests "kr.co.vividnext.sodalive.v2.main.content.*"`, `--tests "kr.co.vividnext.sodalive.v2.creator.channel.*"`, 추가 Home 회귀 `--tests "kr.co.vividnext.sodalive.v2.main.home.*"`를 각각 실행해 모두 `BUILD SUCCESSFUL`을 확인했다. Content 묶음은 99개 테스트가 통과했다.
|
||||
- 2026-07-14: Phase 1에서 작성된 `ContentMainFragmentLoginGuardSourceTest`가 이전 화면 내부 `ensureV2Access` 구현을 고정해 Content 묶음 3건이 실패했다. 실제 Access 계약은 `ContentMainFragment -> ContentAction -> ContentActionHandler` 순으로 이동했으므로 invalid ID, 성인 요구사항, Access-before-navigation을 새 소유자에서 검증하도록 테스트를 갱신한 뒤 단일 클래스와 Content 99건을 다시 통과시켰다.
|
||||
- 2026-07-14: `./gradlew :app:testDebugUnitTest`를 실행해 전체 debug 단위 테스트가 44초에 `BUILD SUCCESSFUL`로 통과했고, `./gradlew :app:compileDebugKotlin`도 `BUILD SUCCESSFUL`로 통과했다.
|
||||
- 2026-07-14: `./gradlew :app:ktlintTestSourceSetCheck --rerun-tasks`는 `BUILD SUCCESSFUL`로 통과했고 test source 리포트는 0건이다. `./gradlew :app:ktlintCheck`는 이번 변경과 무관한 기존 main source 기준선 위반 550줄로 실패했으며, 리포트에서 Phase 2 변경 Kotlin 파일의 위반은 0건임을 확인했다. 레거시 파일은 수정하지 않았다.
|
||||
- 2026-07-14: 대상 Home, Content, Content Overview, Creator Channel 운영 source에서 `AudioContentDetailActivity`, `SeriesDetailActivity` 및 상세 ID extra를 검색한 결과 잔존이 없고, `ContentActionHandler`만 기존 Activity/extra 생성을 소유함을 확인했다. Phase 1에서 계약을 고정한 `MainV2Activity` 시스템 route는 범위대로 유지했다.
|
||||
- 2026-07-14: `./gradlew tasks --all`은 `BUILD SUCCESSFUL`로 통과했다. `adb devices`는 연결된 기기가 없음을 반환해 실기기 수동 탭 검증은 수행하지 못했고, 대신 Robolectric handler 테스트로 허용/차단과 기존 extra를 검증했다.
|
||||
- 2026-07-14: `git diff --check HEAD`는 whitespace 오류 없이 통과했다.
|
||||
|
||||
### Phase 3: Live 공통 Action
|
||||
- [ ] **Task 3.1: 기존 Live 흐름 차이와 레거시 의존 목록 확정**
|
||||
@@ -569,3 +610,4 @@
|
||||
- 2026-07-14: Community 업로드 후 Home/Community 탭 갱신 설계를 구체화했다. 초기 구현은 전역 observer 대신 `CommunityChange` 결과와 Creator Channel의 단일 `handleCommunityChange` composition handler를 사용하며, 레거시 `ActivityResult`는 `v2` adapter에서 변경 결과로 변환한다.
|
||||
- 2026-07-14: 사용자 확인에 따라 Activity result가 필요한 모든 도메인 Action에 공통 결과 전달 원칙을 확장했다. 기본 방식은 `ActivityResult -> 명시적 도메인 결과 -> feature 단일 handler`이며, Action/Repository 직접 결과도 동일 handler로 합류한다. `SharedFlow`/observer는 Activity 밖의 독립 소비자와 lifecycle/replay 요구가 확인될 때만 도입한다.
|
||||
- 2026-07-14: Phase 0/1 리뷰 답변을 반영해 Legacy MyPage 호출부와 로그인 token 정책 확인, FanTalk source assertion 수동 삭제 사유를 기록했다. 문서 변경 후 `./gradlew tasks --all`은 `BUILD SUCCESSFUL`, `git diff --check HEAD`는 무출력으로 통과했다.
|
||||
- 2026-07-14: Phase 2 Content Action 전환 후 전체 `:app:testDebugUnitTest`, `:app:compileDebugKotlin`, `tasks --all`, `git diff --check HEAD`가 통과했다. 전체 ktlint는 기존 main source 550줄 기준선 위반으로 실패했지만 Phase 2 변경 Kotlin 파일과 test source의 신규 위반은 0건이다. 연결된 Android 기기가 없어 실기기 수동 탭 검증은 후속 확인 항목으로 남겼다.
|
||||
|
||||
@@ -85,6 +85,11 @@ Access Phase 테스트 예시:
|
||||
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.*"
|
||||
```
|
||||
|
||||
Content Action Phase 테스트 예시:
|
||||
```bash
|
||||
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.content.action.ContentActionTest"
|
||||
```
|
||||
|
||||
참고:
|
||||
- 신규 Kotlin 테스트 메서드는 backtick 함수명을 사용하고, 테스트명은 한글 문장으로 작성한다.
|
||||
- 기존 영어 테스트명을 수정하지 않는 최소 변경 상황을 제외하고, 새 테스트명에 영어 문장을 사용하지 않는다.
|
||||
|
||||
Reference in New Issue
Block a user