# PRD: 크리에이터 채널 차단 후 이탈 ## 문서 정보 | 항목 | 내용 | |---|---| | 문서 상태 | 구현 완료 | | 작성일 | `2026-08-14` | | 최종 수정일 | `2026-08-14` | | 대상 제품 | 크리에이터 채널 사용자 차단 흐름 | | 작성자·결정권자 | 사용자, Sisyphus | | 관련 API Contract | 기존 `CreatorChannelRepository.blockUser(userId, token)` 계약 사용 | | 관련 구현 계획 | `docs/20260814_크리에이터_채널_차단_후_이탈/plan-task.md` | | 관련 review | 없음 | ## 1. Overview 사용자가 크리에이터 채널에서 현재 보고 있는 크리에이터를 차단하면, 차단 성공 후 더 이상 해당 크리에이터 채널 화면에 머물지 않는다. 일반 진입에서는 현재 채널 화면을 종료해 이전 화면으로 돌아가고, 푸시 또는 딥링크처럼 이전 화면이 없는 진입에서는 홈 화면인 `MainV2Activity`로 이동한다. ## 2. Problem Statement - 현재 `CreatorChannelHomeViewModel.blockUser()`는 차단 성공 시 성공 토스트만 emit한다. - 그 결과 사용자가 차단한 크리에이터 채널 화면에 그대로 남아, 차단 이후에도 차단 대상의 채널 콘텐츠를 보는 부자연스러운 상태가 된다. - 딥링크·푸시 진입처럼 이전 화면이 없는 경우 단순 종료만 하면 앱 내 안전한 목적지가 부족할 수 있다. 문제를 해결했다는 판단은 차단 API 성공 후 현재 `CreatorChannelActivity`가 종료되고, task root 상태에서는 `MainV2Activity`가 fallback으로 시작되는 것으로 한다. ## 3. Goals ### 3.1 제품 목표 - 사용자는 차단 성공 후 현재 크리에이터 채널에서 즉시 빠져나간다. - 일반 진입에서는 Android 뒤로가기와 같은 의미로 이전 화면으로 돌아간다. - 이전 화면이 없는 푸시·딥링크 진입에서는 홈인 `MainV2Activity`로 이동한다. ### 3.2 UX 목표 - 기존 차단 확인 모달과 성공 토스트는 유지한다. - API 성공 전에는 화면을 이탈하지 않는다. - API 실패 시에는 현재처럼 오류 토스트만 표시하고 화면에 머문다. ## 4. Non-Goals - 차단 API 계약, 차단 대상 식별자, 서버 응답 형식을 변경하지 않는다. - `MainV2Activity` 자체의 홈 탭 구조나 초기 탭 정책을 변경하지 않는다. - 차단 목록, 차단 해제, 차단된 크리에이터 콘텐츠 필터링 정책은 이번 범위에 포함하지 않는다. - `app/src/androidTest`, 기기·에뮬레이터 조작, 스크린샷 기반 검증은 이번 계획에 포함하지 않는다. ## 5. Target Users and Permissions | 사용자 | 목표 | 주요 작업 | 사용 환경 | |---|---|---|---| | 로그인 사용자 | 원하지 않는 크리에이터를 차단하고 해당 채널에서 벗어난다 | 크리에이터 채널 더보기 > 차단 확인 | Android 앱 | - 인증 주체: 기존 `SharedPreferenceManager.token` 기반 로그인 사용자. - 허용 조건: 기존 크리에이터 채널 차단 액션을 수행할 수 있는 상태. - 거부 조건: API 실패, 네트워크 오류, `CreatorChannelHomeUiState.Content` 미준비 상태. ## 6. 핵심 사용자 흐름 1. 사용자가 `CreatorChannelActivity`에서 더보기 메뉴를 연다. 2. 사용자가 차단을 선택하고 기존 확인 모달에서 확인한다. 3. 앱은 기존 `homeActionDelegate?.blockUser()` 경로로 차단 API를 호출한다. 4. API 성공 시 기존 차단 성공 토스트를 표시하고 현재 크리에이터 채널에서 이탈한다. 5. `CreatorChannelActivity.isTaskRoot == false`이면 `finish()`로 이전 화면에 돌아간다. 6. `CreatorChannelActivity.isTaskRoot == true`이면 `MainV2Activity`를 시작한 뒤 현재 `CreatorChannelActivity`를 종료한다. 7. API 실패 또는 예외 발생 시 기존 unknown error toast를 표시하고 현재 화면에 머문다. ## 7. 정보 구조와 라우팅 ```text CreatorChannelActivity block success, isTaskRoot=false -> finish() -> previous Activity block success, isTaskRoot=true -> MainV2Activity -> finish() ``` - 홈 fallback 대상은 `kr.co.vividnext.sodalive.v2.main.MainV2Activity`다. - fallback은 차단 성공 후 현재 Activity가 task root일 때만 수행한다. ## 8. 기능 요구사항 | ID | 상태 | 요구사항 | 수용 기준 | 계약/Goal 연결 | |---|---|---|---|---| | `CCB-001` | 확정 | 차단 성공은 화면 이탈 이벤트를 발생시킨다. | `CreatorChannelHomeViewModel.blockUser()`가 `ApiResponse.success == true`일 때만 one-shot 차단 성공 이벤트를 emit한다. | `P1-T1` | | `CCB-002` | 확정 | API 성공 전에는 화면 이탈을 시작하지 않는다. | `showUserBlockDialog()`의 확인 콜백은 기존처럼 `homeActionDelegate?.blockUser()`만 호출하며 직접 `finish()` 또는 홈 이동을 하지 않는다. | `P1-T2` | | `CCB-003` | 확정 | 일반 진입에서는 이전 화면으로 돌아간다. | `CreatorChannelActivity.isTaskRoot == false`이면 `finish()`만 호출한다. | `P1-T2` | | `CCB-004` | 확정 | 이전 화면이 없는 진입에서는 홈으로 이동한다. | `CreatorChannelActivity.isTaskRoot == true`이면 `MainV2Activity` intent를 시작하고 현재 Activity를 종료한다. | `P1-T2` | | `CCB-005` | 확정 | 기존 성공/실패 feedback은 유지한다. | 성공 시 `creator_channel_block_success`, 실패·예외 시 `common_error_unknown` toast 흐름을 유지한다. | `P1-T1` | ## 9. UI/UX Expectations - 신규 UI는 없다. - 기존 차단 확인 모달 문구와 버튼은 변경하지 않는다. - 성공 후 이동은 추가 확인 없이 즉시 수행한다. ## 10. API 계약 - 신규 API는 없다. - 기존 호출 경로: `CreatorChannelRepository.blockUser(userId, token)`. - 성공 판단은 기존 `ApiResponse.success`를 따른다. ## 11. 보안과 데이터 취급 - token, URL, 사용자 식별자 등 민감 정보는 로그·Toast·문서 fixture에 추가 노출하지 않는다. - 실패 시 서버 오류 상세를 사용자에게 직접 노출하지 않고 기존 unknown error toast를 유지한다. ## 12. 성공 기준 ### 12.1 기능 수용 기준 - [x] 차단 성공 시 `CreatorChannelHomeViewModel`이 성공 토스트와 차단 성공 이벤트를 emit한다. (`CCB-001`, `CCB-005`) - [x] 차단 실패 또는 예외 시 차단 성공 이벤트가 emit되지 않는다. (`CCB-001`, `CCB-005`) - [x] `CreatorChannelHomeFragment`가 차단 성공 이벤트를 consume한 뒤 `Host`에 전달한다. (`CCB-001`) - [x] `CreatorChannelActivity`가 `isTaskRoot`에 따라 이전 화면 복귀 또는 `MainV2Activity` fallback을 수행한다. (`CCB-003`, `CCB-004`) - [x] 확인 모달의 confirm callback은 API 성공 전 직접 이동하지 않는다. (`CCB-002`) ### 12.2 검증 기준 - [x] `CreatorChannelHomeViewModelTest` focused unit test가 통과한다. - [x] `CreatorChannelActivitySourceTest` focused source contract test가 통과한다. - [x] 변경 파일 compile, ktlint 범위 검증이 통과하거나 기존 전역 blocker를 문서에 기록한다. ## 13. Open Questions | ID | 상태 | 결정 필요 사항 | 현재 결정 | 결정 주체 | 영향 Goal | |---|---|---|---|---|---| | `OQ-001` | 확정 | 뒤로가기 의미 | 현재 `CreatorChannelActivity`에서 빠져나가 이전 화면으로 돌아가는 의미 | 사용자 | `P1-T2` | | `OQ-002` | 확정 | 이전 화면이 없는 경우 fallback | `MainV2Activity`로 이동 | 사용자 | `P1-T2` | ## 14. 요구사항 추적표 | 요구사항 범위 | API Contract | 계획 Phase | Goal | 자동 검증 | 수동 검증 | |---|---|---:|---|---|---| | `CCB-001`, `CCB-005` | 기존 `blockUser` | 1 | `P1-T1` | `CreatorChannelHomeViewModelTest` | 없음 | | `CCB-002~004` | 없음 | 1 | `P1-T2` | `CreatorChannelActivitySourceTest` | 없음 | ## 15. Decision Log | 날짜 | ID | 상태 | 결정 | 근거 | 영향 요구사항·계약·Goal | |---|---|---|---|---|---| | `2026-08-14` | `DEC-001` | 확정 | 차단 성공 후 현재 크리에이터 채널에서 이탈한다. | 사용자 요청 | `CCB-001~005`, `P1-T1`, `P1-T2` | | `2026-08-14` | `DEC-002` | 확정 | 일반 진입은 `finish()`로 이전 화면에 돌아가고, task root는 `MainV2Activity`로 fallback한다. | 사용자 확인 | `CCB-003`, `CCB-004`, `P1-T2` | ## Verification Log - 2026-08-14: 현재 구현 맥락을 확인했다. `CreatorChannelHomeViewModel.blockUser()`는 성공 토스트만 emit하고, `CreatorChannelActivity.showUserBlockDialog()`는 확인 시 `homeActionDelegate?.blockUser()`를 호출한다. 이번 문서 작성 요청에 따라 production code와 test code는 변경하지 않았다. - 2026-08-14: 승인 후 `CreatorChannelHomeViewModel`의 차단 성공 one-shot event, `CreatorChannelHomeFragment.Host` 전달, `CreatorChannelActivity`의 `isTaskRoot` 기반 `MainV2Activity` fallback을 구현했다. ViewModel/source contract RED를 각각 확인한 뒤 최소 구현으로 GREEN 전환했다. - 2026-08-14: focused test 통합 실행, `compileDebugKotlin`, `ktlintCheck`, `git diff --check`가 성공했다. 전체 `testDebugUnitTest`는 1,221개 중 이번 변경과 무관한 `CreatorChannelFanTalkFragmentLayoutTest` 일본어 문구 기대값 불일치 1건으로 실패했으며, 실패 test와 locale string 파일은 현재 diff에 포함되지 않는다. - 2026-08-14: Phase 1 재리뷰에서 이전 문서 정합성 blocker 해소를 확인하고 최종 `APPROVE` 판정을 받았다. - 2026-08-14: 후속으로 `CreatorChannelFanTalkFragmentLayoutTest`의 일본어 empty message 기대값을 현재 `values-ja/strings.xml`의 팬레터 문구와 맞췄다. focused Fan Talk layout test와 전체 `testDebugUnitTest`가 `BUILD SUCCESSFUL`로 통과했다.