54 KiB
V2 공통 접근 가드와 도메인 액션 Plan/Task
Assumptions
- 작업 범위는
kr.co.vividnext.sodalive.v2하위 신규/기존 코드와 이를 조립하는AppDI.kt로 제한한다. - 화면별 최초 집계 API와 Response는 feature가 계속 소유할 수 있다.
- 공통화 대상은 최소 두 호출부에서 반복되거나 모든 화면에서 동일해야 하는 정책과 사용자 행동이다.
- 기존 UX, API, Intent extra, Activity result, 화면 새로고침 동작을 보존한다.
- 직접적인 하위 Activity 결과는
ActivityResult -> 명시적 도메인 결과 -> feature 단일 handler를 기본 전달 방식으로 사용한다. - 현재 화면 안에서 Action/Repository가 직접 반환하는 결과에는 불필요하게
ActivityResult를 도입하지 않고 같은 handler를 호출한다. SharedFlow/observer는 Activity 밖의 독립 소비자가 다수 존재하거나 백그라운드 변경 전파 요구가 확인될 때만 사용한다.- 레거시 기능은 수정하지 않고
v2adapter/wrapper에서 호출한다. - 구현은 Access부터 도메인별 Phase로 진행하며 각 Phase를 독립적으로 검증한다.
- 모든 도메인에 동일한 형식의 클래스를 강제하지 않고 실제 중복과 정책이 확인된 최소 단위만 추출한다.
Success Criteria
v2로그인/성인 접근 판단의 단일 소유자가 존재한다.- Activity와 Fragment가 동일한 Access 공개 진입점을 사용한다.
- 합의된 도메인별 반복 동작이 단일 Action 공개 진입점을 사용한다.
- Action 입력은 화면 전용 UI model/DTO가 아닌 ID, 값 또는 명시적 command다.
- 화면별 최초 query와 UI composition은 유지된다.
- Community mutation은 명시적 변경 결과를 반환하고 Creator Channel의 단일 composition handler가 Home/Community projection 갱신을 결정한다.
- Activity result를 사용하는 도메인 흐름은 raw result를 화면마다 해석하지 않고 명시적 결과와 단일 handler를 사용한다.
- feature 간 직접 Activity/Coordinator 의존은 공통 Action 또는 navigation 계약으로 대체된다.
- 각 Phase의 테스트, 컴파일, ktlint, whitespace 검증 결과가 문서에 누적된다.
Phase 0: 기준선과 Action 카탈로그 확정
-
Task 0.1:
v2구조와 중복 접근 구현 기준선 조사- 파일:
app/src/main/java/kr/co/vividnext/sodalive/v2/app/src/test/java/kr/co/vividnext/sodalive/v2/
- 확인 내용:
- 운영 Kotlin 258개, 약 25,294줄
- 테스트 Kotlin 127개, 약 23,809줄
SharedPreferenceManager직접 참조 29개 파일, 92곳- API 11개, Repository 11개, ViewModel 22개, Activity/Fragment 20개
- 검증 기준: 전체 재배치가 아닌 반복 동작별 점진 전환이 필요한 근거를 기록한다.
- 검증 기록:
- 2026-07-14:
find,wc,rg로v2운영/테스트 코드 규모와 직접 의존을 확인했다.widget64개는 UI 재사용 컴포넌트이므로 초기 도메인 Action 전환 대상에서 제외한다.
- 2026-07-14:
- 파일:
-
Task 0.2: 초기 Action 카탈로그 작성
- 파일:
docs/20260714_V2_공통_접근_가드와_도메인_액션/prd.mddocs/20260714_V2_공통_접근_가드와_도메인_액션/plan-task.md
- 작업: Access, Content, Live, Creator, Community, Chat의 초기 공통 동작과 호출 화면을 기록한다.
- 검증 기준: 화면별 집계 query와 공통 action을 구분하고, FanTalk/Donation/Schedule은 실제 재사용 수요 확인 전 추출 대상에서 제외한다.
- 검증 기록:
- 2026-07-14: 기존 호출부 조사 결과 Access, 오디오/시리즈 진입, Live 상세/입장, Creator Channel 진입, Community 상세, Chat/DM 진입을 초기 후보로 확정했다.
- 파일:
-
Task 0.3: 구현 직전 호출부 및 동작 차이 상세 목록 확정
- 파일:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/app/src/main/java/kr/co/vividnext/sodalive/v2/creator/app/src/main/java/kr/co/vividnext/sodalive/v2/live/app/src/main/java/kr/co/vividnext/sodalive/mypage/MyPageFragment.kt(호출부 확인만 수행하고 수정하지 않음)docs/20260714_V2_공통_접근_가드와_도메인_액션/plan-task.md
- 작업: 각 Action별 호출 함수, 접근 조건, Intent extra, Activity result, callback/refresh 차이를 기록한다.
- 검증 기준:
- 공통 계약으로 보존할 동작과 화면에 남길 후처리가 구분된다.
- Activity result 흐름은 adapter에서 만들 명시적 결과와 feature 단일 handler 후보가 기록된다.
- observer가 필요한 흐름은 Activity 밖의 소비자 수, lifecycle, replay 요구사항이 함께 기록된다.
- 확인 결과:
- Access:
HomeMainFragment,ContentMainFragment,ChatMainFragment는 기존ensureMainV2NavigationAllowed를 사용했고,CreatorChannelActivity,HomeOnAirLiveActivity는 자체ensureLoginAndAdultAuth를 중복 구현하고 있었다. - Access:
MainV2Activity는 chat tab, audio notification route처럼 로그인 차단 UX가 필요한 navigation guard와 push token/member/deeplink 초기화처럼 부수효과 없이 허용 여부만 확인하는 흐름이 섞여 있었다. Phase 1에서는 두 용도를ensureV2Access(AccessRequirement.Login)와isV2AccessAllowed(AccessRequirement.Login)로 분리해 기존 route 처리 순서와 invalid audio content id 반환 계약을 유지한다. - Content:
ContentMainFragment의 오디오/시리즈 상세 진입은 ID 검사 후 판단 가능한 성인 여부를 guard에 전달하며, banner/overview/전체 탭 이동은 login guard만 필요하다. - Live:
HomeMainFragment와HomeOnAirLiveActivity는 로그인 후 room detail을 조회하고, detail의isAdult로 성인 Access를 다시 검사한다. Creator Channel 현재 라이브도 동일 입장 흐름을 사용한다. - Creator/Community:
CreatorChannelActivity는 Activity 자체 진입 로그인 guard와 Community/FanTalk/Live ActivityResult refresh를 소유한다. Phase 1에서는 result adapter를 만들지 않고 기존 launcher/refresh를 유지한다. - Chat: title bar 및 Home following chat은 login guard 후 기존 AI/DM intent helper를 사용한다. DM room result adapter나 observer 변경은 Phase 5 대상으로 유지한다.
- Legacy MyPage:
MyPageFragment.showLoginActivity는 실행 Activity가MainV2Activity이면 공개showLoginActivity()를 호출하므로 해당 호환 진입점을 유지해야 한다.
- Access:
- 파일:
상세 호출부 및 계약
| Action 후보 | 호출부 | Access 조건 | Intent extra / 입력 | Result / callback 차이 | Phase 1 처리 |
|---|---|---|---|---|---|
| Login/Adult Access | HomeMainFragment.openWithLoginGuard, openFollowingTab, title bar cash/search/bell, ContentMainFragment title/overview/banner/detail, ChatMainFragment title bar, CreatorChannelActivity community/FanTalk/live, HomeOnAirLiveActivity live entry |
Login 또는 forAdultContent(isAdult) |
화면별 기존 Activity/Intent helper 그대로 사용 | 화면별 후처리는 호출부에 유지 | ensureV2Access로 전환하고 정책 판단만 공통화 |
| MainV2 chat tab | MainV2Activity.selectChatTabWithLoginGuard, openChatTab, initial chat filter |
Login | EXTRA_CHAT_FILTER는 기존 consume/open 흐름 유지 |
탭 전환은 허용 시에만 viewModel.clickTab(CHAT) |
ensureV2Access(Login) 사용, legacy showLoginActivity()는 guard 위임만 유지 |
| Legacy MyPage login bridge | MyPageFragment.showLoginActivity -> MainV2Activity.showLoginActivity |
Login | MainV2Activity.intent.extras |
레거시 Activity 타입 분기와 로그인 화면 이동 계약 유지 | MainV2Activity.showLoginActivity()를 유지하고 ensureV2Access(Login)에 위임 |
| MainV2 deeplink/audio notification | onCreate, onNewIntent, handleAudioNotificationRoute, executeDeeplink |
Login 허용 여부 확인 또는 Login guard | EXTRA_DATA, deep_link, EXTRA_AUDIO_NOTIFICATION_ROUTE, EXTRA_AUDIO_CONTENT_ID |
audio route가 먼저 소비되고 invalid audio content id는 false 반환해 기존 후속 처리 가능 |
route 순서와 반환 계약 보존, side-effect 없는 분기는 isV2AccessAllowed(Login) 사용 |
| Content 상세/전체/overview | ContentMainFragment.openAudioContentDetail, openSeriesDetail, openContentOverview, openContentAllTab |
Login 또는 콘텐츠 성인 여부에 따른 AdultContent | Constants.EXTRA_AUDIO_CONTENT_ID, series id, ContentOverviewType, MainContentAllType, ContentSort |
Activity result 없음, 전체 탭 이동은 MainV2Activity.openContentAllTab 호출 |
Phase 1에서는 guard만 공통화, Content Action 계약은 Phase 2에서 구현 |
| Live entry | HomeMainFragment.onLiveClick, HomeOnAirLiveActivity.enterLiveRoom, CreatorChannelActivity.onCreatorChannelCurrentLiveClicked |
Login 후 room detail의 isAdult로 AdultContent |
room id/live id, room detail | 기존 liveCoordinator.enterLiveRoom 및 on-air 목록 refresh/상태는 호출부에 유지 |
Phase 1에서는 중복 adult guard 제거, Live Action은 Phase 3 |
| Creator / Community | CreatorChannelActivity.onCreatorChannelCommunityPostClicked, Home creator/profile/community 진입 |
Login | creator id, post id, existing newIntent |
Creator Channel의 Home/Community/FanTalk refresh 조합과 launcher는 Activity 소유 유지 | Phase 1에서는 login guard만 공통화, result adapter는 Phase 4 |
| Chat / DM | HomeMainFragment.openFollowingChat, title bar search/cash, MainV2Activity chat route |
Login | AI room id, DM room id, existing chat intent helpers | DM room result adapter/observer 없음, 기존 Activity 전환만 수행 | Phase 1에서는 login guard만 공통화, Chat Action은 Phase 5 |
observer 판단
- Phase 1 Access는 one-shot UI navigation/action 차단이므로 전역 observer나 EventBus를 추가하지 않는다.
- ActivityResult/refresh가 있는 Creator Channel Community/FanTalk는 기존 launcher와 Activity 내부 composition handler 후보를 Phase 4에서 정리한다.
- Live room entry는 detail 조회 후 접근 판단이 필요하므로 repository/result observer가 아니라 호출부 callback 조합을 유지하고 Phase 3에서 Action 계약을 분리한다.
검증 기록
- 2026-07-14:
rg와explore조사로 Access, Content, Live, Creator, Community, Chat 후보의 호출부와 차이를 확정했다. Phase 1 구현 범위는 Access로 제한하고, Content 이후 도메인 Action은 카탈로그 상태로 유지한다. - 2026-07-14: 리뷰 보완으로
MainV2Activity의 직접isLoggedIn()/showLoginActivity()소유 여부를 재확인했고, 로그인 UX 실행이 필요한 경로와 단순 허용 여부 확인 경로를 분리해 공통 Access 정책으로 이관하기로 확정했다. - 2026-07-14: 리뷰 게이트 보완으로 Action 후보별 호출 함수, Access 조건, Intent 입력, Result/callback 차이, observer 판단을 표로 추가해 Task 0.3 검증 기준을 충족하도록 문서를 보강했다.
- 2026-07-14: Phase 0/1 리뷰 답변에 따라 레거시
MyPageFragment에서MainV2Activity.showLoginActivity()를 호출하는 호환 경로를 상세 호출부 표에 추가했다. 레거시 파일은 수정하지 않았다.
Phase 1: V2 공통 Access 정책과 실행기
-
Task 1.1: Access 판단 단위 테스트 작성
- 생성 예정 파일:
app/src/test/java/kr/co/vividnext/sodalive/v2/access/AccessPolicyTest.kt
- 검증 대상:
- 로그인 필요 요구사항의 로그인/미로그인 결과
- 성인 콘텐츠 요구사항의 미로그인 결과
- 국내 미인증 사용자의 본인인증 필요 결과
- 국외 사용자의 본인인증 생략
- 성인 콘텐츠 표시 설정 비활성 결과
- 모든 조건 충족 시 허용 결과
- 실행 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.access.AccessPolicyTest" - 기대 결과: 구현 전 RED, 구현 후 GREEN.
- 검증 기록:
- 2026-07-14: 테스트를 먼저 추가한 뒤
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.access.AccessPolicyTest"를 실행해AccessPolicy,AccessRequirement,AccessDecision,AccessState미정의 컴파일 오류로 RED를 확인했다.
- 2026-07-14: 테스트를 먼저 추가한 뒤
- 생성 예정 파일:
-
Task 1.2: Access 입력·출력 계약과 순수 정책 구현
- 생성 예정 파일:
app/src/main/java/kr/co/vividnext/sodalive/v2/access/AccessRequirement.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/access/AccessDecision.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/access/AccessState.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/access/AccessPolicy.kt
- 작업: 로그인, 국가/본인인증, 성인 콘텐츠 표시 설정을 명시적 입력과 결과로 판단한다.
- 검증 기준: Android, Activity, Fragment, Dialog, Retrofit 의존 없이 Task 1.1 테스트가 통과한다.
- 검증 기록:
- 2026-07-14:
AccessRequirement,AccessDecision,AccessState,AccessPolicy를 추가하고 같은 단일 테스트 명령을 재실행해 GREEN을 확인했다.
- 2026-07-14:
- 생성 예정 파일:
-
Task 1.3: Activity/Fragment 공용 Access 실행기 구현
- 생성 예정 파일:
app/src/main/java/kr/co/vividnext/sodalive/v2/access/V2AccessGuard.kt
- 수정 가능 파일:
app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt
- 작업:
AccessDecision을 로그인, 본인인증, 콘텐츠 설정 UX로 연결한다.- 기존
LoginActivity,V2ModalDialog,Auth.auth,MyPageViewModel.authVerify,ContentSettingsActivity를 재사용한다. - Activity와 Fragment에서 같은 공개 함수를 호출할 수 있게 한다.
- 검증 기준:
Allowed에서만 원래 action을 한 번 실행한다.- 거부 결과에서 원래 action을 실행하지 않는다.
- 기존 Intent flag/extra와 인증 완료 후 흐름을 유지한다.
- 검증 기록:
- 2026-07-14:
V2AccessGuard를 추가해 Activity/Fragment 공용ensureV2Access를 제공하고, 기존LoginActivityextra/flag,V2ModalDialog,Auth.auth,MyPageViewModel.authVerify,SplashActivity,ContentSettingsActivityextra 계약을 source test로 고정했다. - 2026-07-14:
MainV2Activity의 초기화/조건부 실행처럼 로그인 UX를 띄우지 않아야 하는 경로를 위해 같은AccessPolicy와AccessStateProvider를 사용하는isV2AccessAllowed를 추가했다. - 2026-07-14: 리뷰 보완으로 기존
MainV2Activity.isLoggedIn()의token.isNotBlank() && token.length > 10기준을AccessPolicy에 보존하고, 10자/11자/공백 토큰 경계 테스트를 추가했다. - 2026-07-14: 레거시
MyPageFragment본문을 수정하지 않고 기존MainV2Activity.showLoginActivity()호출 계약을 유지하기 위해MainV2Activity에 얇은 호환 메서드를 남기고 내부에서ensureV2Access(AccessRequirement.Login)을 호출하게 했다. - 2026-07-14: 사용자 확인 결과 현재
token.length > 10기준은 실제 토큰 계약에서 동작 변경을 만들지 않으므로 추가 코드 변경 없이 유지한다.
- 2026-07-14:
- 생성 예정 파일:
-
Task 1.4: 기존 Access 구현을 공통 실행기로 전환
- 수정 예정 파일:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/MainV2LoginGuard.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/main/MainV2Activity.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/main/content/ContentMainFragment.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/main/chat/ChatMainFragment.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/live/onair/HomeOnAirLiveActivity.kt
- 작업:
- 기존 호출부를
V2AccessGuard로 전환한다. - 화면 진입 guard와 클릭 action guard의 기존 종료/후처리 차이를 보존한다.
- 모든 호출부 전환 후 중복
ensureLoginAndAdultAuth구현을 제거한다.
- 기존 호출부를
- 검증 기준:
CreatorChannelActivity,HomeOnAirLiveActivity에 별도 로그인/성인 판단 함수가 남지 않는다.- 대상 클릭 handler에 직접 token 조건문이 남지 않는다.
- 검증 기록:
- 2026-07-14:
HomeMainFragment,ContentMainFragment,ChatMainFragment,CreatorChannelActivity,HomeOnAirLiveActivity호출부를ensureV2Access와AccessRequirement로 전환했다.MainV2LoginGuard.kt와 Activity별ensureLoginAndAdultAuth구현을 제거했다. - 2026-07-14:
MainV2Activity의 chat tab, audio notification route는ensureV2Access(AccessRequirement.Login)로 전환하고, deeplink 실행 전 조건, push token update, member info 조회 등은isV2AccessAllowed(AccessRequirement.Login)로 전환했다. Activity 내부 직접isLoggedIn()구현은 제거했고, 기존 외부 호출 호환용showLoginActivity()는 공통 guard 위임만 수행한다. - 2026-07-14:
rg -n "ensureMainV2NavigationAllowed|ensureLoginAndAdultAuth" app/src/main/java/kr/co/vividnext/sodalive/v2 app/src/test/java/kr/co/vividnext/sodalive/v2 --glob '*.kt'결과 production 잔존은 없고, source test의 제거 확인 assertion만 남았다. - 2026-07-14: 대상 UI 파일의
SharedPreferenceManager.(token|countryCode|isAuth|isAdultContentVisible)검색 결과 Creator Channel의 API auth header 생성 함수만 남았고, 접근 정책 직접 판단은 제거됐다.
- 2026-07-14:
- 수정 예정 파일:
-
Task 1.5: 기존 Access source test를 새 계약에 맞게 전환
- 수정 예정 파일:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/MainV2LoginGuardSourceTest.ktapp/src/test/java/kr/co/vividnext/sodalive/v2/main/MainV2ActivitySourceTest.ktapp/src/test/java/kr/co/vividnext/sodalive/v2/main/MainV2AudioNotificationRouteSourceTest.ktapp/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragmentLoginGuardSourceTest.ktapp/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainTitleBarActionSourceTest.ktapp/src/test/java/kr/co/vividnext/sodalive/v2/main/content/ContentMainFragmentLoginGuardSourceTest.ktapp/src/test/java/kr/co/vividnext/sodalive/v2/main/content/ContentMainFragmentSourceTest.ktapp/src/test/java/kr/co/vividnext/sodalive/v2/main/content/ContentMainTitleBarActionSourceTest.ktapp/src/test/java/kr/co/vividnext/sodalive/v2/main/chat/ChatMainTitleBarActionSourceTest.ktapp/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.kt
- 작업: 이전 함수명 고정 assertion을 새 공통 Access 사용 및 기존 UX 보존 검증으로 최소 수정한다.
- 검증 기준: 정책은
AccessPolicyTest, 호출 연결은 필요한 source test가 담당한다. - 검증 기록:
- 2026-07-14:
MainV2LoginGuardSourceTest, Home/Content/Chat title bar source test, Home/Content login guard source test,CreatorChannelActivitySourceTest의 Access 관련 assertion을 새V2AccessGuard계약 기준으로 전환했다. - 2026-07-14:
MainV2ActivitySourceTest와MainV2AudioNotificationRouteSourceTest를 새ensureV2Access/isV2AccessAllowed경계 기준으로 갱신하고,MainV2Activity에 직접isLoggedIn()판단 함수가 남지 않음을 고정했다. - 2026-07-14:
MainV2LoginGuardSourceTest에MainV2Activity.showLoginActivity()가 기존 호출명은 유지하되ensureV2Access(AccessRequirement.Login)으로 위임하는지 확인하는 assertion을 추가했다.
- 2026-07-14:
- 수정 예정 파일:
-
Task 1.6: Access Phase 검증 및 문서 반영
- 파일:
docs/agent-guides/build-test-style.mddocs/20260714_V2_공통_접근_가드와_도메인_액션/plan-task.md
- 실행 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.access.*" ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.*" ./gradlew :app:compileDebugKotlin ./gradlew :app:ktlintCheck --rerun-tasks git diff --check HEAD - 기대 결과: 신규 Access 테스트와 영향받은 기존 테스트, 컴파일, whitespace 검증이 통과한다.
ktlintCheck는 전체 기준선을 재실행하고, 저장소 기존 위반으로 실패하면 Phase 1 변경 파일에 신규 위반이 없음을 완료 gate로 확인한다. - 검증 기록:
- 2026-07-14: Access 관련 좁은 회귀 명령
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.access.*" --tests "kr.co.vividnext.sodalive.v2.main.*" --tests "kr.co.vividnext.sodalive.v2.live.onair.*" --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest.현재 라이브 카드는 동일한 enterLiveRoom 플로우로 입장한다" --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest.커뮤니티 게시물 클릭 source는 상세 Activity newIntent로 진입하고 invalid postId를 무시한다" --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest.FanTalk fixed plus source는 Activity overlay와 write result refresh 계약을 연결한다" --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest.FanTalk item click source는 owner gate와 상세 ActivityResult refresh를 연결한다"가BUILD SUCCESSFUL로 통과했다. - 2026-07-14: 더 넓은 관련 테스트 묶음은 497개 중
CreatorChannelActivitySourceTest > 팬Talk 섹션은 Figma ListComment layout과 bind로 렌더링한다1개가@drawable/ic_chevron_down_whitesource assertion으로 실패했다. Access 변경 파일과 무관한 기존 FanTalk layout assertion으로 확인해 별도 관찰로 남긴다. - 2026-07-14:
./gradlew :app:compileDebugKotlin은BUILD SUCCESSFUL로 통과했다. - 2026-07-14:
./gradlew :app:ktlintCheck는 이번 변경과 무관한app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingFragmentSourceTest.kt:118-120기존 max line length/argument wrapping 위반으로 실패했다. 해당 파일에는 이번 diff가 없음을git diff -- app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingFragmentSourceTest.kt로 확인했다. - 2026-07-14:
git diff --check는 whitespace 오류 없이 통과했다. - 2026-07-14:
MainV2LoginGuardSourceTest의 신규 adapter assertion line length를 수정한 뒤./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.access.*" --tests "kr.co.vividnext.sodalive.v2.main.*" && ./gradlew :app:compileDebugKotlin && ./gradlew :app:ktlintCheck && git diff --check를 재실행해 모두BUILD SUCCESSFUL또는 무출력 통과를 확인했다. - 2026-07-14: 리뷰 게이트에서
token.isNotBlank() && token.length > 10보존과mypageadapter 제거가 차단 이슈로 확인되어,AccessPolicy로그인 기준과MainV2Activity.showLoginActivity()호환 메서드 위임 방식으로 보완했다. - 2026-07-14: 보완 후
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.access.*" --tests "kr.co.vividnext.sodalive.v2.main.*" && ./gradlew :app:compileDebugKotlin && ./gradlew :app:ktlintCheck && git diff --check를 재실행해 모두BUILD SUCCESSFUL또는 무출력 통과를 확인했다. - 2026-07-14: 추가 리뷰에서 11자 이상 공백 토큰이 허용되는 회귀를 확인해
AccessPolicy에isNotBlank()조건을 복원하고 공백 토큰 회귀 테스트와 PRD 문구를 보강했다. - 2026-07-14: Kotlin LSP 진단은 환경에
kotlin-lsp가 설치되어 있지 않아 실행할 수 없었고, Gradle compile/test로 대체 검증했다.
- 2026-07-14: Access 관련 좁은 회귀 명령
- 파일:
-
Task 1.7: 리뷰 보완으로 Access 실행 계약과 source test 범위 강화
- 생성 파일:
app/src/test/java/kr/co/vividnext/sodalive/v2/access/V2AccessGuardTest.kt
- 수정 파일:
app/src/main/java/kr/co/vividnext/sodalive/v2/access/V2AccessGuard.ktapp/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.ktdocs/agent-guides/build-test-style.mddocs/20260714_V2_공통_접근_가드와_도메인_액션/plan-task.md
- 작업:
AccessDecision실행 분기를 Android 비의존 함수로 분리해Allowedcallback과 거부 UX callback 실행 횟수를 실제 입력·출력으로 검증한다.- Creator Channel 커뮤니티 게시물 클릭 source test가 Activity 전체가 아닌 해당 handler 본문에서 guard와 launcher 순서를 확인하게 한다.
- Task 1.4와 Task 1.5의 실제 변경 파일 목록을 현재 diff와 일치시킨다.
- 검증 기준:
Allowed는 원래 action을 정확히 한 번 실행하고 거부 UX callback은 실행하지 않는다.- 모든 거부 결과는 원래 action을 실행하지 않고 대응 UX callback만 정확히 한 번 실행한다.
- 커뮤니티 게시물 handler 밖의 다른 로그인 guard로 source test가 통과하지 않는다.
- 실행 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.access.V2AccessGuardTest" ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest.커뮤니티 게시물 클릭 source는 상세 Activity newIntent로 진입하고 invalid postId를 무시한다" - 기대 결과: 실행 계약 테스트는 구현 전 RED, 구현 후 GREEN이고 강화된 source test가 통과한다.
- 검증 기록:
- 2026-07-14:
V2AccessGuardTest를 먼저 추가하고 단일 테스트를 실행해executeAccessDecision미정의 컴파일 오류로 RED를 확인했다. - 2026-07-14: 기존
V2AccessGuard.handleDecision의 분기를 Android 비의존executeAccessDecision으로 추출한 뒤 같은 단일 테스트가BUILD SUCCESSFUL로 전환되는 것을 확인했다. 네 가지AccessDecision별 반환값과 실행 callback이 정확히 하나인지 검증한다. - 2026-07-14: Creator Channel 커뮤니티 handler source에서 guard 문자열을 일시 제거한 변이 입력으로 대상 테스트가 실패하는 것을 확인한 뒤, 실제 handler source 검사로 복원해
BUILD SUCCESSFUL을 확인했다. - 2026-07-14: Access, Main, On-air 전체와 변경 영향 Creator Channel 4개 테스트를 묶어 재실행해
BUILD SUCCESSFUL을 확인했다. - 2026-07-14:
./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck,./gradlew tasks --all을 실행해 모두BUILD SUCCESSFUL을 확인했다. ktlint에는 기존.editorconfig의disabled_rules속성 사용에 대한 deprecation warning이 남아 있다. - 2026-07-14:
git diff --check HEAD를 실행해 staged와 unstaged를 합친 전체 변경에 whitespace 오류가 없음을 확인했다. - 2026-07-14: 사용자 확인에 따라 현재 layout에 존재하지 않아 기존 테스트를 실패시키던
ic_chevron_down_whitesource assertion은 수동 삭제한 상태를 유지한다. Phase 1 운영 코드 변경과는 무관한 기존 테스트 정리다.
- 2026-07-14:
- 생성 파일:
-
Task 1.8: 코드 리뷰 후 ktlint 재현성 보완
- 수정 파일:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingFragmentSourceTest.ktdocs/20260714_V2_공통_접근_가드와_도메인_액션/plan-task.md
- 작업:
- 캐시를 배제한
ktlintCheck에서 재현된 기존 source test 3줄의 max line length와 argument wrapping 위반만 수정한다. - 기존 인증 문자열과 테스트 의미는 변경하지 않는다.
- 캐시를 배제한
- 검증 기준:
./gradlew :app:ktlintCheck --rerun-tasks로 전체 기준선을 재검사하고, Phase 1 변경 파일에 신규 위반이 없음을 보고서에서 확인한다.- 수정한 source test와 Access 관련 회귀 테스트가 통과한다.
git diff --check HEAD가 통과한다.
- RED 검증 기록:
- 2026-07-14:
./gradlew :app:ktlintCheck --rerun-tasks를 실행해HomeFollowingFragmentSourceTest.kt:118-120의 max line length와 argument wrapping 위반으로BUILD FAILED를 재현했다. 해당 파일은 기존 Phase 1 diff에 없었으므로, 이전 통과 기록은 Gradle up-to-date 캐시에 의해 실제 전체 린트를 재실행하지 않은 결과였다.
- 2026-07-14:
- GREEN 검증 기록:
- 2026-07-14: 세 문자열 assertion만 ktlint 규칙에 맞게 줄바꿈하고
HomeFollowingFragmentSourceTest를--rerun-tasks로 실행해BUILD SUCCESSFUL을 확인했다. - 2026-07-14: 수정 후
./gradlew :app:ktlintCheck --rerun-tasks를 재실행한 결과ktlintTestSourceSetCheck보고서는 0건이 되었고 Phase 1 변경 파일에서 위반이 검출되지 않았다. 전체 명령은 Phase 1 범위 밖 파일의 기존 ktlint 위반으로 실패했으며, 레거시 운영 코드 위반과 함께app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/ui/ContentCommentedAudioAdapter.kt:29의 기존 V2 위반 1건도 포함되므로 전체 통과가 아닌 기준선 제약으로 기록한다. - 2026-07-14:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.access.*" --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest" --rerun-tasks를 실행해 Access 회귀와 수정한 source test가BUILD SUCCESSFUL로 통과함을 확인했다. - 2026-07-14:
git diff --check HEAD는 whitespace 오류 없이 통과했다.
- 2026-07-14: 세 문자열 assertion만 ktlint 규칙에 맞게 줄바꿈하고
- 수정 파일:
-
Task 1.9: 코드 리뷰 후 FanTalk source test와 ktlint gate 정정
- 수정 파일:
app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.ktdocs/20260714_V2_공통_접근_가드와_도메인_액션/prd.mddocs/20260714_V2_공통_접근_가드와_도메인_액션/plan-task.md
- 작업:
- FanTalk write와 item click source test가 Activity 전체가 아닌 해당 함수 본문에서 login guard와 launcher 순서를 확인하게 한다.
- PRD의 ktlint 완료 기준을 현재 저장소 기준선에 맞춰
ktlintCheck전체 재실행과 Phase 변경 파일 신규 위반 없음으로 명확히 한다. - 기존 ktlint 실패 기록에서 V2 파일 위반 1건을 레거시 위반으로 잘못 분류한 표현을 정정한다.
- 검증 기준:
- FanTalk write/item click handler 밖의 다른
ensureV2Access문자열로 source test가 통과하지 않는다. - Phase 1 완료 판정은 전체 ktlint 통과로 오인되지 않고 기준선 제약과 변경 파일 신규 위반 여부를 함께 기록한다.
- 관련 source test와 whitespace 검증이 통과한다.
- FanTalk write/item click handler 밖의 다른
- 검증 기록:
- 2026-07-14:
openFanTalkWrite와onCreatorChannelFanTalkItemClicked본문만sourceSection으로 추출해 guard, launcher, 실행 순서를 검증하도록 source test를 강화했다. - 2026-07-14:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest.FanTalk fixed plus source는 Activity overlay와 write result refresh 계약을 연결한다" --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest.FanTalk item click source는 owner gate와 상세 ActivityResult refresh를 연결한다" --rerun-tasks를 실행해BUILD SUCCESSFUL을 확인했다. - 2026-07-14:
./gradlew :app:ktlintCheck --rerun-tasks는ktlintMainSourceSetCheck기준선 위반으로 실패했다. 보고서에는 기존 main source 위반 551줄이 남아 있고, 그중app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/ui/ContentCommentedAudioAdapter.kt:29의 V2 max line length 위반 1건이 포함된다. - 2026-07-14:
./gradlew :app:ktlintTestSourceSetCheck --rerun-tasks는BUILD SUCCESSFUL로 통과해 이번에 수정한 source test 파일에는 신규 ktlint 위반이 없음을 확인했다. - 2026-07-14:
git diff --check HEAD는 whitespace 오류 없이 통과했다. - 2026-07-14: 리뷰어 게이트에서 P2/P3 반영, assertion 약화 없음, 문서 모순 없음에 대해 조건부 없는
PASS를 확인했다.
- 2026-07-14:
- 수정 파일:
-
Task 1.10: Phase 0/1 재리뷰 결과 반영
- 수정 파일:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/MainV2LoginGuardSourceTest.ktdocs/20260714_V2_공통_접근_가드와_도메인_액션/plan-task.md
- 작업:
V2AccessGuard.handleDecision이 각 거부 결과를 로그인, 본인인증, 콘텐츠 설정 UX callback에 연결하는 실제 결선을 source assertion으로 고정한다.- Task 1.6의 ktlint 기대 결과를 PRD의 최종 gate와 일치시킨다.
- 검증 기준:
- 로그인, 본인인증, 콘텐츠 설정 callback 결선이 서로 바뀌면 source test가 실패한다.
ktlintCheck는 전체 기준선을 재실행하고, 기존 위반으로 실패하면 Phase 1 변경 파일의 신규 위반이 없음을 확인한다.- 관련 회귀 테스트, 컴파일, test source ktlint, whitespace 검증이 통과한다.
- 실행 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.MainV2LoginGuardSourceTest" --rerun-tasks ./gradlew :app:compileDebugKotlin ./gradlew :app:ktlintCheck --rerun-tasks ./gradlew :app:ktlintTestSourceSetCheck --rerun-tasks git diff --check HEAD - 기대 결과: 결선 source test, 컴파일, test source ktlint, whitespace 검증이 통과하고 전체 ktlint 기준선 제약이 기존 기록과 일치한다.
- 검증 기록:
- 2026-07-14:
handleDecision본문만 추출해 로그인, 본인인증, 콘텐츠 설정AccessDecision이 각각startLogin,showAuthDialog,startContentSettingscallback에 연결되는지 검증하도록 source test를 강화했다. - 2026-07-14:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.MainV2LoginGuardSourceTest" --rerun-tasks를 실행해 테스트 1건이 실패 없이 통과하고BUILD SUCCESSFUL임을 확인했다. - 2026-07-14: 위 회귀 테스트에서 production/test source를 새로 컴파일했으며, 별도
./gradlew :app:compileDebugKotlin도BUILD SUCCESSFUL로 통과했다. - 2026-07-14:
./gradlew :app:ktlintCheck --rerun-tasks는 기존 main source 기준선 위반 551줄로 실패했다. Phase 1 변경 main source의 신규 위반은 0건이고, V2 위반 1건은 변경하지 않은ContentCommentedAudioAdapter.kt:29의 기존 max line length 위반이다. - 2026-07-14:
./gradlew :app:ktlintTestSourceSetCheck --rerun-tasks는BUILD SUCCESSFUL로 통과했으며 test source 보고서 위반은 0건이다. - 2026-07-14:
./gradlew tasks --all은BUILD SUCCESSFUL로 통과해 문서 변경 후 Gradle task 구성을 확인했다. - 2026-07-14:
git diff --check HEAD는 whitespace 오류 없이 통과했다.
- 2026-07-14:
- 수정 파일:
-
Task 1.11: Phase 0/1 리뷰의 Activity별 Access 결선 테스트 보강
- 수정 파일:
app/src/test/java/kr/co/vividnext/sodalive/v2/live/onair/HomeOnAirLiveEntryPolicyTest.ktapp/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivitySourceTest.ktdocs/20260714_V2_공통_접근_가드와_도메인_액션/plan-task.md
- 작업:
- On-air 라이브 입장이 로그인 가드, room detail 조회, 성인 콘텐츠 가드, 기존 입장 함수 순서로 실행되는지 함수 본문 source로 검증한다.
- Creator Channel 화면 진입이 유효한 creator ID 확인 후 로그인 가드를 거치며, 거부 시 화면 조립 전에 종료되는지 검증한다.
- Creator Channel AI 채팅이 성인 콘텐츠 가드 통과 후에만 채팅방 생성을 요청하는지 클릭 listener 범위에서 검증한다.
- 검증 기준:
- 각 함수 밖의 다른
ensureV2Access문자열로 테스트가 통과하지 않는다. - 각 가드 문자열을 제거한 변이 source에서는 대응 테스트가 실패한다.
- production 코드는 변경하지 않고 관련 source test와 기존 Access 회귀 테스트가 통과한다.
- 각 함수 밖의 다른
- 실행 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.live.onair.HomeOnAirLiveEntryPolicyTest" --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest" --rerun-tasks ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.access.*" --tests "kr.co.vividnext.sodalive.v2.main.*" --tests "kr.co.vividnext.sodalive.v2.live.onair.*" --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest" --rerun-tasks ./gradlew :app:compileDebugKotlin ./gradlew :app:ktlintTestSourceSetCheck --rerun-tasks git diff --check HEAD - 기대 결과: 변이 source RED 확인 후 실제 source 기준 대상 테스트와 관련 회귀 테스트, 컴파일, test source ktlint, whitespace 검증이 통과한다.
- RED 검증 기록:
- 2026-07-14: 세 결선 테스트에서 각 대상 가드 문자열을 제거한 변이 source를 사용해 실행한 결과, On-air 로그인/성인 결선 1건과 Creator Channel 진입/AI 채팅 결선 2건이 각각 실패하고
BUILD FAILED가 발생함을 확인했다.
- 2026-07-14: 세 결선 테스트에서 각 대상 가드 문자열을 제거한 변이 source를 사용해 실행한 결과, On-air 로그인/성인 결선 1건과 Creator Channel 진입/AI 채팅 결선 2건이 각각 실패하고
- GREEN 검증 기록:
- 2026-07-14: 변이를 제거하고 실제 production source를 대상으로 신규 결선 테스트 3건을
--rerun-tasks로 실행해 모두 통과하고BUILD SUCCESSFUL임을 확인했다. - 2026-07-14:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.access.*" --tests "kr.co.vividnext.sodalive.v2.main.*" --tests "kr.co.vividnext.sodalive.v2.live.onair.*" --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest" --rerun-tasks를 실행해 관련 회귀 테스트 503건이 실패, 오류, 스킵 없이 통과했다. - 2026-07-14:
./gradlew :app:compileDebugKotlin은BUILD SUCCESSFUL로 통과했다. - 2026-07-14:
./gradlew :app:ktlintTestSourceSetCheck --rerun-tasks는BUILD SUCCESSFUL로 통과해 test source 신규 위반이 없음을 확인했다. - 2026-07-14:
./gradlew tasks --all은BUILD SUCCESSFUL로 통과해 문서 변경 후 Gradle task 구성을 확인했다. - 2026-07-14:
git diff --check HEAD는 whitespace 오류 없이 통과했다. - 2026-07-14: Task 1.11에서는 production 코드를 추가 변경하지 않고 기존 source test 클래스 두 곳과 계획 문서만 보강했다.
- 2026-07-14: 변이를 제거하고 실제 production source를 대상으로 신규 결선 테스트 3건을
- 수정 파일:
Phase 2: Content 공통 Action
-
Task 2.1: 오디오/시리즈 진입 호출부와 계약 확정
- 확인 예정 파일:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/main/content/ContentMainFragment.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/ContentOverviewActivity.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt
- 작업: ID, 성인 여부, Activity result, route source, 기존 extra 차이를 목록화하고 Action 계약을 확정한다.
- 검증 기준:
- 화면 전용 UI model을 받지 않는 최소 command/result 계약이 정해진다.
- Activity result 또는 호출 화면 후처리가 있는 경로는 Content result adapter와 단일 handler 필요 여부가 결정된다.
- 확인 예정 파일:
-
Task 2.2: Content Action 순수 계약 테스트 및 구현
- 생성 예정 파일:
app/src/main/java/kr/co/vividnext/sodalive/v2/content/action/ContentAction.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/content/action/ContentActionCommand.ktapp/src/test/java/kr/co/vividnext/sodalive/v2/content/action/ContentActionTest.kt
- 검증 대상: invalid ID, audio/series route, 성인 Access 요구사항 전달, 허용/차단 결과.
- 검증 기준: feature UI model과 DTO 의존 없이 입력·출력이 테스트된다.
- 생성 예정 파일:
-
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 호출 파일
- 작업: 기존 extra와 Access UX를 보존하면서 오디오/시리즈 상세 진입을 한 곳으로 통합한다.
- 검증 기준: 대상 UI에서 상세 Activity Intent 직접 생성이 제거되고 Content Action을 사용한다.
- 생성/수정 예정 파일:
-
Task 2.4: Content Phase 회귀 검증
- 실행 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.content.action.*" ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.*" ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*" ./gradlew :app:compileDebugKotlin ./gradlew :app:ktlintCheck git diff --check - 수동 확인: Home, Content, Content Overview, Creator Channel에서 audio/series 상세 진입과 성인 차단 UX가 기존과 동일하다.
- 실행 명령:
Phase 3: Live 공통 Action
-
Task 3.1: 기존 Live 흐름 차이와 레거시 의존 목록 확정
- 확인 예정 파일:
app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelLiveCoordinator.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/live/onair/HomeOnAirLiveActivity.kt
- 작업: 상세, 입장, 예약, 결제, 비밀번호, 오디오 중단, Activity result, refresh callback, navigation 차이를 기록한다.
- 검증 기준:
- Live 공통 정책과 화면별 후처리가 구분된다.
- 라이브 생성 결과를 포함한 raw Activity result의 Live 결과 변환과 feature 단일 handler가 확정된다.
- 확인 예정 파일:
-
Task 3.2: Live 입장 결정 계약과 단위 테스트 작성
- 생성 예정 파일:
app/src/main/java/kr/co/vividnext/sodalive/v2/live/action/LiveEntryDecision.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/live/action/LiveEntryPolicy.ktapp/src/test/java/kr/co/vividnext/sodalive/v2/live/action/LiveEntryPolicyTest.kt
- 검증 대상: 관리자, 무료/결제 완료, 비밀번호, 유료, 상세 표시 분기.
- 검증 기준: Activity/Dialog 없이 기존 분기 순서를 순수 입력·출력으로 검증한다.
- 생성 예정 파일:
-
Task 3.3: Live Action/Coordinator 단일 구현과 호환 adapter 구성
- 생성/이동/수정 예정 파일:
app/src/main/java/kr/co/vividnext/sodalive/v2/live/action/LiveActions.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/live/action/LiveActionCoordinator.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelLiveCoordinator.kt
- 작업:
- 기존 Coordinator 동작을 Live 소유 진입점으로 옮기고 필요한 동안 기존 이름은 얇은 adapter로 유지한다.
- 하위 Activity가 반환하는 Live 결과는 명시적 result로 변환하고 호출 feature의 단일 handler로 전달한다.
- 검증 기준: 새 구현이 Creator Channel feature를 import하지 않고 레거시 Live 기능만 adapter로 호출한다.
- 생성/이동/수정 예정 파일:
-
Task 3.4: Home/Creator Channel/On-air 호출부 전환과 중복 제거
- 수정 예정 파일:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/live/onair/HomeOnAirLiveActivity.kt
- 검증 기준: 세 화면이 동일 Live Action을 사용하고 On-air의 중복 입장 조건이 제거된다.
- 수정 예정 파일:
-
Task 3.5: Live Phase 회귀 검증
- 실행 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.live.*" ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.live.*" ./gradlew :app:compileDebugKotlin ./gradlew :app:ktlintCheck git diff --check - 수동 확인: 무료, 유료, 비밀번호, 관리자, 상세 표시, 예약/취소 흐름과 화면별 refresh 동작이 기존과 동일하다.
- 실행 명령:
Phase 4: Creator와 Community 공통 Action
-
Task 4.1: Creator Channel 진입 호출부와 계약 확정
- 확인 예정 파일:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/MainV2Activity.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/main/home/app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/
- 검증 기준:
creatorId, 로그인 요구 여부, route source, 기존 extra 차이가 정리된다.
- 확인 예정 파일:
-
Task 4.2: Creator Action 구현과 호출부 전환
- 생성 예정 파일:
app/src/main/java/kr/co/vividnext/sodalive/v2/creator/action/CreatorActions.ktapp/src/test/java/kr/co/vividnext/sodalive/v2/creator/action/CreatorActionsTest.kt
- 검증 기준: 유효 ID와 Access를 한 곳에서 처리하고 feature UI model을 입력받지 않는다.
- 생성 예정 파일:
-
Task 4.3: Community 게시글 진입 계약 구현과 호출부 전환
- 생성 예정 파일:
app/src/main/java/kr/co/vividnext/sodalive/v2/community/action/CommunityActions.ktapp/src/test/java/kr/co/vividnext/sodalive/v2/community/action/CommunityActionsTest.kt
- 수정 예정 파일:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt
- 검증 기준: 로그인, ID 검사, Activity result 차이를 보존하고 공통 게시글 진입점을 사용한다.
- 생성 예정 파일:
-
Task 4.4: Community 변경 결과와 레거시 ActivityResult adapter 구현
- 생성 예정 파일:
app/src/main/java/kr/co/vividnext/sodalive/v2/community/action/CommunityChange.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/community/action/CommunityActivityResultMapper.ktapp/src/test/java/kr/co/vividnext/sodalive/v2/community/action/CommunityChangeTest.kt
- 작업:
- 작성, 수정, 삭제, 고정 변경을
Created,Updated,Deleted,PinChanged로 표현한다. - 레거시 작성/수정 Activity의
RESULT_OK를 명시적인 Community 변경 결과로 변환한다. - 결과 계약에는 Home/Community 탭 refresh callback 또는 Fragment 참조를 포함하지 않는다.
- 작성, 수정, 삭제, 고정 변경을
- 검증 기준: result code, 유효/누락 post ID, 변경 종류가 화면 의존 없이 테스트된다.
- 생성 예정 파일:
-
Task 4.5: Creator Channel Community 변경 composition handler 통합
- 수정 예정 파일:
app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt
- 작업:
handleCommunityChange(change)단일 함수에서 Home/Community projection 갱신을 조합한다.- Community 작성, 수정, 삭제, 고정 변경 성공 경로가 위 함수를 사용하도록 전환한다.
- 기존
ActivityResultLauncher, Activity result 수신 시점, Fragment initial load 동작은 유지한다.
- 검증 기준:
- Community Action/결과가 Creator Channel Home 또는 Community Fragment를 알지 않는다.
- Activity 내부의 개별 성공 경로에
refreshHome()과refreshCreatorChannelCommunity()조합이 반복되지 않는다. - 현재 Activity 내부 전파를 위해 전역 EventBus/observer singleton을 추가하지 않는다.
- 수정 예정 파일:
-
Task 4.6: Creator/Community Phase 회귀 검증
- 실행 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.action.*" ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.community.action.*" ./gradlew :app:compileDebugKotlin ./gradlew :app:ktlintCheck git diff --check
- 실행 명령:
Phase 5: Chat 공통 Action
-
Task 5.1: Chat/DM 진입 유형과 결과 계약 확정
- 확인 예정 파일:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/chat/app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt
- 작업: 기존 room 진입, creator 기반 DM 생성, AI/DM 타입, owner/non-owner, Activity result 차이를 구분한다.
- 검증 기준:
- 서로 다른 동작을 하나의 nullable/boolean 다목적 함수로 합치지 않는다.
- 호출 화면 후처리가 필요한 Activity result는 명시적 Chat 결과와 feature 단일 handler로 연결한다.
- 확인 예정 파일:
-
Task 5.2: Chat Action 계약과 단위 테스트 작성
- 생성 예정 파일:
app/src/main/java/kr/co/vividnext/sodalive/v2/chat/action/ChatActions.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/chat/action/ChatActionCommand.ktapp/src/test/java/kr/co/vividnext/sodalive/v2/chat/action/ChatActionsTest.kt
- 검증 기준: room/creator 식별자와 진입 유형이 명시적이고 Home/Creator UI model에 의존하지 않는다.
- 생성 예정 파일:
-
Task 5.3: Home/Chat/Creator Channel 호출부 전환
- 수정 예정 파일:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/main/chat/ChatMainFragment.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt
- 검증 기준: 기존 login guard, room 생성 API, 성공 후 이동, owner/non-owner 분기가 유지된다.
- 수정 예정 파일:
-
Task 5.4: Chat Phase 회귀 검증
- 실행 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.chat.action.*" ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.*" ./gradlew :app:compileDebugKotlin ./gradlew :app:ktlintCheck git diff --check
- 실행 명령:
Phase 6: 의존 방향과 이전 구현 정리
-
Task 6.1: feature 간 직접 navigation/Coordinator 의존 재검사
- 확인 범위:
app/src/main/java/kr/co/vividnext/sodalive/v2/**/*.kt - 실행 명령:
rg -n '^import kr\.co\.vividnext\.sodalive\.v2\.(main|creator|live)\..*(Activity|Fragment|Coordinator)' app/src/main/java/kr/co/vividnext/sodalive/v2 --glob '*.kt' - 검증 기준: composition에 필요한 부모-자식 Fragment 연결을 제외하고 도메인 Action으로 대체할 직접 의존이 남지 않는다.
- 확인 범위:
-
Task 6.2: 이전 helper와 중복 함수 제거
- 삭제/수정 대상: 각 Phase에서 호환을 위해 남긴 adapter, 이전
ensure..., 중복open..., 직접 route helper. - 검증 기준: 모든 호출부가 새 공개 진입점을 사용하는 것이 확인된 구현만 제거한다.
- 삭제/수정 대상: 각 Phase에서 호환을 위해 남긴 adapter, 이전
-
Task 6.3: 미추출 도메인 재평가
- 확인 대상: FanTalk, Donation, Schedule, Ranking, Discovery.
- 작업: 실제 반복 호출과 동일 정책이 생겼는지 확인하고 추출 또는 현행 유지 근거를 기록한다.
- 검증 기준: 형식적 Action 추가 없이 단일 사용 기능은 기존 feature에 유지한다.
-
Task 6.4: 결과 전달 방식과 observer 필요성 재검사
- 확인 대상: Content, Live, Community, Chat 및 후속 mutation 흐름.
- 작업:
- 하위 Activity 결과가
ActivityResult -> 명시적 결과 -> feature 단일 handler로 연결되는지 확인한다. - 동일한 raw result 해석과 refresh 조합이 여러 호출부에 남아 있는지 확인한다.
SharedFlow/observer 도입 지점이 있다면 Activity 밖의 독립 소비자, lifecycle, replay, 중복 처리 근거를 기록한다.
- 하위 Activity 결과가
- 검증 기준: 직접 결과 전달로 충분한 흐름에 전역 EventBus 또는 singleton observer가 추가되지 않는다.
-
Task 6.5: 통합 회귀 검증
- 실행 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.*" ./gradlew :app:compileDebugKotlin ./gradlew :app:ktlintCheck git diff --check - 수동 확인:
- 로그인/본인인증/성인 설정 차단과 허용 흐름
- Home, Content, Creator Channel, On-air의 오디오/시리즈/라이브 진입
- Creator Channel 및 Community 상세 진입
- Chat/DM 생성과 기존 room 진입
- 기존 Activity result와 새로고침 동작
- 기대 결과:
v2전체 관련 테스트와 컴파일, ktlint, whitespace 검증 통과.
- 실행 명령:
Verification Log
- 2026-07-14: 사용자 요청에 따라 이번 단계에서는 PRD와 구현 계획 문서만 작성했다. 운영 코드, 테스트 코드, DI는 아직 변경하지 않았고 Gradle 검증은 실행하지 않았다.
- 2026-07-14: 문서 범위는 Access부터 도메인별로 순차 전환하는 하나의 연속 작업으로 정의했다. 화면별 최초 집계 API는 유지하고 반복 action만 단일 소유 진입점으로 통합한다.
- 2026-07-14: 문서 작성 후
./gradlew tasks --all을 실행해 계획에 사용하는:app:testDebugUnitTest,:app:compileDebugKotlin,:app:ktlintCheck작업이 존재함을 확인했으며 명령은BUILD SUCCESSFUL로 종료되었다.git diff --check도 whitespace 오류 없이 통과했다. - 2026-07-14: Community 업로드 후 Home/Community 탭 갱신 설계를 구체화했다. 초기 구현은 전역 observer 대신
CommunityChange결과와 Creator Channel의 단일handleCommunityChangecomposition handler를 사용하며, 레거시ActivityResult는v2adapter에서 변경 결과로 변환한다. - 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는 무출력으로 통과했다.