Files
sodalive-android/docs/20260625_메인_홈_팔로잉_탭/reviews/phase4-following-ui-routing-review.md

14 KiB

Phase 4 팔로잉 UI surface와 routing 리뷰

1. 리뷰 정보

항목 내용
리뷰 대상 Phase 4 / Task 4.1~4.9
기준 commit 또는 working tree f600d10e8b63b6fdc812b18a874b077dfe072ca8 + 2026-07-31 working tree
리뷰 일자 2026-07-31
리뷰어 Codex
기준 문서 대상 prd.md, plan-task.md, 후속 pull-refresh/access 문서
리뷰 상태 수정 검증 완료

2. 리뷰 목적과 범위

목적

  • 팔로잉 surface 전환, section visibility, adapter click 연결과 상태 observer가 요구사항을 충족하는지 확인한다.
  • 후속 pull refresh와 공통 액션 변경을 포함한 현재 실행 경로에서 회귀가 없는지 확인한다.

포함 범위

  • HomeMainFragment.kt, fragment_v2_main_home.xml
  • 팔로잉 adapter 5개, HomeFollowingFragmentSourceTest, HomeMainFragmentLoginGuardSourceTest

제외 범위

  • chevron 실제 목적지와 로그인 유도 UI 디자인.

3. 판정 기준

  • item 상세 이동 누락은 확정 기능 요구사항 위반으로 High, 제한된 로그인 만료/refresh 조건의 복구 문제는 Medium으로 판정했다.

4. 검토한 근거

문서와 코드

  • PRD On Air item 터치 요구사항과 이달의 스케줄 type/target 이동 요구사항
  • HomeMainFragment.kt:115-122, 397-419, 657-687
  • HomeFollowingLiveAdapter.kt:49-54, HomeFollowingScheduleAdapter.kt:53-67

실행 환경

OS: Darwin 25.0.0 x86_64
JDK: OpenJDK 17.0.15
Gradle wrapper: 8.14.3
연결 기기: 없음

실행한 검증

명령 결과 핵심 증거
./gradlew --no-daemon :app:testDebugUnitTest --tests "...HomeFollowingFragmentSourceTest" --tests "...HomeMainFragmentLoginGuardSourceTest" 성공 source test 모두 PASS
callback/observer 본문 수동 추적 문제 확인 live/schedule callback은 Unit, LoginRequired는 refresh 종료 호출 없음
profile helper·Coil 2.7.0 source·저장소 dispose() 사용례 대조 문제 확인 blank 분기가 drawable만 비우고 View 요청을 해제하지 않음
HomeFollowingFragmentSourceTest 이름과 테스트명 가이드 대조 문제 확인 완전한 영문 문장형 테스트명 11개 확인

5. 발견 사항 요약

ID 심각도 상태 제목 소유 Task 후속 goal
REV-P4-001 High 수정 완료 On Air와 스케줄 item 터치가 no-op Task 4.6 P4-R1 완료
REV-P4-002 Medium 수정 완료 LoginRequired 응답에서 pull refresh가 종료되지 않음 Task 4.7 P4-R2 완료
REV-P4-003 Medium 수정 완료 blank 프로필 이미지 바인딩이 이전 Coil 요청을 해제하지 않음 Task 4.8 P4-R3 완료
REV-P4-004 Low 수정 완료 공용 source test의 영문 문장형 테스트명이 한글 테스트명 규칙과 불일치 Task 4.9 P4-R4 완료

6. 발견 사항 상세

REV-P4-001 — On Air와 스케줄 item 터치가 no-op

  • 심각도: High
  • 상태: 수정 완료
  • 관련 요구사항: PRD On Air item 터치 시 해당 live room/detail, 스케줄 type/targetId 목적지
  • 소유 Task: Task 4.6

관찰 내용

adapter click listener는 Fragment callback까지 전달되지만 onFollowingLiveClick()onFollowingScheduleClick() 본문이 Unit이라 아무 이동도 발생하지 않는다.

근거

  • 코드: HomeMainFragment.kt:119-122, 669-671
  • 테스트: source test는 callback 존재만 확인하고 실제 액션을 요구하지 않음
  • 문서: Task 4.5 결과도 route 없는 skeleton임을 기록

재현 또는 검증 절차

  1. On Air 또는 schedule item을 bind한다.
  2. item root를 터치하면 adapter callback이 Fragment로 전달된다.
  3. 실제 결과는 Unit; 요구 결과는 기존 공통 Live/Content/Community Action 이동이다.

영향

팔로잉 핵심 섹션 두 곳에서 사용자가 상세 콘텐츠로 진입할 수 없다.

권장 조치

On Air liveIdLiveActionCoordinator, schedule type/targetId는 기존 최근 활동 route와 공통 액션을 재사용한다.

판정 기록

  • 2026-07-30 — PRD와 실제 callback 본문을 대조해 확정.
  • 2026-07-30 — Task 4.6에서 공통 Live/Content/Community Action 연결과 회귀 검증을 완료.

REV-P4-002 — LoginRequired 응답에서 pull refresh가 종료되지 않음

  • 심각도: Medium
  • 상태: 수정 완료
  • 관련 요구사항: 로그인 필요 상태 분기, 후속 홈 pull refresh 완료 정책
  • 소유 Task: Task 4.7

관찰 내용

ContentEmptyfinishHomePullRefresh()를 호출하지만 LoginRequired는 section만 숨긴다. 유효하지 않은 token 등으로 refresh API가 LoginRequired를 반환하면 SwipeRefresh spinner와 내부 refresh 추적 상태가 남는다.

근거

  • 코드: HomeMainFragment.kt:397-419
  • 비교 경로: Content 406, Empty 411, LoginRequired 413
  • 테스트: LoginRequired의 section 숨김만 검사하고 refresh 종료는 검사하지 않음

재현 또는 검증 절차

  1. 팔로잉 탭에서 pull refresh를 시작한다.
  2. API가 isLoginRequired=true를 반환한다.
  3. 실제 결과는 bindHomeFollowingEmpty(false)만 실행된다.
  4. 요구 결과는 section 숨김과 refresh 종료다.

영향

로그인 만료·서버 세션 불일치 조건에서 refresh UI가 계속 동작 중인 것처럼 남는다.

권장 조치

LoginRequired 분기에서 팔로잉 refresh 종료를 보장하는 최소 분기와 회귀 테스트를 추가한다.

판정 기록

  • 2026-07-30 — observer 분기와 refresh 상태 함수를 추적해 확정.
  • 2026-07-30 — Task 4.7에서 LoginRequired refresh 종료 분기와 회귀 검증을 완료.

REV-P4-003 — blank 프로필 이미지 바인딩이 이전 Coil 요청을 해제하지 않음

  • 심각도: Medium
  • 상태: 수정 완료
  • 관련 요구사항: PRD 팔로잉 크리에이터의 blank/실패 profile fallback, Phase 4 adapter image binding
  • 소유 Task: Task 4.8

관찰 내용

팔로잉 creator/live/chat/schedule와 community profile이 재사용하는 loadHomeCreatorProfileImage()는 URL이 blank이면 drawable만 비운다. Coil 2.7.0은 View에 연결된 기존 요청을 별도로 유지하므로, 이전 item의 요청이 아직 진행 중이면 완료 시점에 재사용된 View에 이전 이미지가 다시 표시될 수 있다.

근거

  • 코드: HomeCreatorProfileImageLoader.kt:10-17의 blank 분기에 dispose()가 없음
  • 호출부: HomeFollowingCreatorAdapter, HomeFollowingLiveAdapter, HomeFollowingChatAdapter, HomeFollowingScheduleAdapter, HomeFollowingNewsAdapter
  • 의존성: app/build.gradle의 Coil 2.7.0; 로컬 Coil source의 ViewTargetRequestManager.dispose()는 현재 요청을 취소·분리함
  • 저장소 정상 사용례: HomePopularCommunityAdapter.kt:67-70은 blank image에서 imageView.dispose() 후 drawable을 비움

재현 또는 검증 절차

  1. 재사용 가능한 profile ImageView에 완료 전 Coil 요청 A를 연결한다.
  2. 같은 ViewHolder에 blank profile URL item B를 바인딩한다.
  3. 현재 구현은 drawable만 비우고 요청 A를 유지한다.
  4. 요청 A가 뒤늦게 완료되면 item B에 A의 프로필이 표시될 수 있다. 요구 결과는 blank 바인딩 시 요청 A를 해제하고 빈 상태를 유지하는 것이다.

영향

빠른 스크롤이나 느린 이미지 응답 조건에서 creator/live/chat/schedule/news item에 다른 사용자의 프로필 이미지가 노출될 수 있다.

권장 조치

공통 loadHomeCreatorProfileImage()의 blank 분기에서 Coil 요청을 해제한 뒤 drawable을 비운다. 각 adapter를 중복 수정하지 않고 공통 helper 한 곳을 수정하며, Robolectric에서 View 요청 연결 해제를 검증한다.

판정 기록

  • 2026-07-30 — 공통 helper, 모든 팔로잉 호출부, Coil 2.7.0 요청 manager와 저장소 내 dispose() 사용례를 대조해 확정.
  • 2026-07-30 — 구현 전 Phase 4 Task 4.8 / P4-R3로 전환.
  • 2026-07-30 — Task 4.8에서 loadHomeCreatorProfileImage() blank 분기에 dispose()를 추가하고, Robolectric focused test와 팔로잉 회귀 검증을 완료.

REV-P4-004 — 공용 source test의 영문 문장형 테스트명이 규칙과 불일치함

  • 심각도: Low
  • 상태: 수정 완료
  • 관련 요구사항: docs/agent-guides/build-test-style.md, docs/agent-guides/code-style.md의 신규 Kotlin 테스트명 규칙
  • 소유 Task: 신규 Task 4.9

관찰 내용

Phase 4에서 생성되고 후속 Phase가 함께 확장한 HomeFollowingFragmentSourceTest에 완전한 영문 문장형 backtick 테스트명 11개가 남아 있다. 테스트 작성 전부터 가이드가 신규 Kotlin 테스트명을 한글 문장으로 작성하도록 규정했지만 별도 한글 설명도 없다.

근거

  • 테스트: HomeFollowingFragmentSourceTest.kthome layout exposes...부터 following recent news adapter binds...까지 영문 문장형 테스트명 11개
  • 가이드: docs/agent-guides/build-test-style.mddocs/agent-guides/code-style.md의 신규 테스트명 한글 규칙
  • 이력: 테스트명 규칙은 2026-05-28, 대상 테스트는 2026-06-25 이후 추가됨

재현 또는 검증 절차

  1. rg -n 'fun `[A-Za-z]' HomeFollowingFragmentSourceTest.kt로 대상 이름을 확인한다.
  2. 클래스의 완전한 영문 문장형 이름 11개와 가이드의 한글 문장 규칙을 대조한다.
  3. 테스트 동작은 통과하지만 명명 규칙 불일치가 재현된다.

영향

runtime 동작에는 영향이 없지만 동일 기능 테스트의 언어 관례가 섞이고, 완료된 Phase가 저장소 테스트 규칙을 충족한다는 판정과 어긋난다.

권장 조치

assertion과 production 코드는 바꾸지 않고 해당 11개 테스트명만 검증 의도가 드러나는 한글 문장으로 변경한다.

판정 기록

  • 2026-07-31 — 테스트 생성 이력, 현재 이름과 가이드를 대조해 확정하고 Phase 4 Task 4.9 / P4-R4로 전환.
  • 2026-07-31 — Task 4.9에서 대상 테스트명 11개를 한글 문장으로 변경하고 focused/팔로잉 회귀 검증을 완료.

7. 확정 항목의 plan·goal 전환

  • Phase 4에 Task 4.6 / P4-R1, Task 4.7 / P4-R2를 추가해 완료했다.
  • 추가 재점검에서 Task 4.8 / P4-R3를 추가했으며 구현·검증을 완료했다.
  • 최종 재점검에서 Task 4.9 / P4-R4를 추가했으며 테스트명 정리를 완료했다.

8. 리뷰 종료 판정

판정 항목 결과 근거
리뷰 범위 전체 확인 충족 UI→adapter→callback→공통 액션 경로 추적
후보 항목 판정 완료 충족 REV-P4-001~004 판정 완료
확정 항목 plan 반영 충족 Task 4.6~4.9 추가
검증 명령과 결과 기록 충족 focused/source test PASS와 수동 코드 추적

최종 결론: 확정 발견 사항 모두 수정 완료

남은 항목: 없음

9. 수정 후 검증 기록

  • 2026-07-30: REV-P4-001 보완으로 팔로잉 On Air item은 liveActionCoordinator.enterLiveRoom(item.liveId), 스케줄 item은 CreatorActivityType별 기존 Live/Content/Community Action을 호출하도록 연결했다. targetId <= 0L은 공통 action 호출 전 return하며 직접 Intent 또는 legacy extra 조립은 추가하지 않았다.
  • 2026-07-30: REV-P4-002 보완으로 HomeFollowingUiState.LoginRequired 분기에서 section 숨김 후 finishHomePullRefresh(HOME_TAB_FOLLOWING)을 호출하도록 변경했다. focused source test, 팔로잉 전체 회귀, v2.live.action.*, v2.content.action.*, v2.community.action.*, :app:compileDebugKotlin, :app:ktlintCheck, git diff --check PASS.
  • 2026-07-30: REV-P4-003 보완으로 HomeCreatorProfileImageLoader.loadHomeCreatorProfileImage()의 blank URL 분기에서 기존 Coil 요청을 dispose()로 해제한 뒤 drawable을 비우도록 변경했다. 구현 전 HomeCreatorProfileImageLoaderTest RED, 구현 후 focused GREEN, 팔로잉 전체 회귀와 신규 프로필 테스트, :app:mergeDebugResources, :app:compileDebugKotlin, :app:ktlintCheck, git diff --check PASS.
  • 2026-07-31 재점검: Fragment/source·공통 action·프로필 loader를 포함한 Phase 1~13 focused 회귀 113개 test, resource merge, Kotlin compile, ktlint PASS. 추가 확정 발견 사항 없음.
  • 2026-07-31 최종 재점검: HomeFollowingFragmentSourceTest의 영문 문장형 테스트명 11개를 REV-P4-004로 확정하고, production/test 동작을 변경하기 전에 Task 4.9 / P4-R4로 전환했다.
  • 2026-07-31 최종 검증: 통합 20개 suite·306개 test와 resource merge, Kotlin compile, ktlint가 PASS했다. 자동 검증 성공과 별개로 이름 규칙 위반 REV-P4-004는 Task 4.9의 수정 항목으로 유지했다.
  • 2026-07-31: REV-P4-004 보완으로 HomeFollowingFragmentSourceTest의 영문 문장형 테스트명 11개를 한글 문장으로 변경했다. ./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest" --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingNewsAdapterTest", 팔로잉 전체 회귀, :app:compileDebugKotlin, :app:ktlintCheck PASS.
  • 2026-07-31 이번 리뷰 재검증: surface 전환, section 상태, live/chat/schedule/news 공통 액션과 blank profile 요청 해제 경로를 다시 추적했다. 통합 16개 suite·120개 test, resource merge, Kotlin compile, ktlint가 PASS해 REV-P4-001~004 수정 완료 판정을 유지한다.