diff --git a/docs/20260627_메인_홈_콘텐츠_페이지_로그인_가드/plan-task.md b/docs/20260627_메인_홈_콘텐츠_페이지_로그인_가드/plan-task.md new file mode 100644 index 00000000..49f12333 --- /dev/null +++ b/docs/20260627_메인_홈_콘텐츠_페이지_로그인_가드/plan-task.md @@ -0,0 +1,217 @@ +# 메인 홈/콘텐츠 페이지 로그인 및 성인 콘텐츠 가드 Plan/Task + +## Assumptions +- "메인 홈, 콘텐츠 페이지"는 v2 `HomeMainFragment`, `ContentMainFragment`를 의미한다. +- "이동시 guard"는 두 Fragment에서 발생하는 실제 화면 이동(`startActivity`)을 의미한다. +- 로그인 여부는 기존 코드와 동일하게 `SharedPreferenceManager.token.isBlank()` 기준으로 판단한다. +- 로그인 화면 이동은 기존 `MainV2Activity.showLoginActivity()`를 재사용한다. +- 성인 콘텐츠 이동 여부를 판단할 수 있는 경우에는 로그인 이후 본인인증/성인콘텐츠 설정 가드를 적용한다. +- 접속 국가가 한국인지 여부는 `SharedPreferenceManager.countryCode.ifBlank { "KR" } == "KR"` 기준으로 판단한다. +- 한국 접속자는 `SharedPreferenceManager.isAuth`가 `true`일 때 본인인증 완료로 판단한다. +- 한국 외 접속자는 본인인증 여부와 무관하게 성인 콘텐츠 설정 확인 단계로 진행한다. +- 성인 콘텐츠 표시 설정은 `SharedPreferenceManager.isAdultContentVisible` 기준으로 판단한다. + +## Success Criteria +- v2 메인 전용 이동 guard helper가 추가된다. +- `HomeMainFragment`의 모든 실제 화면 이동이 helper를 통과한다. +- `ContentMainFragment`의 모든 실제 화면 이동이 helper를 통과한다. +- 성인 콘텐츠로 판별 가능한 이동은 login -> country/auth -> adult setting 순서로 helper를 통과한다. +- helper는 `SharedPreferenceManager.countryCode`, `SharedPreferenceManager.isAuth`, `SharedPreferenceManager.isAdultContentVisible`, `ContentSettingsActivity` 이동을 포함한다. +- 레거시 `HomeFragment`, `MainActivity`, `BaseFragment`는 수정하지 않는다. +- 지정된 source test, 컴파일, ktlint, diff whitespace 검증이 통과한다. + +### Phase 1: 현재 이동 지점과 기존 로그인 진입점 확인 +- [ ] **Task 1.1: `HomeMainFragment` 이동 지점 확인** + - 파일: `app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt` + - 확인 대상: + - `openHomeOnAirLive` + - `openFollowingChat` + - `onBannerClick` + - `onRecentActivityClick` + - `onAiCharacterClick` + - `openCreatorProfile` + - `openAudioContentDetail` + - `openPopularCommunityPost` + - 검증 기준: 실제 `startActivity` 호출 지점을 목록화하고, `Unit` placeholder handler는 이동 대상에서 제외한다. + - 검증 기록: + - 2026-06-27: source 확인 결과 위 함수들이 실제 화면 이동 지점이다. `onLiveClick`, `onFollowingSectionMoreClick`, `onFollowingLiveClick`, `onFollowingScheduleClick`, `onFollowingNewsClick`은 현재 `Unit` 또는 이동 없음이므로 이번 가드 적용 대상이 아니다. + +- [ ] **Task 1.2: `ContentMainFragment` 이동 지점 확인** + - 파일: `app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/ContentMainFragment.kt` + - 확인 대상: + - `onBannerClick` + - `openAudioContentDetail` + - `openSeriesDetail` + - `openRankingAudioContentDetail`은 `openAudioContentDetail`로 위임됨 + - 검증 기준: 실제 `startActivity` 호출 지점과 위임 구조를 목록화한다. + - 검증 기록: + - 2026-06-27: source 확인 결과 `onBannerClick`, `openAudioContentDetail`, `openSeriesDetail`이 실제 화면 이동 지점이다. 랭킹/카드 클릭은 이 함수들로 위임되므로 최종 이동 함수에 가드를 적용하면 된다. + +- [ ] **Task 1.3: 기존 로그인 진입점 확인** + - 파일: `app/src/main/java/kr/co/vividnext/sodalive/v2/main/MainV2Activity.kt` + - 확인 대상: `MainV2Activity.showLoginActivity()` + - 검증 기준: `SharedPreferenceManager.token.isBlank()` 조건에서 `LoginActivity`를 시작하는 기존 메서드를 재사용할 수 있다. + - 검증 기록: + - 2026-06-27: `MainV2Activity.showLoginActivity()`는 token blank 조건에서 `LoginActivity`를 시작한다. helper는 이 메서드를 호출하는 방식으로 계획한다. + +- [ ] **Task 1.4: 기존 성인 콘텐츠/본인인증 정책 확인** + - 파일: + - `app/src/main/java/kr/co/vividnext/sodalive/common/AdultContentVisibilityPolicy.kt` + - `app/src/main/java/kr/co/vividnext/sodalive/common/SharedPreferenceManager.kt` + - `app/src/main/java/kr/co/vividnext/sodalive/settings/ContentSettingsActivity.kt` + - 확인 대상: + - `AdultContentVisibilityPolicy.shouldShowAdultRestrictionSetting(countryCode, isAdultContentVisible, isAuth)` + - `SharedPreferenceManager.countryCode` + - `SharedPreferenceManager.isAuth` + - `SharedPreferenceManager.isAdultContentVisible` + - `ContentSettingsActivity` + - `Constants.EXTRA_SHOW_SENSITIVE_CONTENT_GUIDE` + - 검증 기준: v2 helper가 사용할 기존 정책/설정 값을 목록화한다. + - 검증 기록: + - 2026-06-27: `countryCode` 기본값은 `KR`이고, blank country도 `KR`로 취급하는 기존 패턴을 확인했다. `ContentSettingsActivity`는 `Constants.EXTRA_SHOW_SENSITIVE_CONTENT_GUIDE`가 `true`이면 민감 콘텐츠 안내 Toast를 표시한다. + +### Phase 2: v2 메인 전용 이동 guard helper 추가 +- [ ] **Task 2.1: helper source test 추가** + - 파일: `app/src/test/java/kr/co/vividnext/sodalive/v2/main/MainV2LoginGuardSourceTest.kt` + - 검증 기준: + - helper가 `SharedPreferenceManager.token.isBlank()`를 사용한다. + - helper가 `(activity as? MainV2Activity)?.showLoginActivity()`를 사용한다. + - helper가 `SharedPreferenceManager.countryCode.ifBlank { "KR" }`를 사용한다. + - helper가 한국 접속자에 대해 `SharedPreferenceManager.isAuth`를 확인한다. + - helper가 한국 접속 미인증 사용자에게 `SodaDialog` 본인인증 안내를 표시한다. + - helper가 본인인증 진입에 `Auth.auth`를 직접 재사용한다. + - helper가 `SharedPreferenceManager.isAdultContentVisible`를 확인한다. + - helper가 `ContentSettingsActivity`로 이동할 때 `Constants.EXTRA_SHOW_SENSITIVE_CONTENT_GUIDE`를 `true`로 전달한다. + - helper에 레거시 `MainActivity` 의존이 포함되지 않는다. + - 실행 명령: + ```bash + ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.MainV2LoginGuardSourceTest" + ``` + - 기대 결과: 구현 전에는 helper 파일 부재로 실패한다. + +- [ ] **Task 2.2: helper 구현** + - 파일: `app/src/main/java/kr/co/vividnext/sodalive/v2/main/MainV2LoginGuard.kt` + - 구현 방향: + ```kotlin + fun Fragment.ensureMainV2NavigationAllowed( + requiresAdultContentAccess: Boolean = false, + onAllowed: () -> Unit + ) { + if (SharedPreferenceManager.token.isBlank()) { + (activity as? MainV2Activity)?.showLoginActivity() + return + } + + if (requiresAdultContentAccess) { + val isKoreanCountry = SharedPreferenceManager.countryCode.ifBlank { "KR" } == "KR" + if (isKoreanCountry && !SharedPreferenceManager.isAuth) { + showMainV2AuthDialog() + return + } + + if (!SharedPreferenceManager.isAdultContentVisible) { + startActivity( + Intent(requireContext(), ContentSettingsActivity::class.java).apply { + putExtra(Constants.EXTRA_SHOW_SENSITIVE_CONTENT_GUIDE, true) + } + ) + return + } + } + + onAllowed() + } + ``` + - 검증 기준: Task 2.1 source test가 통과한다. + +- [ ] **Task 2.3: 한국 접속 미인증 사용자 처리 방식 확정** + - 파일: + - `app/src/main/java/kr/co/vividnext/sodalive/v2/main/MainV2LoginGuard.kt` + - 필요 시 v2 main 하위 신규 auth guide helper + - 확인 대상: + - 기존 `SodaDialog` + `Auth.auth` 흐름을 v2 helper에서 직접 재사용한다. + - Fragment별 callback 위임 방식은 사용하지 않는다. + - 검증 기준: 레거시 파일 수정 없이 v2 main helper 범위에서 본인인증 안내/진입을 처리한다. + - 검증 기록: + - 2026-06-27: 사용자 결정에 따라 한국 접속 미인증 사용자 본인인증 안내 흐름은 v2 helper에서 직접 재사용하는 것으로 확정했다. + +### Phase 3: HomeMainFragment 이동 지점에 로그인 가드 적용 +- [ ] **Task 3.1: HomeMainFragment source test 추가** + - 파일: `app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragmentLoginGuardSourceTest.kt` + - 검증 기준: + - `HomeMainFragment`가 `ensureMainV2NavigationAllowed`를 import/use 한다. + - Task 1.1의 실제 화면 이동 함수들이 helper를 통해 `startActivity`를 실행한다. + - invalid route/id return 조건은 가드보다 먼저 유지된다. + - 성인 콘텐츠 여부를 판단할 수 없는 홈 이동은 `requiresAdultContentAccess = false` 또는 기본값을 사용한다. + - 실행 명령: + ```bash + ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLoginGuardSourceTest" + ``` + - 기대 결과: 구현 전에는 helper 사용 부재로 실패한다. + +- [ ] **Task 3.2: HomeMainFragment 적용** + - 파일: `app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt` + - 구현 방향: + - `ensureMainV2NavigationAllowed { startActivity(...) }` 형태로 감싼다. + - `route ?: return`, invalid id return은 기존 위치를 유지한다. + - 홈 모델에서 성인 콘텐츠 여부를 판단할 수 있는 필드가 확인되면 `requiresAdultContentAccess = true`를 전달한다. + - 성인 콘텐츠 여부를 판단할 수 없는 이동에는 임의 adult 판정을 추가하지 않는다. + - `BaseFragment`, legacy `MainActivity`, legacy `HomeFragment`는 수정하지 않는다. + - 검증 기준: Task 3.1 source test가 통과한다. + +### Phase 4: ContentMainFragment 이동 지점에 로그인 가드 적용 +- [ ] **Task 4.1: ContentMainFragment source test 추가** + - 파일: `app/src/test/java/kr/co/vividnext/sodalive/v2/main/content/ContentMainFragmentLoginGuardSourceTest.kt` + - 검증 기준: + - `ContentMainFragment`가 `ensureMainV2NavigationAllowed`를 import/use 한다. + - `onBannerClick`, `openAudioContentDetail`, `openSeriesDetail`이 helper를 통해 `startActivity`를 실행한다. + - invalid id return 조건은 가드보다 먼저 유지된다. + - `showAdultBadge` 또는 `isAdult`에서 유래한 성인 콘텐츠 여부가 helper의 `requiresAdultContentAccess`로 전달된다. + - 실행 명령: + ```bash + ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.ContentMainFragmentLoginGuardSourceTest" + ``` + - 기대 결과: 구현 전에는 helper 사용 부재로 실패한다. + +- [ ] **Task 4.2: ContentMainFragment 적용** + - 파일: `app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/ContentMainFragment.kt` + - 구현 방향: + - 최종 이동 함수인 `onBannerClick`, `openAudioContentDetail`, `openSeriesDetail`에서 `ensureMainV2NavigationAllowed { startActivity(...) }`를 사용한다. + - `ContentAudioCardUiModel.showAdultBadge`, `ContentCommentedAudioUiModel.showAdultBadge`, 전체 탭 audio/series item의 `showAdultBadge`를 성인 콘텐츠 가드 입력으로 전달한다. + - 랭킹 아이템이나 배너처럼 성인 콘텐츠 여부를 판단할 수 없는 이동은 로그인 가드만 적용한다. + - 랭킹/카드 클릭 위임 구조는 유지한다. + - 검증 기준: Task 4.1 source test가 통과한다. + +### Phase 5: 통합 검증 +- [ ] **Task 5.1: v2 main source test 실행** + - 실행 명령: + ```bash + ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.*" + ``` + - 기대 결과: v2 main 관련 source/unit test 통과. + +- [ ] **Task 5.2: 컴파일 검증** + - 실행 명령: + ```bash + ./gradlew :app:compileDebugKotlin + ``` + - 기대 결과: Kotlin debug compile 통과. + +- [ ] **Task 5.3: ktlint 검증** + - 실행 명령: + ```bash + ./gradlew :app:ktlintCheck + ``` + - 기대 결과: ktlint 통과. + +- [ ] **Task 5.4: diff whitespace 검증** + - 실행 명령: + ```bash + git diff --check + ``` + - 기대 결과: whitespace error 없음. + +## Verification Log +- 2026-06-27: 사용자 요청에 따라 이번 작업은 문서 생성만 수행한다. source/test/helper 구현 및 Gradle 검증은 아직 실행하지 않는다. +- 2026-06-27: 사용자 요청에 따라 본인인증/성인 콘텐츠 설정 가드를 문서 범위에 추가했다. 구현은 아직 수행하지 않는다. +- 2026-06-27: 한국 접속 미인증 사용자 본인인증 안내 흐름은 v2 helper에서 기존 `SodaDialog` + `Auth.auth` 패턴을 직접 재사용하는 것으로 확정했다. diff --git a/docs/20260627_메인_홈_콘텐츠_페이지_로그인_가드/prd.md b/docs/20260627_메인_홈_콘텐츠_페이지_로그인_가드/prd.md new file mode 100644 index 00000000..3a1c331e --- /dev/null +++ b/docs/20260627_메인_홈_콘텐츠_페이지_로그인_가드/prd.md @@ -0,0 +1,146 @@ +# PRD: 메인 홈/콘텐츠 페이지 로그인 및 성인 콘텐츠 가드 + +## 1. Overview +v2 메인 홈/콘텐츠 페이지에서 상세 화면, 외부 링크, 채팅방 등 화면 이동 전에 로그인 여부와 성인 콘텐츠 접근 가능 여부를 확인하는 가드를 추가한다. + +--- + +## 2. Problem +비로그인 상태 또는 성인 콘텐츠 접근 조건을 만족하지 않은 상태에서도 `HomeMainFragment`와 `ContentMainFragment`의 일부 화면 이동이 바로 진행될 수 있다. + +- 홈 추천/팔로잉/랭킹 영역에서 크리에이터 프로필, 오디오 상세, 커뮤니티 글, 채팅방, 라이브 목록 등으로 이동하기 전에 로그인 확인이 일관되게 적용되지 않는다. +- 콘텐츠 추천/랭킹/전체 영역에서 배너, 오디오 상세, 시리즈 상세 이동 전에 로그인 확인이 일관되게 적용되지 않는다. +- 성인 콘텐츠로 판별 가능한 콘텐츠 이동에서 접속 국가와 본인인증 여부, 성인 콘텐츠 표시 설정이 일관되게 확인되지 않는다. +- v2 메인 화면에서는 기존 `MainV2Activity.showLoginActivity()` 진입점이 있으나 Fragment 이동 지점에서 공통으로 사용되지 않는다. + +--- + +## 3. Goals +- `HomeMainFragment`에서 발생하는 모든 실제 화면 이동 전에 로그인 여부를 확인한다. +- `ContentMainFragment`에서 발생하는 모든 실제 화면 이동 전에 로그인 여부를 확인한다. +- 미로그인 상태에서는 기존 `MainV2Activity.showLoginActivity()`를 호출하고 원래 이동은 실행하지 않는다. +- 로그인 상태에서는 기존 이동 동작과 Intent extra를 유지한다. +- 성인 콘텐츠로 판별 가능한 이동에서는 `SharedPreferenceManager.countryCode`, `SharedPreferenceManager.isAuth`, `SharedPreferenceManager.isAdultContentVisible`를 기준으로 접근 가능 여부를 확인한다. +- 한국 접속자(`countryCode`가 blank이거나 `KR`)는 본인인증이 완료되어야 성인 콘텐츠 이동을 계속할 수 있다. +- 성인 콘텐츠 표시 설정이 꺼져 있으면 `ContentSettingsActivity`로 이동하고 원래 이동은 실행하지 않는다. +- v2 메인 Fragment 범위에만 영향을 주는 작은 helper 또는 guard 계층으로 구현한다. + +--- + +## 4. Non-Goals +- 본인인증 SDK 또는 본인인증 서버 API의 동작 변경은 제외한다. +- 성인 콘텐츠 설정 화면 UI 변경은 제외한다. +- 레거시 `HomeFragment`, `MainActivity`, `BaseFragment` 수정은 제외한다. +- API, DTO, DB, 서버 스키마 변경은 제외한다. +- 로그인 화면 자체의 UX 또는 인증 플로우 변경은 제외한다. + +--- + +## 5. Target Users +- v2 메인 홈/콘텐츠 페이지를 사용하는 비로그인 사용자 +- v2 메인 홈/콘텐츠 페이지에서 콘텐츠 상세, 크리에이터, 채팅, 배너 링크로 이동하는 로그인 사용자 + +--- + +## 6. User Stories +- 비로그인 사용자는 홈/콘텐츠 페이지에서 상세 화면으로 이동하려 할 때 로그인 화면으로 안내받고 싶다. +- 한국 접속 미인증 사용자는 성인 콘텐츠로 이동하려 할 때 본인인증이 필요하다는 안내를 받고 싶다. +- 성인 콘텐츠 표시 설정이 꺼진 사용자는 성인 콘텐츠로 이동하려 할 때 설정 화면으로 안내받고 싶다. +- 로그인 사용자는 기존처럼 탭, 카드, 배너, 랭킹 아이템을 눌렀을 때 해당 화면으로 이동하고 싶다. +- 개발자는 v2 메인 화면의 이동 가드를 레거시 공통 코드 변경 없이 확인하고 유지보수하고 싶다. + +--- + +## 7. Core Features + +### Feature A: v2 메인 Fragment 전용 이동 가드 +`kr.co.vividnext.sodalive.v2.main` 하위에 v2 메인 Fragment에서만 사용하는 이동 guard helper를 둔다. + +#### Requirements +- `SharedPreferenceManager.token.isBlank()`를 로그인 여부 기준으로 사용한다. +- token이 blank이면 `(activity as? MainV2Activity)?.showLoginActivity()`를 호출하고 원래 이동 callback을 실행하지 않는다. +- token이 blank가 아니고 성인 콘텐츠 가드 대상이 아니면 전달된 이동 callback을 실행한다. +- 성인 콘텐츠 가드 대상이면 접속 국가와 본인인증 여부를 먼저 확인한다. +- `countryCode.ifBlank { "KR" } == "KR"`이면 한국 접속자로 판단한다. +- 한국 접속자이고 `SharedPreferenceManager.isAuth == false`이면 원래 이동 callback을 실행하지 않는다. +- 한국 외 접속자는 본인인증 여부와 무관하게 성인 콘텐츠 설정 확인 단계로 진행한다. +- `SharedPreferenceManager.isAdultContentVisible == false`이면 `ContentSettingsActivity`로 이동하고 원래 이동 callback을 실행하지 않는다. +- `ContentSettingsActivity` 이동 시 기존 패턴과 동일하게 `Constants.EXTRA_SHOW_SENSITIVE_CONTENT_GUIDE`를 `true`로 전달한다. +- 기존 `AdultContentVisibilityPolicy`와 `ContentSettingsActivity`의 country/auth 정책을 확인해 중복 또는 충돌 없이 사용한다. +- helper에는 레거시 `MainActivity` 로직을 넣지 않는다. + +#### Edge Cases +- Fragment가 `MainV2Activity`에 붙어 있지 않은 경우에는 안전하게 login call을 생략하고 이동도 실행하지 않는다. +- 이미 유효성 검사를 통해 invalid id를 return하는 이동 지점은 기존 return 조건을 유지한다. +- 성인 콘텐츠 여부를 판단할 수 없는 이동은 로그인 가드만 적용한다. + +### Feature B: HomeMainFragment 이동 가드 적용 +`HomeMainFragment`의 실제 `startActivity` 이동 지점을 helper로 감싼다. + +#### Requirements +- `openHomeOnAirLive` +- `openFollowingChat` +- `onBannerClick` +- `onRecentActivityClick` +- `onAiCharacterClick` +- `openCreatorProfile` +- `openAudioContentDetail` +- `openPopularCommunityPost` +- 위 이동 지점에 로그인 가드를 적용한다. +- 성인 콘텐츠 여부를 판단할 수 있는 홈 이동 지점이 있으면 성인 콘텐츠 가드도 함께 적용한다. +- 현재 `Unit`으로 남아 있는 클릭 handler는 화면 이동이 아니므로 신규 이동을 만들지 않는다. + +#### Edge Cases +- route 또는 id가 유효하지 않아 기존에 return하던 경우에는 로그인 가드 호출 전에 그대로 return한다. +- `ChatRoomType.AI`, `ChatRoomType.DM` 분기별 기존 Intent 생성을 유지한다. +- 현재 홈 v2 모델에 성인 콘텐츠 여부 필드가 없는 이동은 로그인 가드만 적용하고, 임의로 adult 판정을 만들지 않는다. + +### Feature C: ContentMainFragment 이동 가드 적용 +`ContentMainFragment`의 실제 `startActivity` 이동 지점을 helper로 감싼다. + +#### Requirements +- `onBannerClick` +- `openAudioContentDetail` +- `openSeriesDetail` +- 랭킹/카드 클릭은 위 함수로 위임되는 구조를 유지한다. +- 기존 Intent extra(`Constants.EXTRA_AUDIO_CONTENT_ID`, `Constants.EXTRA_SERIES_ID`)를 유지한다. +- `ContentAudioCardUiModel`, `ContentCommentedAudioUiModel`, `MainContentAllTab` audio/series model처럼 성인 배지 또는 `isAdult`에서 유래한 값을 가진 이동은 성인 콘텐츠 가드 대상이다. +- 배너 이동은 성인 콘텐츠 여부를 판단할 수 있는 데이터가 없으면 로그인 가드만 적용한다. + +#### Edge Cases +- `audioContentId <= 0L`, `seriesId <= 0L`, invalid ranking content id는 기존처럼 무시한다. +- 랭킹 아이템에서 성인 콘텐츠 여부를 판단할 수 없는 경우에는 로그인 가드만 적용하고, 상세 화면 자체 정책에 추가 판단을 위임한다. + +--- + +## 8. UX / UI Expectations +- 미로그인 사용자는 별도 Toast 없이 기존 로그인 화면으로 이동한다. +- 한국 접속 미인증 사용자는 성인 콘텐츠 이동 시 기존 앱 패턴과 동일한 본인인증 안내를 받는다. +- 성인 콘텐츠 표시 설정이 꺼진 사용자는 `ContentSettingsActivity`로 이동하며 민감 콘텐츠 안내 Toast가 표시될 수 있다. +- 로그인 사용자의 화면 이동 UX는 기존과 동일하다. +- 탭 전환, 리스트 렌더링, 정렬 팝업, pagination 등 화면 이동이 아닌 동작은 로그인 가드 대상이 아니다. + +--- + +## 9. Technical Constraints +- 신규 helper는 `kr.co.vividnext.sodalive.v2.main` 패키지 하위에 작성한다. +- `BaseFragment`, 레거시 `MainActivity`, 레거시 `HomeFragment`는 수정하지 않는다. +- 기존 `MainV2Activity.showLoginActivity()`를 재사용한다. +- 성인 콘텐츠 설정 이동은 기존 `ContentSettingsActivity`와 `Constants.EXTRA_SHOW_SENSITIVE_CONTENT_GUIDE`를 재사용한다. +- 본인인증 가능 여부 판단은 `SharedPreferenceManager.countryCode.ifBlank { "KR" }`, `SharedPreferenceManager.isAuth` 기준을 따른다. +- 한국 접속 미인증 사용자 본인인증 안내 흐름은 v2 helper에서 기존 `SodaDialog` + `Auth.auth` 패턴을 직접 재사용한다. +- 성인 콘텐츠 설정 여부 판단은 `SharedPreferenceManager.isAdultContentVisible` 기준을 따른다. +- 구현 시 source test로 helper 사용 여부, login/auth/adult-setting 분기, 레거시 파일 미수정 여부를 고정한다. +- Android Gradle 명령은 저장소 루트에서 실행한다. + +--- + +## 10. Metrics +- 구현 후 `HomeMainFragment`와 `ContentMainFragment`의 모든 실제 `startActivity` 이동 지점이 v2 메인 이동 guard helper를 통과한다. +- 성인 콘텐츠로 판별 가능한 이동은 login -> country/auth -> adult setting 순서로 guard를 통과한다. +- source test가 helper 사용, token 기준, `MainV2Activity.showLoginActivity()` 호출, `countryCode`/`isAuth`/`isAdultContentVisible` 기준, `ContentSettingsActivity` 이동을 검증한다. + +--- + +## 11. Open Questions +- 없음. 한국 접속 미인증 사용자 본인인증 안내 흐름은 v2 helper에서 기존 `SodaDialog` + `Auth.auth` 패턴을 직접 재사용한다.