17 KiB
크리에이터 채널 차단 후 이탈 구현 계획/TASK
For agentic workers: 각 단계는 체크박스(
- [ ])로 추적하고, 완료 즉시- [x]로 갱신한다. 구현 범위 변경이 생기면 이 문서를 먼저 수정한 뒤 코드에 반영한다.
Goal: 차단 성공 후 사용자가 현재 크리에이터 채널에 머물지 않고 이전 화면 또는 MainV2Activity 홈 fallback으로 이동한다.
Architecture: CreatorChannelHomeViewModel은 기존 차단 API 성공 흐름에서 one-shot 성공 이벤트를 추가로 emit한다. CreatorChannelHomeFragment는 이벤트를 consume해 Host callback으로 넘기고, CreatorChannelActivity는 isTaskRoot 여부에 따라 finish() 또는 MainV2Activity fallback 후 finish()를 수행한다.
Tech Stack: Kotlin, AndroidX LiveData, RxJava3, JUnit4 local unit test, source contract test.
전제와 성공 기준
- PRD:
docs/20260814_크리에이터_채널_차단_후_이탈/prd.md - 구현은 차단 API 성공 후에만 화면 이탈을 수행한다.
- 기존 차단 확인 모달과 성공/실패 toast는 유지한다.
- 홈 fallback Activity는
kr.co.vividnext.sodalive.v2.main.MainV2Activity다. - 테스트 범위는
app/src/testlocal unit/source contract test로 한정한다. - 사용자가 명시적으로 요청하지 않았으므로
app/src/androidTest,connectedDebugAndroidTest, 기기·에뮬레이터 조작, 스크린샷 검증은 포함하지 않는다.
파일 구조
- Modify:
app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeViewModel.kt- 차단 성공 one-shot event를 제공한다.
- Modify:
app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeFragment.kt- 차단 성공 event를 observe/consume하고 host callback으로 전달한다.
- Modify:
app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt- host callback을 구현하고
isTaskRootfallback을 처리한다.
- host callback을 구현하고
- Modify:
app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeViewModelTest.kt- 차단 성공/실패 event contract를 검증한다.
- Modify:
app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.kt- Fragment/Activity wiring과
MainV2Activityfallback source contract를 검증한다.
- Fragment/Activity wiring과
Phase 1: 차단 성공 후 채널 이탈
Phase 결과: 사용자가 크리에이터 채널에서 현재 크리에이터 차단에 성공하면 현재 채널에서 빠져나가고, 이전 화면이 없으면 MainV2Activity로 이동한다.
선행조건: docs/20260814_크리에이터_채널_차단_후_이탈/prd.md 확정.
Phase 완료 조건: P1-T1, P1-T2, P1-GATE 완료와 검증 기록 누적.
구현 항목
Task 1.1 차단 성공 이벤트 추가
Goal 실행 P1-T1: CreatorChannelHomeViewModel.blockUser()가 API 성공 시 기존 성공 toast와 함께 차단 성공 event를 emit한다.
- 시작 조건:
CCB-001,CCB-005확정. - 완료 증거: RED/GREEN 체크박스 전체 완료, focused
CreatorChannelHomeViewModelTest통과. - 범위 밖: Fragment/Activity navigation wiring은
P1-T2에서 처리한다.
Files:
- Modify:
app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeViewModelTest.kt - Modify:
app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeViewModel.kt
Interfaces:
-
Consumes: 기존
CreatorChannelHomeUiState.Content,CreatorChannelRepository.blockUser(userId, token),CreatorChannelEvent<T>. -
Produces:
blockSuccessLiveData: LiveData<CreatorChannelEvent<Unit>>. -
RED: 기존
차단 성공은 block API를 호출하고 차단 완료 토스트를 emit한다test에blockSuccessLiveDataevent 검증을 추가한다. 실패 케이스 test에는ApiResponse.success == false일 때blockSuccessLiveData.value == null을 검증한다. -
RED 확인: 아래 focused test를 실행해
blockSuccessLiveData미정의 또는 event 미발행 assertion 실패를 확인한다.
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeViewModelTest" --no-parallel --no-daemon -Pkotlin.incremental=false
- GREEN:
CreatorChannelHomeViewModel에MutableLiveData<CreatorChannelEvent<Unit>>기반blockSuccessLiveData를 추가하고,blockUser()성공 분기에서 기존creator_channel_block_successtoast emit 후CreatorChannelEvent(Unit)을 emit한다. 실패·예외 분기에서는 emit하지 않는다. - GREEN 확인: 같은 focused test를 다시 실행해 성공을 확인한다.
- REFACTOR: event naming과 observe 순서를 기존
toastLiveData,chatRoomIdLiveData스타일과 맞추고 focused test를 재실행해 결과를 이 Task 아래 검증 기록에 남긴다.
검증 기록:
- 2026-08-14 RED:
CreatorChannelHomeViewModelTest실행 시blockSuccessLiveData미정의로compileDebugUnitTestKotlin이 실패했다. - 2026-08-14 GREEN:
blockSuccessLiveData와 성공 분기 emit을 최소 추가한 뒤 같은 focused test가BUILD SUCCESSFUL로 통과했다. 성공 event는 한 번만 consume되고, API 실패·예외에서는 emit되지 않음을 확인했다.
Task 1.2 Fragment/Activity 이탈 연결
Goal 실행 P1-T2: 차단 성공 event를 CreatorChannelActivity까지 전달하고, 이전 화면 또는 MainV2Activity fallback으로 이동한다.
- 시작 조건:
P1-T1완료. - 완료 증거: RED/GREEN 체크박스 전체 완료, focused
CreatorChannelActivitySourceTest통과. - 범위 밖: 차단 API 호출 방식, 기존 modal UI,
MainV2Activity내부 동작 변경.
Files:
- Modify:
app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.kt - Modify:
app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeFragment.kt - Modify:
app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt
Interfaces:
-
Consumes:
CreatorChannelHomeViewModel.blockSuccessLiveData. -
Produces:
CreatorChannelHomeFragment.Host.onCreatorChannelBlockSucceeded(). -
RED:
CreatorChannelActivitySourceTest에 source contract test를 추가한다. 검증 조건은CreatorChannelHomeFragment가blockSuccessLiveData.observe와event.consume()?.let { host.onCreatorChannelBlockSucceeded() }흐름을 갖는지,CreatorChannelActivity가onCreatorChannelBlockSucceeded()를 구현하는지, 구현 내부에서isTaskRoot,MainV2Activity::class.java,finish()를 사용하는지 확인한다. 또한showUserBlockDialog()구간에는homeActionDelegate?.blockUser()만 있고 직접finish()나MainV2Activity이동이 없음을 확인한다. -
RED 확인: 아래 focused test를 실행해 observer, host callback, fallback 구현 부재로 인한 assertion 실패를 확인한다.
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest" --no-parallel --no-daemon -Pkotlin.incremental=false
- GREEN:
CreatorChannelHomeFragment.observeViewModel()에서blockSuccessLiveData를 observe하고 consume 후 host callback을 호출한다.CreatorChannelHomeFragment.Host에onCreatorChannelBlockSucceeded()를 추가한다.CreatorChannelActivity는MainV2Activityimport를 추가하고,onCreatorChannelBlockSucceeded()에서isTaskRoot이면Intent(this, MainV2Activity::class.java)를startActivity한 뒤finish()를 호출한다.isTaskRoot가 아니면finish()만 호출한다. - GREEN 확인: 같은 focused source test를 다시 실행해 성공을 확인한다.
- REFACTOR: 추가한 source contract가 과도하게 넓지 않은지 확인하고, 기존
CreatorChannelActivitySourceTest.sourceSection()helper를 재사용한다. focused test를 재실행해 결과를 이 Task 아래 검증 기록에 남긴다.
검증 기록:
- 2026-08-14 RED:
CreatorChannelActivitySourceTest100개 중 신규 차단 이탈 contract만 observer 부재 assertion으로 실패했다. - 2026-08-14 GREEN: Fragment observer/Host callback과 Activity
isTaskRoot분기를 최소 추가한 뒤 같은 source test 100개가 모두 통과했다.
완료 조건
P1-T1,P1-T2의 체크박스와 완료 증거가 모두 충족됐다.CCB-001~005가 구현 또는 명시 검증으로 추적된다.- API 성공 전 navigation이 발생하지 않는다는 source contract가 남아 있다.
- task root fallback 대상이
MainV2Activity임을 source contract가 검증한다.
검증 방법
Phase 1 Gate
Goal 실행 P1-GATE: 차단 성공 후 채널 이탈과 홈 fallback 동작을 최종 판정한다.
- 시작 조건:
P1-T1,P1-T2완료. - 완료 증거: 아래 자동 검증 통과와 Progress 기록.
- 범위 밖: Gate 통과를 위한 test 삭제·완화, unrelated refactor, instrumentation test 추가.
./gradlew :app:testDebugUnitTest \
--tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeViewModelTest" \
--tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest" \
--no-parallel --no-daemon -Pkotlin.incremental=false
./gradlew :app:compileDebugKotlin --no-parallel --no-daemon -Pkotlin.incremental=false
./gradlew :app:ktlintCheck --no-parallel --no-daemon
git diff --check
Expected: focused tests와 compile은 BUILD SUCCESSFUL, git diff --check는 출력 없음. ktlintCheck가 기존 전역 위반으로 실패하면 이번 변경 파일 포함 여부를 확인해 Progress에 구분 기록한다.
- ViewModel과 Activity source focused test 통합 실행이 통과했다.
compileDebugKotlin과ktlintCheck가 통과했다.git diff --check와git diff --cached --check결과 출력이 없었다.- 전체 local unit suite의 범위 밖 실패를 분리하고 아래 Progress에 기록했다.
실행 순서와 의존성
| 순서 | Goal | 선행조건 | 병행 가능 | 차단 시 다음 행동 |
|---|---|---|---|---|
| 1 | P1-T1 |
PRD 확정 | 아니요 | ViewModel event contract 재검토 |
| 2 | P1-T2 |
P1-T1 |
아니요 | Host callback 또는 Activity fallback contract 재검토 |
| 3 | P1-GATE |
P1-T1, P1-T2 |
아니요 | 실패 소유 Task의 회귀 수정 Task 추가 |
P1-T1 -> P1-T2 -> P1-GATE
변경 금지 항목
- 차단 API request/response 계약을 변경하지 않는다.
MainV2Activity내부 구현을 변경하지 않는다.- API 성공 전
CreatorChannelActivity를 종료하거나 홈으로 이동하지 않는다. - 기존 modal UI와 string을 변경하지 않는다.
app/src/androidTest, 기기·에뮬레이터 UI 조작, 스크린샷 QA를 추가하지 않는다.- 관련 없는 creator channel tab, community, fan talk, live routing 코드를 리팩터링하지 않는다.
의사결정 및 중단 규칙
- 실패 event 또는 예외 event에서도 화면 이탈이 필요하다는 요구가 생기면 PRD
Decision Log와 이 문서 범위를 먼저 갱신한다. MainV2Activityfallback에 flag 정책이 필요하다는 증거가 나오면 source/test로 먼저 실패를 고정하고, 기존 홈 진입점의 intent flag 관례를 확인한 뒤 최소 변경한다.- 검증 중 기존 전역 test/ktlint 실패가 나오면 이번 변경 파일 포함 여부를 분리해 기록하고, 범위 밖 실패는 임의 수정하지 않는다.
Progress
기존 기록을 삭제하거나 덮어쓰지 않고 실제 실행 결과를 차수별로 누적한다.
문서 작성 — 2026-08-14
- 상태: 완료
- 무엇을: PRD와 구현 계획/TASK 문서를 생성했다. production code와 test code는 변경하지 않았다.
- 왜: 사용자가 “문서만 생성 또는 수정하고 아직 구현은 하지 않는다”고 지시했다.
- 어떻게:
docs/sample/sample-prd.md— 샘플 구조 확인.docs/sample/sample-plan-task.md— TDD Task 구조 확인.docs/agent-guides/work-plan-docs.md— 신규 문서 배치와 검증 기록 규칙 확인.rg -n "차단|block|CreatorChannel|크리에이터 채널|MainV2Activity|뒤로가기" "docs"— 기존 관련 문서 범위 확인.
- 남은 항목:
P1-T1,P1-T2,P1-GATE구현과 검증. - 다음 행동: 사용자가 구현 진행을 승인하면
P1-T1RED 단계부터 시작한다.
P1-GATE 1차 실행 — 2026-08-14
- 상태: 완료
- 무엇을:
P1-T1,P1-T2를 RED/GREEN으로 구현하고 focused test, compile, ktlint, diff 검증을 완료했다. - 왜: 차단 성공 후 현재 크리에이터 채널에서 이탈하고 task root에서는
MainV2Activity로 fallback해야 한다. - 어떻게:
- ViewModel RED —
blockSuccessLiveData미정의 compile failure 확인. - ViewModel GREEN — focused
CreatorChannelHomeViewModelTestBUILD SUCCESSFUL. - Activity RED — source test 100개 중 신규 차단 이탈 contract 1건 실패 확인.
- Activity GREEN — source test 100개 전체 통과.
- focused 통합 test —
BUILD SUCCESSFUL. ./gradlew :app:compileDebugKotlin --no-parallel --no-daemon -Pkotlin.incremental=false—BUILD SUCCESSFUL../gradlew :app:ktlintCheck --no-parallel --no-daemon— 기존disabled_rulesdeprecation warning만 출력하고BUILD SUCCESSFUL.git diff --check,git diff --cached --check— 출력 없음.- 전체
testDebugUnitTest— 1,221개 중 범위 밖CreatorChannelFanTalkFragmentLayoutTest1건 실패. 일본어 리소스는 팬레터 문구이나 테스트는 기존 응원 문구를 기대하며, 관련 파일은 현재 diff에 없다.
- ViewModel RED —
- 남은 항목: Phase 1 리뷰 blocker 해소 확인.
- 다음 행동: 문서 완료 상태를 반영한 diff를 재리뷰한다.
P1-GATE 재리뷰 — 2026-08-14
- 상태: 완료
- 무엇을: PRD와 계획 문서의 체크박스·검증 기록을 현재 구현 증거와 재대조했다.
- 왜: 초기 리뷰의 유일한 blocker였던 문서 완료 상태 누락을 해소하기 위해서다.
- 어떻게:
- Oracle 재리뷰 — 이전 blocker 해소 및 코드 신규 blocker 없음, 최종
APPROVE. rg -n -- "- \\[ \\]" prd.md plan-task.md— 실제 미완료 체크박스 없음. 템플릿 안내문에 포함된 리터럴 표기만 검색됨.git diff --check,git diff --cached --check— 출력 없음.
- Oracle 재리뷰 — 이전 blocker 해소 및 코드 신규 blocker 없음, 최종
- 남은 항목: 없음.
- 다음 행동: 완료 결과를 보고한다.
범위 밖 테스트 정정 — 2026-08-14
- 상태: 완료
- 무엇을:
CreatorChannelFanTalkFragmentLayoutTest의 일본어 empty message 기대값을 현재values-ja/strings.xml과 맞췄다. - 왜: 전체 unit suite에서 남아 있던 유일한 실패가 테스트 기대값의 오래된 “응원” 문구 때문이었고, 사용자가 테스트 수정 지시를 했다.
- 어떻게:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.fantalk.CreatorChannelFanTalkFragmentLayoutTest" --no-parallel --no-daemon -Pkotlin.incremental=false—BUILD SUCCESSFUL../gradlew :app:testDebugUnitTest --no-parallel --no-daemon -Pkotlin.incremental=false—BUILD SUCCESSFUL.
- 남은 항목: 없음.
- 다음 행동: 완료 결과를 보고한다.
Decision Log
| 날짜 | ID | 상태 | 결정 | 근거 | 영향 Goal/문서 |
|---|---|---|---|---|---|
2026-08-14 |
DEC-001 |
확정 | 차단 성공 후 현재 크리에이터 채널에서 이탈한다. | 사용자 요청과 후속 확인 | P1-T1, P1-T2, PRD CCB-001~005 |
2026-08-14 |
DEC-002 |
확정 | 이전 화면이 없으면 홈인 MainV2Activity로 fallback 이동한다. |
사용자 명시 | P1-T2, PRD CCB-004 |
2026-08-14 |
DEC-003 |
확정 | 이번 턴에서는 문서만 생성하고 구현하지 않는다. | 사용자 명시 | 이 문서 Progress |
발견된 문제
| ID | 심각도 | 상태 | 발견 내용 | 영향 Goal | 처리 계획 |
|---|---|---|---|---|---|
ISSUE-001 |
Medium | 확정 | 현재 차단 성공 흐름은 성공 토스트만 emit하고 채널 화면에 머문다. | P1-T1, P1-T2 |
구현 승인 후 RED test부터 수정한다. |
Verification Log
- 2026-08-14: 문서 작성만 수행했다. 구현 파일과 테스트 파일은 수정하지 않았으므로 Gradle 테스트·compile은 실행하지 않았다. 문서 샘플과 작업 문서 규칙, 기존 관련 문서 검색 결과를 기준으로 새 작업 디렉터리를 생성했다.
- 2026-08-14:
P1-T1,P1-T2를 RED/GREEN으로 완료했다. focused test 통합 실행,compileDebugKotlin,ktlintCheck, diff check는 통과했다. 전체 unit suite는 현재 diff 밖 일본어 팬레터 문구와 기존 테스트 기대값 불일치 1건으로 실패했으며 해당 실패를 범위 밖 blocker로 분리 기록했다. - 2026-08-14: 문서 완료 상태를 갱신한 뒤 Oracle 재리뷰에서 최종
APPROVE를 받았다. PRD와 계획 문서에 실제 미완료 체크박스가 없음을 확인했다. - 2026-08-14: 후속 테스트 정정으로 Fan Talk 일본어 empty message 기대값을 현재 리소스와 맞췄고, focused Fan Talk test와 전체 local unit suite가 통과했다.