14 KiB
14 KiB
메인 V2 홈 FAB 구현 계획/TASK
Architecture
MainV2Activity에 CreatorChannelActivity owner FAB와 동일한 overlay UI와 상태 제어 로직을 추가한다. 표시 조건은 currentTab == MainV2Tab.HOME, isV2AccessAllowed(AccessRequirement.Login), SharedPreferenceManager.role == MemberRole.CREATOR.name의 AND 조건으로 제한한다. 액션 진입은 기존 Activity를 재사용하고, 라이브 생성 결과 처리는 기존 LiveCreationResult/LiveActionCoordinator 패턴을 따른다.
Success Criteria
- 로그인한 크리에이터가
MainV2Activity홈 탭에 있을 때 우측 하단 FAB가 표시된다. - 일반 유저와 비로그인 유저에게 FAB가 표시되지 않는다.
- 콘텐츠/채팅/마이 탭으로 이동하면 FAB가 숨겨지고 확장 상태가 닫힌다.
- FAB 확장 UI와 각 버튼 기능은
CreatorChannelActivity홈 탭 FAB와 동일하다. - 기존 CreatorChannel FAB, 미니 플레이어, 하단 내비게이션 동작을 회귀시키지 않는다.
Phase 1: 기존 패턴 및 표시 조건 확정
-
Task 1.1: CreatorChannel FAB 구조 확인
- 파일:
app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt,app/src/main/res/layout/activity_creator_channel.xml - 확인 내용:
ownerFabButton,ownerFabExpandedContainer,ownerFabDim,ownerFabCloseButton구조를 재사용한다.- 액션은
CreatorCommunityWriteActivity,AudioContentUploadActivity,LiveRoomCreateActivity로 이동한다. - Live 생성 결과는
resolveLiveCreationResult()와LiveActionCoordinator.enterLiveRoom()을 사용한다.
- 검증 기록:
- 2026-07-16:
CreatorChannelActivity와activity_creator_channel.xml을 읽어 홈 탭 owner FAB의 UI, 애니메이션, 액션 연결을 확인했다.
- 2026-07-16:
- 파일:
-
Task 1.2: MainV2 표시 조건 확인
- 파일:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/MainV2Activity.kt,app/src/main/java/kr/co/vividnext/sodalive/v2/main/MainV2ViewModel.kt,app/src/main/java/kr/co/vividnext/sodalive/common/SharedPreferenceManager.kt,app/src/main/java/kr/co/vividnext/sodalive/settings/notification/GetMemberInfoResponse.kt - 확인 내용:
MainV2Activity는viewModel.currentTab관찰로 탭 변경을 처리한다.MainV2ViewModel.getMemberInfo()는SharedPreferenceManager.role = data.role.name을 갱신한다.- 기존 코드에서 크리에이터 판정은
SharedPreferenceManager.role == MemberRole.CREATOR.name패턴을 사용한다.
- 검증 기록:
- 2026-07-16:
MainV2ViewModel.getMemberInfo()와SharedPreferenceManager.role을 확인했고,HomeFragment/LiveFragment등 기존 화면이MemberRole.CREATOR.name으로 크리에이터 role을 판정함을 확인했다.
- 2026-07-16:
- 파일:
Phase 2: Source 계약 테스트 추가
-
Task 2.1: MainV2 FAB 표시 정책 테스트 추가
- 파일:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/MainHomeFabVisibilityPolicy.kt,app/src/test/java/kr/co/vividnext/sodalive/v2/main/MainHomeFabVisibilityPolicyTest.kt - 요구사항:
MainHomeFabVisibilityPolicy순수 로직으로 홈 탭/로그인/role 조합에 따른 표시 여부를 검증한다.- UI 레이아웃, constraint, visibility 표현 속성은 테스트하지 않는다.
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.MainHomeFabVisibilityPolicyTest"
- 검증 기록:
- 2026-07-16: 최초 구현에서 레이아웃 ID/drawable/string/constraint를 문자열로 검사하는 source test를 추가했으나,
docs/agent-guides/code-style.md의 UI 레이아웃/표현 속성 검증 금지 규칙에 맞지 않아 제거했다. - 2026-07-16: RED로
MainHomeFabVisibilityPolicyTest를 추가했고, 정책 파일 미구현으로 컴파일 실패함을 확인했다.MainHomeFabVisibilityPolicy추가 후 동일 테스트가 PASS했다.
- 2026-07-16: 최초 구현에서 레이아웃 ID/drawable/string/constraint를 문자열로 검사하는 source test를 추가했으나,
- 파일:
-
Task 2.2: MainV2 FAB 기존 source test 정리
- 파일:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/MainV2ActivitySourceTest.kt,app/src/test/java/kr/co/vividnext/sodalive/v2/main/MainHomeFabVisibilityPolicyTest.kt - 요구사항:
- 신규 레이아웃/visibility source test를 제거한다.
- 표시 조건은 실행 가능한 순수 정책 테스트로 검증한다.
- 기존
MainV2ActivitySourceTest의 unrelated source 계약 테스트는 유지한다.
- 검증 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.MainV2ActivitySourceTest"
- 검증 기록:
- 2026-07-16: 최초 구현에서 FAB Activity source test를 추가했으나 실제 동작 실행 없이 source 문자열만 확인한다는 리뷰 지적을 반영해 제거했다. 표시 조건 검증은
MainHomeFabVisibilityPolicyTest로 대체했다.
- 2026-07-16: 최초 구현에서 FAB Activity source test를 추가했으나 실제 동작 실행 없이 source 문자열만 확인한다는 리뷰 지적을 반영해 제거했다. 표시 조건 검증은
- 파일:
Phase 3: MainV2 FAB UI 구현
- Task 3.1: activity_main_v2.xml에 FAB overlay 추가
- 파일:
app/src/main/res/layout/activity_main_v2.xml - 구현 내용:
owner_fab_dim에 대응되는 MainV2 전용 dim view를 추가한다.- expanded container에 community/audio/live/close 버튼을 추가한다.
- collapsed FAB를 추가한다.
- ID는
main_home_fab_*형태로 충돌 없이 명명한다. - drawable/icon/string은 CreatorChannel 리소스를 재사용한다.
- 검증 기준:
- ViewBinding에서 새 ID들이 생성 가능해야 한다.
- 새 리소스를 만들지 않아야 한다.
- 검증 기록:
- 2026-07-16:
activity_main_v2.xml에 MainV2 전용main_home_fab_*overlay를 추가하고 CreatorChannel FAB drawable/icon/string 리소스를 재사용했다../gradlew :app:assembleDebug로 ViewBinding/resource 생성이 성공함을 확인했다.
- 2026-07-16:
- 파일:
Phase 4: MainV2 FAB 상태/액션 구현
-
Task 4.1: MainV2Activity에 FAB 상태와 애니메이션 추가
- 파일:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/MainV2Activity.kt - 구현 내용:
isMainHomeFabExpanded,isMainHomeFabAnimating상태를 추가한다.expandMainHomeFab(),collapseMainHomeFab(),animateMainHomeFab(),updateMainHomeFabVisibility()를 추가한다.updateMainHomeFabVisibility()는MainV2Tab.HOME,isV2AccessAllowed(AccessRequirement.Login),SharedPreferenceManager.role == MemberRole.CREATOR.name조건을 모두 만족할 때만 collapsed FAB를 표시한다.- 홈이 아닌 탭 또는 비크리에이터 상태에서는 확장 상태를 false로 만들고 관련 view를 숨긴다.
- 검증 기준:
- 일반 유저와 비로그인 상태에서는 FAB visibility가
gone이어야 한다.
- 일반 유저와 비로그인 상태에서는 FAB visibility가
- 검증 기록:
- 2026-07-16:
MainV2Activity에HOME + isV2AccessAllowed(Login) + SharedPreferenceManager.role == MemberRole.CREATOR.name표시 조건과 확장/접기 상태를 추가했다. 리뷰어 지적으로 FAB spring 상수를CreatorChannelActivity와 동일한260L/1f/256f/24f로 맞추고 source test에 parity assertion을 추가했다. - 2026-07-16: source test parity assertion은 UI/source 문자열 테스트 규칙 위반 리뷰를 반영해 제거했고, 표시 조건은
MainHomeFabVisibilityPolicy순수 로직으로 분리했다.
- 2026-07-16:
- 파일:
-
Task 4.2: FAB click action 연결
- 파일:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/MainV2Activity.kt - 구현 내용:
- collapsed FAB 클릭 시 확장한다.
- dim/close 클릭 시 닫는다.
- community 버튼은
CreatorCommunityWriteActivity를 연다. - audio 버튼은
AudioContentUploadActivity를 연다. - live 버튼은
LiveRoomCreateActivity를ActivityResultContracts.StartActivityForResult()launcher로 연다. - 각 액션은 실행 직전에 FAB를 닫는다.
- 액션 실행 전에도
ensureV2Access(AccessRequirement.Login)과 creator role 조건을 확인해 비정상 노출/상태 변경에 대비한다.
- 검증 기준:
- 기존 legacy Activity 파일은 수정하지 않는다.
- 검증 기록:
- 2026-07-16: dim/close/collapsed FAB 클릭과 커뮤니티/오디오/라이브 버튼 클릭을 연결했다. 커뮤니티는
CreatorCommunityWriteActivity, 오디오는AudioContentUploadActivity, 라이브는LiveRoomCreateActivity기존 진입점을 재사용하며 legacy Activity 파일은 수정하지 않았다. - 2026-07-16: 액션 실행 전
isV2AccessAllowed()만 확인해 세션 무효화 시 조용히 무시될 수 있다는 리뷰 지적을 반영했다.runMainHomeFabAction()에서 먼저 FAB를 닫고ensureV2Access(AccessRequirement.Login)을 실행한 뒤, 크리에이터 홈 탭 조건이 유지될 때만 기존 생성 진입점을 실행하도록 수정했다.
- 2026-07-16: dim/close/collapsed FAB 클릭과 커뮤니티/오디오/라이브 버튼 클릭을 연결했다. 커뮤니티는
- 파일:
-
Task 4.3: 생성 결과 후 홈 갱신 연결
- 파일:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/MainV2Activity.kt,app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt - 구현 내용:
HomeMainFragment에 최소 공개 메서드refreshHome()를 추가해 추천 데이터를 다시 로드한다.- 커뮤니티 작성 완료 및 라이브 생성 결과에서 홈 갱신이 필요한 경우 현재 Home fragment의
refreshHome()를 호출한다. - 라이브 생성 결과가 입장 케이스이면
LiveActionCoordinator.enterLiveRoom()를 사용한다.
- 검증 기준:
- Fragment가 없거나 현재 탭이 홈이 아니어도 크래시가 없어야 한다.
- 검증 기록:
- 2026-07-16:
HomeMainFragment.refreshHome()을 추가해 기존homeRecommendationViewModel.loadRecommendations()경로를 재사용했다. 커뮤니티 작성 결과와 라이브 생성 결과에서 현재 홈 fragment가 있을 때만 safe-call로 갱신하도록 연결했다.
- 2026-07-16:
- 파일:
Phase 5: 검증 및 문서 갱신
-
Task 5.1: 단위/source test 실행
- 명령:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.MainV2ActivitySourceTest"./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.MainHomeFabVisibilityPolicyTest"./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.live.action.*"
- 기대 결과:
- 신규/관련 테스트가 통과한다.
- 검증 기록:
- 2026-07-16:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.MainV2ActivitySourceTest"PASS. - 2026-07-16:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.MainHomeFabVisibilityPolicyTest"PASS. - 2026-07-16:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.live.action.*"PASS.
- 2026-07-16:
- 명령:
-
Task 5.2: 빌드/정적 검증 실행
- 명령:
./gradlew :app:ktlintCheck./gradlew :app:assembleDebuggit diff --check
- 기대 결과:
- 포맷, 빌드, diff whitespace 검증이 통과한다.
- 검증 기록:
- 2026-07-16:
./gradlew :app:ktlintCheck는 신규 테스트 긴 줄로 1차 실패했고, assertion 포맷 수정 후 PASS했다. 기존.editorconfig disabled_rulesdeprecation warning은 출력되지만 실패 원인은 아니다. - 2026-07-16:
./gradlew :app:assembleDebugPASS. - 2026-07-16:
git diff --checkPASS. - 2026-07-16:
lsp_diagnostics는kotlin-ls미설치 상태라 실행할 수 없었고,compileDebugKotlin/테스트/빌드로 타입 검증을 대체했다.
- 2026-07-16:
- 명령:
-
Task 5.3: 수동 QA
- 확인 항목:
- 비로그인 상태 홈 탭에서 FAB가 표시되지 않는다.
- 일반 유저 로그인 상태 홈 탭에서 FAB가 표시되지 않는다.
- 크리에이터 로그인 상태 홈 탭에서 FAB가 표시된다.
- 크리에이터가 콘텐츠/채팅/마이 탭으로 이동하면 FAB가 숨겨진다.
- FAB 확장, dim 닫기, close 닫기가
CreatorChannelActivity와 동일하게 동작한다. - 커뮤니티/오디오/라이브 버튼이 기존 화면으로 이동한다.
- 미니 플레이어가 표시되어도 FAB가 하단 UI와 과도하게 겹치지 않는다.
- 검증 기록:
- 2026-07-16: 연결 기기
SM-G960N이 처음adb devices에 표시되어./gradlew :app:installDebug로 실기기 QA를 시도했으나 APK sync 중Broken pipe로 실패했다. 이어adb install -r app/build/outputs/apk/debug/app-debug.apk를 시도했을 때no devices/emulators found가 발생했고 이후adb devices도 빈 목록이었다. 따라서 실제 화면 캡처 QA는 ADB 연결 문제로 차단되었고, source test/빌드/리뷰어 게이트로 검증을 대체했다. - 2026-07-16: 리뷰 지적을 반영해 Task 5.3을 완료(
[x])가 아닌[blocked]상태로 정정했다. FAB 위치, 애니메이션, 권한별 노출, 미니 플레이어 중첩은 실제 기기/에뮬레이터 연결 후 별도 수동 QA가 필요하다. - 2026-07-17: 사용자가 직접 수동 QA를 수행해 비로그인/일반 유저 FAB 미노출, 크리에이터 홈 탭 FAB 노출, 비홈 탭 이동 시 숨김, 확장/닫기 동작, 각 생성 화면 진입, 미니 플레이어 중첩 방지를 확인했다. 액션 실행 직전에 FAB가 닫히는 동작도 확인했다.
- 2026-07-16: 연결 기기
- 확인 항목:
Verification Log
- 2026-07-16: 구현 전 문서 작성 단계. 사용자 확인으로 FAB 표시 대상은 “로그인 후 크리에이터인 경우만”으로 확정했다.
- 2026-07-16: 독립 리뷰어 게이트 1차에서
CreatorChannelActivity와 FAB spring 상수가 다르다는 blocker를 받았고, MainV2 상수를 동일하게 수정한 뒤 source test를 확장했다. 재리뷰 결과 PASS, blocker 없음. - 2026-07-17: 사용자의 직접 수동 QA로 Task 5.3 전체 확인 항목이 통과했으며, 액션 실행 직전 FAB가 닫히는 동작을 포함해 최종 화면 동작을 확인했다.