fix(home): 팔로잉 탭 후속 검증을 반영한다
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
# Phase 1 기존 구조와 작업 경계 리뷰
|
||||
|
||||
## 1. 리뷰 정보
|
||||
|
||||
| 항목 | 내용 |
|
||||
|---|---|
|
||||
| 리뷰 대상 | Phase 1 / Task 1.1~1.3 |
|
||||
| 기준 commit 또는 working tree | `f600d10e8b63b6fdc812b18a874b077dfe072ca8` + 2026-07-31 working tree |
|
||||
| 리뷰 일자 | 2026-07-31 |
|
||||
| 리뷰어 | Codex |
|
||||
| 기준 문서 | `docs/20260625_메인_홈_팔로잉_탭/prd.md`, `docs/20260625_메인_홈_팔로잉_탭/plan-task.md` |
|
||||
| 리뷰 상태 | 판정 완료 |
|
||||
|
||||
## 2. 리뷰 목적과 범위
|
||||
|
||||
### 목적
|
||||
|
||||
- 기존 홈 탭 삽입 지점, 재사용 후보, 제외 범위가 이후 구현과 일치하는지 확인한다.
|
||||
- 레거시 직접 수정이나 추천·랭킹 리팩터링으로 범위가 확장되지 않았는지 확인한다.
|
||||
|
||||
### 포함 범위
|
||||
|
||||
- `HomeMainFragment`, `fragment_v2_main_home.xml`, v2 홈 widget/mapper와 Phase 1 문서 기록.
|
||||
|
||||
### 제외 범위
|
||||
|
||||
- Phase 2 이후 구현의 동작 상세와 Figma 실기기 대조.
|
||||
|
||||
## 3. 판정 기준
|
||||
|
||||
- 심각도와 상태는 `docs/sample/sample-review.md`의 Blocker/High/Medium/Low 및 확정/오탐/보류 기준을 적용했다.
|
||||
- 완료 체크박스, 실제 코드 위치, 후속 Phase가 유지한 경계를 상호 대조했다.
|
||||
|
||||
## 4. 검토한 근거
|
||||
|
||||
### 문서와 코드
|
||||
|
||||
- `HomeMainFragment.kt:85-168`, `366-395`
|
||||
- `fragment_v2_main_home.xml:9-34`, `227-393`
|
||||
- `HomeCreatorProfileImageLoader`, `ChatRoomListItemResponse.toUiItems()`, `CreatorActivityType`
|
||||
- Phase 1 Task 1.1~1.3과 PRD Non-Goals
|
||||
|
||||
### 실행 환경
|
||||
|
||||
```text
|
||||
OS: Darwin 25.0.0 x86_64
|
||||
JDK: OpenJDK 17.0.15
|
||||
Gradle wrapper: 8.14.3
|
||||
환경 변수: 민감정보 확인/출력 없음
|
||||
```
|
||||
|
||||
### 실행한 검증
|
||||
|
||||
| 명령 또는 수동 검증 | 결과 | 핵심 증거 |
|
||||
|---|---|---|
|
||||
| `rg -n "HOME_TAB_FOLLOWING|showHomeTab|HomeCreatorProfileImageLoader|CreatorActivityType" ...` | 성공 | 홈 탭 분기와 재사용 경로 확인 |
|
||||
| Phase 1 문서와 현재 파일 구조 대조 | 성공 | 신규 팔로잉 코드는 `v2.main.home` 하위, 레거시는 호출만 사용 |
|
||||
|
||||
## 5. 발견 사항 요약
|
||||
|
||||
확정 발견 사항 없음.
|
||||
|
||||
## 6. 발견 사항 상세
|
||||
|
||||
해당 없음. 이후 별도 작업에서 도입된 로그인 가드와 pull refresh는 각각의 PRD/계획으로 관리되고 있어 Phase 1 범위 위반으로 판정하지 않았다.
|
||||
|
||||
## 7. 확정 항목의 plan·goal 전환
|
||||
|
||||
전환 항목 없음.
|
||||
|
||||
## 8. 리뷰 종료 판정
|
||||
|
||||
| 판정 항목 | 결과 | 근거 |
|
||||
|---|---|---|
|
||||
| 리뷰 범위 전체 확인 | 충족 | Task 1.1~1.3과 현재 구조 대조 완료 |
|
||||
| 후보 항목 판정 완료 | 충족 | 범위 확장 후보를 후속 문서 근거로 오탐 판정 |
|
||||
| 확정 항목 plan 반영 | 해당 없음 | 확정 발견 사항 없음 |
|
||||
| 검증 명령과 결과 기록 | 충족 | 검색·정적 대조 기록 |
|
||||
|
||||
**최종 결론:** 확정 발견 사항 없음
|
||||
|
||||
**남은 항목:** 없음
|
||||
|
||||
## 9. 수정 후 검증 기록
|
||||
|
||||
- 2026-07-31 재점검: Phase 1 경계와 현재 파일 구조를 다시 대조했고 기존 판정을 유지했다. Phase 1~13 focused 회귀 15개 suite/113개 test, resource merge, Kotlin compile, ktlint PASS.
|
||||
- 2026-07-31 최종 검증: 현재 경계·파일 구조 판정을 유지했다. 통합 20개 suite·306개 test, resource merge, Kotlin compile, ktlint, Gradle task 목록, staged/unstaged diff 검사가 모두 PASS했다.
|
||||
- 2026-07-31 이번 리뷰 재검증: Phase 1의 홈 탭 삽입 경계, v2 재사용 경로와 레거시 비수정 원칙을 현재 working tree에서 다시 대조했다. 통합 16개 suite·120개 test, resource merge, Kotlin compile, ktlint, staged/unstaged diff 검사가 PASS해 기존 “확정 발견 사항 없음” 판정을 유지한다.
|
||||
@@ -0,0 +1,178 @@
|
||||
# Phase 10 On Air 라이브 item 리뷰
|
||||
|
||||
## 1. 리뷰 정보
|
||||
|
||||
| 항목 | 내용 |
|
||||
|---|---|
|
||||
| 리뷰 대상 | Phase 10 / Task 10.1~10.4 |
|
||||
| 기준 commit 또는 working tree | `f600d10e8b63b6fdc812b18a874b077dfe072ca8` + 2026-07-31 working tree |
|
||||
| 리뷰 일자 | 2026-07-31 |
|
||||
| 리뷰어 | Codex |
|
||||
| 기준 문서 | 대상 `prd.md`, `plan-task.md` |
|
||||
| 리뷰 상태 | 수정 검증 완료 |
|
||||
|
||||
## 2. 리뷰 목적과 범위
|
||||
|
||||
### 목적
|
||||
|
||||
- 263dp × 100dp 캡슐 item의 필드·배경·profile binding과 가로 목록 배치를 확인한다.
|
||||
|
||||
### 포함 범위
|
||||
|
||||
- `item_home_following_live.xml`, `bg_home_following_live_capsule.xml`
|
||||
- `HomeFollowingLiveAdapter.kt`, following RecyclerView와 source test
|
||||
|
||||
### 제외 범위
|
||||
|
||||
- item 터치 이동은 Phase 4 `REV-P4-001`에서 별도 판정.
|
||||
|
||||
## 3. 판정 기준
|
||||
|
||||
- 캡슐 내부 표현은 Task 10.1, 가로 item 간격은 PRD UX의 item spacing과 기존 홈 helper 관례로 판정했다.
|
||||
|
||||
## 4. 검토한 근거
|
||||
|
||||
- `item_home_following_live.xml:2-99`
|
||||
- `bg_home_following_live_capsule.xml:2-8`
|
||||
- `HomeFollowingLiveAdapter.kt:23-31`
|
||||
- `HomeRecyclerItemLayoutParams.kt:7-14`
|
||||
- creator/chat adapter의 동일 horizontal item layout parameter 사용
|
||||
- `item_home_following_live.xml:5-6`: root `263dp x 100dp`
|
||||
|
||||
### 실행한 검증
|
||||
|
||||
| 명령 | 결과 | 핵심 증거 |
|
||||
|---|---|---|
|
||||
| 팔로잉 전체 회귀 | 성공 | 39개 테스트 실패 0 |
|
||||
| resource merge/compile/ktlint | 성공 | 모두 PASS |
|
||||
| adapter layout parameter 수동 대조 | 문제 확인 | live adapter만 end margin helper 미사용 |
|
||||
|
||||
## 5. 발견 사항 요약
|
||||
|
||||
| ID | 심각도 | 상태 | 제목 | 소유 Task | 후속 goal |
|
||||
|---|---|---|---|---|---|
|
||||
| `REV-P10-001` | Low | 수정 완료 | 연속된 On Air 캡슐 item 사이 간격이 없음 | Task 10.2 | `P10-R1` 완료 |
|
||||
| `REV-P10-002` | Low | 수정 완료 | On Air margin을 source 문자열 테스트로 고정해 UI 표현 속성 테스트 금지 규칙을 위반함 | Task 10.3 | `P10-R2` 완료 |
|
||||
| `REV-P10-003` | Medium | 수정 완료 | 간격 helper가 On Air root의 `263dp` 폭을 `WRAP_CONTENT`로 덮음 | Task 10.4 | `P10-R3` 완료 |
|
||||
|
||||
## 6. 발견 사항 상세
|
||||
|
||||
### REV-P10-001 — On Air 가로 item end margin 누락
|
||||
|
||||
- **심각도:** Low
|
||||
- **상태:** 수정 완료
|
||||
- **관련 요구사항:** PRD 가로 리스트 item 간격, Task 10.1 Figma 간격
|
||||
- **소유 Task:** Task 10.2
|
||||
|
||||
**관찰 내용**
|
||||
|
||||
live adapter는 XML을 inflate한 뒤 layout parameter를 그대로 반환한다. RecyclerView에는 ItemDecoration이 없어 두 번째 item부터 캡슐이 바로 붙는다. creator/chat adapter는 공통 helper로 `spacing_12` end margin을 적용한다.
|
||||
|
||||
**근거**
|
||||
|
||||
- 코드: `HomeFollowingLiveAdapter.kt:23-31`
|
||||
- 비교: `HomeFollowingCreatorAdapter.kt:28-30`, `HomeFollowingChatAdapter.kt:23-26`
|
||||
- helper: `HomeRecyclerItemLayoutParams.kt:7-14`
|
||||
|
||||
**영향**
|
||||
|
||||
On Air item이 2개 이상일 때 Figma/기존 홈 가로 리스트와 다른 비핵심 UI가 노출된다.
|
||||
|
||||
**권장 조치**
|
||||
|
||||
신규 decoration 없이 기존 `recyclerItemLayoutParams(parent)`를 재사용한다.
|
||||
|
||||
**판정 기록**
|
||||
|
||||
- 2026-07-30 — RecyclerView/adapter/helper 경로 대조로 확정.
|
||||
- 2026-07-30 — Task 10.2에서 기존 helper를 적용하고 resource/compile/회귀 검증을 완료.
|
||||
|
||||
### REV-P10-002 — On Air 간격 source test가 테스트 정책을 위반함
|
||||
|
||||
- **심각도:** Low
|
||||
- **상태:** 수정 완료
|
||||
- **관련 요구사항:** `docs/agent-guides/code-style.md` 테스트 관례
|
||||
- **소유 Task:** Task 10.3
|
||||
|
||||
**관찰 내용**
|
||||
|
||||
Task 10.2에서 추가한 `following live adapter keeps horizontal item spacing`은 `recyclerItemLayoutParams(parent)` 문자열을 검사해 item margin이라는 UI 표현 속성을 고정한다. 현재 가이드는 View 크기·margin·padding 같은 UI 표현 속성 테스트를 새로 작성하지 않도록 규정한다.
|
||||
|
||||
**근거**
|
||||
|
||||
- 테스트: `HomeFollowingFragmentSourceTest.kt:355-363`
|
||||
- 가이드: `docs/agent-guides/code-style.md`의 “신규 테스트는 로직에 대한 테스트 코드만 작성” 및 UI margin 테스트 금지 규칙
|
||||
- production: `HomeFollowingLiveAdapter.kt:23-30`의 helper 적용은 현재 유지되어야 함
|
||||
|
||||
**영향**
|
||||
|
||||
기능에는 영향이 없지만 금지된 테스트 유형이 회귀 Gate에 추가되고, 내부 구현 문자열 변경만으로 불필요한 실패가 발생한다.
|
||||
|
||||
**권장 조치**
|
||||
|
||||
해당 신규 source test만 제거하고 adapter의 helper 적용은 유지한다. 이 UI 간격은 `rg` 정적 대조, resource merge, compile, 수동 화면 확인으로 검증한다.
|
||||
|
||||
**판정 기록**
|
||||
|
||||
- 2026-07-30 — 신규 테스트 diff와 현재 코드 스타일 가이드를 대조해 확정.
|
||||
- 2026-07-30 — Task 10.3에서 금지된 UI margin source test만 제거하고 helper 재사용 대체 검증을 완료.
|
||||
|
||||
### REV-P10-003 — 간격 보완이 On Air 고정 폭을 보존하지 않음
|
||||
|
||||
- **심각도:** Medium
|
||||
- **상태:** 수정 완료
|
||||
- **관련 요구사항:** Task 10.1 `263dp x 100dp`, Task 10.2 “기존 XML 크기 유지”
|
||||
- **소유 Task:** Task 10.4
|
||||
|
||||
**관찰 내용**
|
||||
|
||||
Task 10.2는 `recyclerItemLayoutParams(parent)`를 적용해 XML 크기를 유지했다고 기록했지만, helper는 새 `RecyclerView.LayoutParams(WRAP_CONTENT, WRAP_CONTENT)`를 반환한다. 따라서 inflate된 root의 `263dp x 100dp` 중 width 계약이 런타임에 `WRAP_CONTENT`로 교체된다.
|
||||
|
||||
**근거**
|
||||
|
||||
- layout: `item_home_following_live.xml:5-6`
|
||||
- adapter: `HomeFollowingLiveAdapter.kt:23-30`
|
||||
- helper: `HomeRecyclerItemLayoutParams.kt:7-14`
|
||||
- 문서: Task 10.2 완료 증거와 검증 기록
|
||||
|
||||
**영향**
|
||||
|
||||
On Air 캡슐의 폭이 자식 content 측정값에 따라 축소되거나 달라져 제목/상태 영역과 연속 item 배치가 Figma와 불일치할 수 있다.
|
||||
|
||||
**권장 조치**
|
||||
|
||||
inflate된 기존 layout parameter의 width/height는 보존하고 `spacing_12` end margin만 추가한다. UI width/margin 자동 테스트는 다시 추가하지 않고 정적 대조·resource merge·compile·Task 5.3 수동 확인으로 검증한다.
|
||||
|
||||
**판정 기록**
|
||||
|
||||
- 2026-07-30 — XML root 크기와 adapter/helper의 최종 layout parameter를 대조해 확정.
|
||||
- 2026-07-30 — 구현 전 Phase 10 Task 10.4 / `P10-R3`로 전환.
|
||||
- 2026-07-30 — Task 10.4에서 inflate된 root의 기존 layout parameter를 보존하고 end margin만 적용하도록 수정했다.
|
||||
|
||||
## 7. 확정 항목의 plan·goal 전환
|
||||
|
||||
- Phase 10에 Task 10.2 / `P10-R1`을 추가해 완료했다.
|
||||
- 재점검에서 Task 10.3 / `P10-R2`를 추가해 완료했다.
|
||||
- 추가 재점검에서 Task 10.4 / `P10-R3`를 추가해 완료했다.
|
||||
|
||||
## 8. 리뷰 종료 판정
|
||||
|
||||
| 판정 항목 | 결과 | 근거 |
|
||||
|---|---|---|
|
||||
| 리뷰 범위 전체 확인 | 충족 | layout/drawable/adapter 대조 |
|
||||
| 후보 항목 판정 완료 | 충족 | REV-P10-001~003 판정 완료 |
|
||||
| 확정 항목 plan 반영 | 충족 | Task 10.2, Task 10.3, Task 10.4 |
|
||||
| 검증 명령과 결과 기록 | 충족 | 빌드 Gate PASS |
|
||||
|
||||
**최종 결론:** 확정 발견 사항 모두 수정 완료
|
||||
|
||||
**남은 항목:** 없음
|
||||
|
||||
## 9. 수정 후 검증 기록
|
||||
|
||||
- 2026-07-30: `HomeFollowingLiveAdapter.onCreateViewHolder()`에서 기존 horizontal list helper `recyclerItemLayoutParams(parent)`를 재사용해 XML 크기는 유지하고 `spacing_12` end margin을 적용했다. `HomeFollowingFragmentSourceTest`, 팔로잉 전체 회귀, resource merge, Kotlin compile, ktlint, `git diff --check` PASS.
|
||||
- 2026-07-30: Task 10.3으로 `following live adapter keeps horizontal item spacing` source test만 제거하고 production helper 적용은 유지했다. `rg`로 `HomeFollowingLiveAdapter`의 `recyclerItemLayoutParams(parent)` 재사용을 대조했고 팔로잉 전체 회귀, resource merge, Kotlin compile, ktlint, `git diff --check` PASS.
|
||||
- 2026-07-30: Task 10.4로 `HomeFollowingLiveAdapter`가 `recyclerItemLayoutParams(parent)` 대신 inflate된 `RecyclerView.LayoutParams`를 보존하고 `spacing_12` end margin만 적용하도록 수정했다. focused test, 팔로잉 전체 회귀, resource merge, Kotlin compile, ktlint PASS. 연결 기기가 없어 실기기 확인은 Task 5.3 보류 상태를 유지했다.
|
||||
- 2026-07-31 재점검: On Air binding/action을 포함한 Phase 1~13 focused 113개 test, resource merge, Kotlin compile, ktlint PASS. 연결 기기가 없어 실기기 폭/간격 확인은 Task 5.3에 유지했다.
|
||||
- 2026-07-31 최종 검증: On Air binding/action 회귀를 포함한 통합 20개 suite·306개 test와 resource merge, Kotlin compile, ktlint가 PASS했다. 추가 확정 수정 사항은 없고 실기기 확인은 Phase 5 Task 5.3에 유지한다.
|
||||
- 2026-07-31 이번 리뷰 재검증: On Air 캡슐의 XML 고정 크기 보존, end margin과 live action 경로를 다시 추적했다. 통합 16개 suite·120개 test, resource merge, Kotlin compile, ktlint가 PASS해 `REV-P10-001~003` 수정 완료 판정을 유지하고 시각 대조는 Phase 5 Task 5.3에 유지한다.
|
||||
@@ -0,0 +1,77 @@
|
||||
# Phase 11 COMMUNITY_POST 상세 이동 리뷰
|
||||
|
||||
## 1. 리뷰 정보
|
||||
|
||||
| 항목 | 내용 |
|
||||
|---|---|
|
||||
| 리뷰 대상 | Phase 11 / Task 11.1~11.3 |
|
||||
| 기준 commit 또는 working tree | `f600d10e8b63b6fdc812b18a874b077dfe072ca8` + 2026-07-31 working tree |
|
||||
| 리뷰 일자 | 2026-07-31 |
|
||||
| 리뷰어 | Codex |
|
||||
| 기준 문서 | 대상 `prd.md`, `plan-task.md`, 공통 community action 문서 |
|
||||
| 리뷰 상태 | 판정 완료 |
|
||||
|
||||
## 2. 리뷰 목적과 범위
|
||||
|
||||
### 목적
|
||||
|
||||
- COMMUNITY_POST가 유효한 `postId`로 상세 이동하고 legacy extra 조립을 사용하지 않는지 확인한다.
|
||||
- 후속 공통 도메인 액션 리팩터링이 Phase 11 의도를 유지하는지 확인한다.
|
||||
|
||||
### 포함 범위
|
||||
|
||||
- `HomeMainFragment.onFollowingNewsClick()`
|
||||
- `CommunityActionCommand.PostDetail`, handler와 source test
|
||||
|
||||
### 제외 범위
|
||||
|
||||
- 상세 Activity 내부 데이터 로딩과 다른 news type 이동.
|
||||
|
||||
## 3. 판정 기준
|
||||
|
||||
- 유효 ID 검증, Login access, `CreatorChannelCommunityDetailActivity` intent 생성과 legacy 참조 부재를 기준으로 판정했다.
|
||||
|
||||
## 4. 검토한 근거
|
||||
|
||||
- `HomeMainFragment.kt:673-686`
|
||||
- `CommunityAction.kt:5-20`
|
||||
- `CommunityActionHandler.kt:13-42`
|
||||
- `HomeMainFragmentLoginGuardSourceTest.kt:53-76`
|
||||
|
||||
### 실행한 검증
|
||||
|
||||
| 명령 | 결과 | 핵심 증거 |
|
||||
|---|---|---|
|
||||
| `HomeMainFragmentLoginGuardSourceTest` | 성공 | source 계약 PASS |
|
||||
| 팔로잉 전체 회귀/compile/ktlint/diff | 성공 | 모두 PASS |
|
||||
|
||||
## 5. 발견 사항 요약
|
||||
|
||||
확정 발견 사항 없음.
|
||||
|
||||
## 6. 발견 사항 상세
|
||||
|
||||
`postId <= 0L`은 Fragment와 공통 action에서 모두 무시되고, 유효 ID만 공통 Login access 후 `CreatorChannelCommunityDetailActivity`로 이동한다. Phase 11의 직접 intent 표현은 후속 공통 action 리팩터링으로 대체되었지만 사용자 동작과 보안 정책은 유지된다.
|
||||
|
||||
## 7. 확정 항목의 plan·goal 전환
|
||||
|
||||
전환 항목 없음.
|
||||
|
||||
## 8. 리뷰 종료 판정
|
||||
|
||||
| 판정 항목 | 결과 | 근거 |
|
||||
|---|---|---|
|
||||
| 리뷰 범위 전체 확인 | 충족 | Fragment→Community Action→Activity 추적 |
|
||||
| 후보 항목 판정 완료 | 충족 | 추가 후보 없음 |
|
||||
| 확정 항목 plan 반영 | 해당 없음 | 확정 발견 사항 없음 |
|
||||
| 검증 명령과 결과 기록 | 충족 | focused/통합 PASS |
|
||||
|
||||
**최종 결론:** 확정 발견 사항 없음
|
||||
|
||||
**남은 항목:** 없음
|
||||
|
||||
## 9. 수정 후 검증 기록
|
||||
|
||||
- 2026-07-31 재점검: COMMUNITY_POST 공통 action과 ID guard를 다시 추적했고 Phase 1~13 focused 113개 test, resource merge, Kotlin compile, ktlint PASS. 추가 확정 발견 사항 없음.
|
||||
- 2026-07-31 최종 검증: COMMUNITY_POST route 회귀를 포함한 통합 20개 suite·306개 test와 Kotlin compile, ktlint가 PASS했다. 추가 확정 발견 사항 없음.
|
||||
- 2026-07-31 이번 리뷰 재검증: `COMMUNITY_POST`의 양수 `postId` 가드와 공통 Community Action 이동을 다시 추적했다. 통합 16개 suite·120개 test, Kotlin compile, ktlint가 PASS해 기존 “확정 발견 사항 없음” 판정을 유지한다.
|
||||
111
docs/20260625_메인_홈_팔로잉_탭/reviews/phase12-empty-state-review.md
Normal file
111
docs/20260625_메인_홈_팔로잉_탭/reviews/phase12-empty-state-review.md
Normal file
@@ -0,0 +1,111 @@
|
||||
# Phase 12 전체 empty 상태 리뷰
|
||||
|
||||
## 1. 리뷰 정보
|
||||
|
||||
| 항목 | 내용 |
|
||||
|---|---|
|
||||
| 리뷰 대상 | Phase 12 / Task 12.1~12.4 |
|
||||
| 기준 commit 또는 working tree | `f600d10e8b63b6fdc812b18a874b077dfe072ca8` + 2026-07-31 working tree |
|
||||
| 리뷰 일자 | 2026-07-31 |
|
||||
| 리뷰어 | Codex |
|
||||
| 기준 문서 | 대상 `prd.md`, `plan-task.md` |
|
||||
| 리뷰 상태 | 수정 검증 완료 |
|
||||
|
||||
## 2. 리뷰 목적과 범위
|
||||
|
||||
### 목적
|
||||
|
||||
- Empty에서만 중앙 문구를 표시하고 Content/LoginRequired/Error에서는 숨기는지 확인한다.
|
||||
- 한국어·영어·일본어 문구와 resource merge를 확인한다.
|
||||
|
||||
### 포함 범위
|
||||
|
||||
- `fragment_v2_main_home.xml`, `HomeMainFragment` empty/content binding, 3개 locale string, mapper Empty 조건과 source test.
|
||||
|
||||
### 제외 범위
|
||||
|
||||
- 로그인 유도 문구·CTA와 실기기 typography 시각 대조.
|
||||
|
||||
## 3. 판정 기준
|
||||
|
||||
- PRD의 전체 section empty 조건, fillViewport surface, locale별 문구와 visibility 분기를 기준으로 판정했다.
|
||||
|
||||
## 4. 검토한 근거
|
||||
|
||||
- `HomeFollowingUiState.kt:8-23`
|
||||
- `HomeFollowingMappers.kt:18-35`
|
||||
- `fragment_v2_main_home.xml:237-277`
|
||||
- `HomeMainFragment.kt:397-419`, `503-524`
|
||||
- `HomeFollowingFragmentSourceTest.kt:104-147`
|
||||
|
||||
### 실행한 검증
|
||||
|
||||
| 명령 | 결과 | 핵심 증거 |
|
||||
|---|---|---|
|
||||
| mapper/source/팔로잉 전체 회귀 | 성공 | 관련 테스트 실패 0 |
|
||||
| resource merge/compile/ktlint/diff | 성공 | 모두 PASS |
|
||||
|
||||
## 5. 발견 사항 요약
|
||||
|
||||
| ID | 심각도 | 상태 | 제목 | 소유 Task | 후속 goal |
|
||||
|---|---|---|---|---|---|
|
||||
| `REV-P12-001` | Low | 수정 완료 | empty source test가 금지된 크기·정렬·visibility 표현을 고정함 | Task 12.4 | `P12-R1` 완료 |
|
||||
|
||||
## 6. 발견 사항 상세
|
||||
|
||||
모든 표시 section이 비었을 때만 mapper가 `Empty`를 만들고, Fragment는 empty 문구를 표시하면서 adapter와 section을 비운다. Content/LoginRequired/Error의 숨김 경로와 세 locale 문구도 요구사항과 일치한다.
|
||||
|
||||
### REV-P12-001 — empty source test가 UI 표현 속성 정책을 위반함
|
||||
|
||||
- **심각도:** Low
|
||||
- **상태:** 수정 완료
|
||||
- **관련 요구사항:** `docs/agent-guides/code-style.md` 테스트 관례
|
||||
- **소유 Task:** Task 12.4
|
||||
|
||||
**관찰 내용**
|
||||
|
||||
`following empty state shows centered reusable empty string only for all empty content` 테스트는 XML width/height/gravity/textAlignment/visibility와 Fragment의 직접 `View.VISIBLE/GONE` 문자열을 assertion한다. 이 테스트는 UI 크기·constraint·visibility 테스트 금지 규칙이 추가된 뒤 생성되었다.
|
||||
|
||||
**근거**
|
||||
|
||||
- 테스트: `HomeFollowingFragmentSourceTest.kt:107-150`
|
||||
- 가이드: `docs/agent-guides/code-style.md:42-43`
|
||||
- 이력: 가이드 규칙 `566f76df` 이후 테스트 `2c609836`, locale 문자열 assertion `dadf3a51` 추가
|
||||
|
||||
**영향**
|
||||
|
||||
mapper의 Empty 판정과 locale 문구라는 유효한 계약에 UI 배치 구현 문자열이 섞여 있어, 디자인 조정이 기능 회귀처럼 실패하고 현재 테스트 정책과 불일치한다.
|
||||
|
||||
**권장 조치**
|
||||
|
||||
mapper Empty 조건·locale 문구·상태 분기 검증은 유지하고 width/height/정렬/직접 visibility assertion만 제거한다. 중앙 배치는 정적 대조와 Task 5.3 실기기 확인으로 검증한다.
|
||||
|
||||
**판정 기록**
|
||||
|
||||
- 2026-07-30 — 테스트 추가 시점과 assertion 범위를 현행 가이드와 대조해 확정.
|
||||
- 2026-07-30 — 구현 전 Phase 12 Task 12.4 / `P12-R1`로 전환.
|
||||
- 2026-07-30 — Task 12.4에서 UI 표현 source assertion만 제거하고 locale 문구와 상태 분기 검증을 유지했다.
|
||||
|
||||
## 7. 확정 항목의 plan·goal 전환
|
||||
|
||||
- Phase 12에 Task 12.4 / `P12-R1`을 추가해 완료했다.
|
||||
|
||||
## 8. 리뷰 종료 판정
|
||||
|
||||
| 판정 항목 | 결과 | 근거 |
|
||||
|---|---|---|
|
||||
| 리뷰 범위 전체 확인 | 충족 | mapper→layout→binding→resource 추적 |
|
||||
| 후보 항목 판정 완료 | 충족 | REV-P12-001 확정 |
|
||||
| 확정 항목 plan 반영 | 충족 | Task 12.4 |
|
||||
| 검증 명령과 결과 기록 | 충족 | focused/통합 PASS |
|
||||
|
||||
**최종 결론:** 확정 발견 사항 모두 수정 완료
|
||||
|
||||
**남은 항목:** 실기기 중앙 정렬 대조는 Phase 5 Task 5.3에 포함
|
||||
|
||||
## 9. 수정 후 검증 기록
|
||||
|
||||
- 2026-07-30: Task 12.4로 empty source test명을 한글화하고 width/height/gravity/textAlignment/visibility 및 직접 `View.VISIBLE/GONE` 문자열 assertion을 제거했다. 3개 locale 문구와 `HomeFollowingUiState.Empty` 상태 분기 검증은 유지했다. focused test, 팔로잉 전체 회귀, resource merge, Kotlin compile, ktlint PASS.
|
||||
- 2026-07-31 재점검: Empty mapper/state/locale 회귀를 포함한 Phase 1~13 focused 113개 test, resource merge, Kotlin compile, ktlint PASS. 연결 기기가 없어 중앙 정렬 실기기 확인은 Task 5.3에 유지했다.
|
||||
- 2026-07-31 최종 검증: empty state·locale 회귀를 포함한 통합 20개 suite·306개 test와 resource merge, Kotlin compile, ktlint가 PASS했다. 추가 확정 수정 사항은 없고 실기기 중앙 정렬 확인은 Phase 5 Task 5.3에 유지한다.
|
||||
- 2026-07-31 이번 리뷰 재검증: 전체 section empty mapper 조건, 세 locale 문구와 상태별 표시 분기를 다시 대조했다. 통합 16개 suite·120개 test, resource merge, Kotlin compile, ktlint가 PASS해 `REV-P12-001` 수정 완료 판정을 유지하고 중앙 정렬 시각 대조는 Phase 5 Task 5.3에 유지한다.
|
||||
@@ -0,0 +1,87 @@
|
||||
# Phase 13 CREATOR_RANKING·AUDIO_CONTENT 이동 리뷰
|
||||
|
||||
## 1. 리뷰 정보
|
||||
|
||||
| 항목 | 내용 |
|
||||
|---|---|
|
||||
| 리뷰 대상 | Phase 13 / Task 13.1~13.3 |
|
||||
| 기준 commit 또는 working tree | `f600d10e8b63b6fdc812b18a874b077dfe072ca8` + 2026-07-31 working tree |
|
||||
| 리뷰 일자 | 2026-07-31 |
|
||||
| 리뷰어 | Codex |
|
||||
| 기준 문서 | 대상 `prd.md`, `plan-task.md`, 공통 creator/content/community action |
|
||||
| 리뷰 상태 | 판정 완료 |
|
||||
|
||||
## 2. 리뷰 목적과 범위
|
||||
|
||||
### 목적
|
||||
|
||||
- 미커밋 Phase 13 변경이 요청된 두 news type만 기존 공통 액션으로 이동시키는지 확인한다.
|
||||
- 기존 COMMUNITY_POST와 명시적 no-op인 CONTENT_RANKING/PHOTO_CONTENT를 회귀시키지 않는지 확인한다.
|
||||
|
||||
### 포함 범위
|
||||
|
||||
- `HomeMainFragment.onFollowingNewsClick()`
|
||||
- `HomeMainFragmentLoginGuardSourceTest`
|
||||
- `CreatorAction`, `ContentAction`, `CommunityAction`의 ID/access 정책
|
||||
- Phase 13 PRD/Task/검증 기록
|
||||
|
||||
### 제외 범위
|
||||
|
||||
- CONTENT_RANKING/PHOTO_CONTENT 신규 이동, API/DTO/mapper/UI 변경, 실제 기기 터치.
|
||||
|
||||
## 3. 판정 기준
|
||||
|
||||
- type 판별, payload target ID, 공통 액션 재사용, invalid ID 무시와 기존 COMMUNITY_POST 유지 여부를 기준으로 판정했다.
|
||||
|
||||
## 4. 검토한 근거
|
||||
|
||||
- working diff의 `HomeMainFragment.kt:673-687`
|
||||
- `HomeMainFragmentLoginGuardSourceTest.kt:53-104`
|
||||
- `CreatorAction.kt`, `ContentAction.kt`, `CommunityAction.kt`의 양수 ID 검증과 access 정책
|
||||
- Phase 13 Task 13.1~13.3
|
||||
|
||||
### 실행한 검증
|
||||
|
||||
| 명령 | 결과 | 핵심 증거 |
|
||||
|---|---|---|
|
||||
| `HomeMainFragmentLoginGuardSourceTest` | 성공 | 13개 테스트 실패 0 |
|
||||
| 팔로잉 전체 회귀 | 성공 | 39개 테스트 실패 0 |
|
||||
| resource merge/compile/ktlint/diff | 성공 | 모두 PASS |
|
||||
| `adb devices` | 기기 없음 | 실제 터치 미실행 |
|
||||
|
||||
## 5. 발견 사항 요약
|
||||
|
||||
확정 발견 사항 없음.
|
||||
|
||||
## 6. 발견 사항 상세
|
||||
|
||||
- `CREATOR_RANKING`만 `CreatorActionCommand.Profile(item.targetId)`로 전달된다.
|
||||
- `AUDIO_CONTENT`만 `ContentActionCommand.AudioDetail(item.contentId)`로 전달된다.
|
||||
- 두 공통 action은 양수 ID와 access requirement를 자체 검증한다.
|
||||
- COMMUNITY_POST의 `postId` 가드와 상세 이동은 유지된다.
|
||||
- CONTENT_RANKING/PHOTO_CONTENT는 조건 불일치로 no-op을 유지한다.
|
||||
|
||||
실기기 터치는 연결 기기 부재로 실행하지 못했지만 Task 13.3이 이 경우 사유 기록을 완료 조건으로 허용하므로 보류 finding으로 전환하지 않았다.
|
||||
|
||||
## 7. 확정 항목의 plan·goal 전환
|
||||
|
||||
전환 항목 없음.
|
||||
|
||||
## 8. 리뷰 종료 판정
|
||||
|
||||
| 판정 항목 | 결과 | 근거 |
|
||||
|---|---|---|
|
||||
| 리뷰 범위 전체 확인 | 충족 | working diff와 공통 액션 end-to-end 추적 |
|
||||
| 후보 항목 판정 완료 | 충족 | 추가 후보 없음 |
|
||||
| 확정 항목 plan 반영 | 해당 없음 | 확정 발견 사항 없음 |
|
||||
| 검증 명령과 결과 기록 | 충족 | focused/통합/build PASS |
|
||||
|
||||
**최종 결론:** 확정 발견 사항 없음
|
||||
|
||||
**남은 항목:** 없음
|
||||
|
||||
## 9. 수정 후 검증 기록
|
||||
|
||||
- 2026-07-31 재점검: CREATOR_RANKING·AUDIO_CONTENT·COMMUNITY_POST 공통 action 경로를 다시 추적했고 Phase 1~13 focused 113개 test, resource merge, Kotlin compile, ktlint PASS. 추가 확정 발견 사항 없음.
|
||||
- 2026-07-31 최종 검증: 최근 소식 상세 route 회귀를 포함한 통합 20개 suite·306개 test와 Kotlin compile, ktlint가 PASS했다. 추가 확정 발견 사항 없음.
|
||||
- 2026-07-31 이번 리뷰 재검증: `CREATOR_RANKING`, `AUDIO_CONTENT`, 기존 `COMMUNITY_POST` 공통 액션과 `CONTENT_RANKING`·`PHOTO_CONTENT` no-op 범위를 다시 추적했다. 통합 16개 suite·120개 test, Kotlin compile, ktlint가 PASS해 기존 “확정 발견 사항 없음” 판정을 유지한다.
|
||||
@@ -0,0 +1,173 @@
|
||||
# Phase 2 API·DTO·Repository·mapper 리뷰
|
||||
|
||||
## 1. 리뷰 정보
|
||||
|
||||
| 항목 | 내용 |
|
||||
|---|---|
|
||||
| 리뷰 대상 | Phase 2 / Task 2.1~2.8 |
|
||||
| 기준 commit 또는 working tree | `f600d10e8b63b6fdc812b18a874b077dfe072ca8` + 2026-07-31 working tree |
|
||||
| 리뷰 일자 | 2026-07-31 |
|
||||
| 리뷰어 | Codex |
|
||||
| 기준 문서 | 대상 `prd.md`, `plan-task.md`, `docs/agent-guides/code-style.md` |
|
||||
| 리뷰 상태 | 수정 검증 완료 |
|
||||
|
||||
## 2. 리뷰 목적과 범위
|
||||
|
||||
### 목적
|
||||
|
||||
- endpoint, optional auth header, DTO nested payload, mapper 상태 계약과 locale resource가 현재 PRD를 충족하는지 확인한다.
|
||||
- Phase 9에서 교체된 최근 소식 계약을 Phase 2의 과거 기록과 혼동하지 않고 현재 계약 기준으로 판정한다.
|
||||
|
||||
### 포함 범위
|
||||
|
||||
- `HomeFollowingApi.kt`, `HomeFollowingModels.kt`, `HomeFollowingRepository.kt`
|
||||
- `HomeFollowingAuthHeader.kt`, `HomeFollowingUiState.kt`, `HomeFollowingUiModels.kt`, `HomeFollowingMappers.kt`
|
||||
- `HomeFollowingAuthHeaderTest`, `HomeFollowingMapperTest`, `HomeFollowingNewsAdapterTest`, 관련 string resource와 DI
|
||||
|
||||
### 제외 범위
|
||||
|
||||
- Fragment 표시·터치 이동과 서버 `permitAll` 실제 설정.
|
||||
|
||||
## 3. 판정 기준
|
||||
|
||||
- PRD endpoint/response contract, Gson/Kotlin 관례, mapper의 login/empty/content 분기와 `docs/sample/sample-review.md` 심각도 기준을 적용했다.
|
||||
|
||||
## 4. 검토한 근거
|
||||
|
||||
### 문서와 코드
|
||||
|
||||
- `HomeFollowingApi.kt:8-12`: query 없는 `GET /api/v2/home/following`, nullable header
|
||||
- `HomeFollowingModels.kt:8-111`: DTO와 nested payload
|
||||
- `HomeFollowingMappers.kt:18-158`: LoginRequired/Empty/Content, matching payload 필터, locale label
|
||||
- `HomeFollowingNewsAdapter.kt:155-171`: UI model label을 읽지 않고 `FollowingNewsType.toFeedContentCategory()`로 표시 label을 결정
|
||||
- `AppDI.kt`: API/Repository 등록
|
||||
|
||||
### 실행 환경
|
||||
|
||||
```text
|
||||
OS: Darwin 25.0.0 x86_64
|
||||
JDK: OpenJDK 17.0.15
|
||||
Gradle wrapper: 8.14.3
|
||||
```
|
||||
|
||||
### 실행한 검증
|
||||
|
||||
| 명령 | 결과 | 핵심 증거 |
|
||||
|---|---|---|
|
||||
| `./gradlew --no-daemon :app:testDebugUnitTest --tests "...HomeFollowingAuthHeaderTest" --tests "...HomeFollowingMapperTest" --tests "...HomeFollowingViewModelTest"` | 성공 | 전체 20개 중 Phase 2 대상 13개(auth 3, mapper 10) 실패 0 |
|
||||
| `./gradlew --no-daemon :app:mergeDebugResources :app:compileDebugKotlin :app:ktlintCheck` | 성공 | resource/compile/style PASS |
|
||||
| 2026-07-31 Phase 1~13 통합 focused 회귀 | 성공 | 15개 suite, 113개 test, failures/errors 0 |
|
||||
| `git diff --check` | 성공 | whitespace 오류 없음 |
|
||||
|
||||
## 5. 발견 사항 요약
|
||||
|
||||
| ID | 심각도 | 상태 | 제목 | 소유 Task | 후속 goal |
|
||||
|---|---|---|---|---|---|
|
||||
| `REV-P2-001` | Low | 수정 완료 | 후속 UI·오류 처리 변경 후 미사용 팔로잉 string resource 3개가 남음 | Task 2.7 | `P2-R1` 완료 |
|
||||
| `REV-P2-002` | Low | 수정 완료 | Feed category 전환 후 미사용 `Content.labelResId`와 mapper가 남음 | Task 2.8 | `P2-R2` 완료 |
|
||||
|
||||
## 6. 발견 사항 상세
|
||||
|
||||
- Phase 2 기록의 `rank == null` 필터 문구는 Phase 9 nested payload 계약에서 `rank: Int`로 확정된 현재 계약에 의해 대체되었다. 현재 DTO·fixture·mapper가 동일 계약을 사용하므로 결함이 아닌 과거 기록으로 판정했다.
|
||||
|
||||
### REV-P2-001 — 후속 UI·오류 처리 변경 후 미사용 팔로잉 string resource가 남음
|
||||
|
||||
- **심각도:** Low
|
||||
- **상태:** 수정 완료
|
||||
- **관련 요구사항:** Task 2.4 string resource, Phase 6 팔로잉 크리에이터 header 제거, Task 3.2 공통 오류 Toast 패턴
|
||||
- **소유 Task:** Task 2.7
|
||||
|
||||
**관찰 내용**
|
||||
|
||||
`screen_home_following_creators_title`, `screen_home_following_on_air_title`, `screen_home_following_error`는 `values`, `values-en`, `values-ja`에 모두 선언되어 있지만 production/test/layout에서 참조되지 않는다. On Air 섹션과 상태는 `screen_home_following_on_air`를 사용하고, API 오류는 `common_error_unknown` Toast를 사용한다.
|
||||
|
||||
**근거**
|
||||
|
||||
- resource: `app/src/main/res/values/strings.xml:311-322`, `values-en/strings.xml:312-323`, `values-ja/strings.xml:312-323`
|
||||
- code: `HomeMainFragment.kt:627-640`, `HomeFollowingViewModel.kt:73-75`
|
||||
- 검색: 각 대상 key의 `R.string` / `@string` production/test 참조 0건
|
||||
|
||||
**재현 또는 검증 절차**
|
||||
|
||||
1. 3개 locale string file에서 위 key 선언을 확인한다.
|
||||
2. `rg`로 `app/src/main`, `app/src/test`의 resource 참조를 검색한다.
|
||||
3. 실제 결과는 선언 외 참조 0건이다.
|
||||
|
||||
**영향**
|
||||
|
||||
런타임 오류는 없지만 번역·유지보수 대상을 불필요하게 늘리고, 후속 작업자가 현재 UI에 필요한 계약으로 오인할 수 있다.
|
||||
|
||||
**권장 조치**
|
||||
|
||||
3개 locale에서 위 3개 미사용 key만 제거하고, 사용 중인 `screen_home_following_on_air`와 나머지 팔로잉 문자열은 유지한다.
|
||||
|
||||
**판정 기록**
|
||||
|
||||
- 2026-07-30 — 3개 locale 선언과 production/test/layout 참조를 대조해 확정.
|
||||
- 2026-07-30 — 코드는 수정하지 않고 Phase 2 Task 2.7 / `P2-R1`로 전환.
|
||||
|
||||
### REV-P2-002 — Feed category 전환 후 미사용 label UI model이 남음
|
||||
|
||||
- **심각도:** Low
|
||||
- **상태:** 수정 완료
|
||||
- **관련 요구사항:** Task 2.6 최근 소식 UI model/mapper, Task 6.4 Feed 위젯 재사용
|
||||
- **소유 Task:** Task 2.8
|
||||
|
||||
**관찰 내용**
|
||||
|
||||
`HomeFollowingNewsUiItem.Content.labelResId`는 mapper가 값을 대입하고 test fixture가 검증하지만 production adapter는 이 필드를 읽지 않는다. 실제 label은 `content.type.toFeedContentCategory()`과 `FeedContentCategory.labelResId`에서 결정된다.
|
||||
|
||||
**근거**
|
||||
|
||||
- UI model: `HomeFollowingUiModels.kt:74-86`
|
||||
- mapper: `HomeFollowingMappers.kt:111-128`, `151-158`
|
||||
- runtime: `HomeFollowingNewsAdapter.kt:155-171`, `FeedContentCategory.kt:6-15`
|
||||
- 검색: 팔로잉 `Content.labelResId`의 production read 0건, test/fixture만 참조
|
||||
|
||||
**재현 또는 검증 절차**
|
||||
|
||||
1. `rg -n "labelResId|toLabelResId"` 결과에서 팔로잉 최근 소식 model·mapper·test 참조를 확인한다.
|
||||
2. `HomeFollowingNewsAdapter.ContentViewHolder.bind()`의 category/label 결정 경로를 추적한다.
|
||||
3. 실제 결과는 `labelResId`를 읽지 않고 `FeedContentCategory.Audio/Photo`를 사용한다.
|
||||
|
||||
**영향**
|
||||
|
||||
런타임 표시 오류는 없지만 동일 label 계약이 UI model mapper와 Feed category에 이중으로 남아 후속 문구·category 변경 시 test와 production이 엇갈릴 수 있다.
|
||||
|
||||
**권장 조치**
|
||||
|
||||
미사용 `Content.labelResId`와 `FollowingNewsType.toLabelResId()`만 제거하고, 실제 표시 경로인 `FeedContentCategory.Audio/Photo`와 locale string 회귀를 유지한다.
|
||||
|
||||
**판정 기록**
|
||||
|
||||
- 2026-07-31 — production/test 참조와 Feed binding 경로를 대조해 확정.
|
||||
- 2026-07-31 — production은 수정하지 않고 Phase 2 Task 2.8 / `P2-R2`로 전환.
|
||||
- 2026-07-31 — Task 2.8에서 미사용 UI model 필드와 mapper를 제거하고 Feed category label 회귀 검증을 완료.
|
||||
|
||||
## 7. 확정 항목의 plan·goal 전환
|
||||
|
||||
- `plan-task.md` Phase 2에 Task 2.7 / `P2-R1`을 추가했다.
|
||||
- objective: `[P2-R1]의 REV-P2-001을 최소 resource 삭제로 정리하고 팔로잉 resource 회귀를 방지한다.`
|
||||
- `plan-task.md` Phase 2에 Task 2.8 / `P2-R2`를 추가했다.
|
||||
- objective: `[P2-R2]의 REV-P2-002를 미사용 UI model/mapper 제거로 정리하고 Feed category label 회귀를 방지한다.`
|
||||
|
||||
## 8. 리뷰 종료 판정
|
||||
|
||||
| 판정 항목 | 결과 | 근거 |
|
||||
|---|---|---|
|
||||
| 리뷰 범위 전체 확인 | 충족 | API→Repository→mapper와 resource 확인 |
|
||||
| 후보 항목 판정 완료 | 충족 | 과거 rank 문구는 오탐, `REV-P2-001~002` 판정 완료 |
|
||||
| 확정 항목 plan 반영 | 충족 | Task 2.7 / `P2-R1`, Task 2.8 / `P2-R2` 추가 |
|
||||
| 검증 명령과 결과 기록 | 충족 | focused test 및 빌드 품질 검증 PASS |
|
||||
|
||||
**최종 결론:** 확정 발견 사항 모두 수정 완료
|
||||
|
||||
**남은 항목:** 없음
|
||||
|
||||
## 9. 수정 후 검증 기록
|
||||
|
||||
- 2026-07-31: `REV-P2-001` 보완으로 `screen_home_following_creators_title`, `screen_home_following_on_air_title`, `screen_home_following_error`를 3개 locale에서 제거했다. `rg`로 production/test/layout 참조 0건을 확인했고, 사용 중인 `screen_home_following_on_air`, empty, ranking, section title 문자열은 유지했다. `./gradlew --no-daemon :app:mergeDebugResources :app:compileDebugKotlin`, `./gradlew --no-daemon --rerun-tasks :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingMapperTest"`, `./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*"`, `./gradlew --no-daemon :app:ktlintCheck`, `git diff --check` PASS.
|
||||
- 2026-07-31 재점검: Phase 1~13 focused 회귀 15개 suite/113개 test, resource merge, Kotlin compile, ktlint는 PASS했다. `REV-P2-002`는 정적 사용처 대조로 확정했고, 이번 리뷰에서 production/test 코드는 수정하지 않았다.
|
||||
- 2026-07-31: `REV-P2-002` 보완으로 `HomeFollowingNewsUiItem.Content.labelResId`, mapper 대입, `FollowingNewsType.toLabelResId()`를 제거했다. `PHOTO_CONTENT` 표시는 실제 `FeedContentCategory.Photo`와 locale string을 쓰는 adapter 회귀로 유지했다. mapper/news adapter focused test, 팔로잉 전체 회귀, resource merge, Kotlin compile, ktlint PASS.
|
||||
- 2026-07-31 최종 검증: DTO·Repository·mapper 회귀를 포함한 통합 20개 suite·306개 test와 resource merge, Kotlin compile, ktlint가 PASS했다. 추가 확정 발견 사항 없음.
|
||||
- 2026-07-31 이번 리뷰 재검증: endpoint·optional auth·nested payload·mapper·Feed category label 경로를 다시 추적했다. 통합 16개 suite·120개 test, resource merge, Kotlin compile, ktlint, staged/unstaged diff 검사가 PASS했으며 추가 확정 발견 사항은 없다.
|
||||
@@ -0,0 +1,123 @@
|
||||
# Phase 3 ViewModel 상태와 API 호출 리뷰
|
||||
|
||||
## 1. 리뷰 정보
|
||||
|
||||
| 항목 | 내용 |
|
||||
|---|---|
|
||||
| 리뷰 대상 | Phase 3 / Task 3.1~3.4 |
|
||||
| 기준 commit 또는 working tree | `f600d10e8b63b6fdc812b18a874b077dfe072ca8` + 2026-07-31 working tree |
|
||||
| 리뷰 일자 | 2026-07-31 |
|
||||
| 리뷰어 | Codex |
|
||||
| 기준 문서 | 대상 `prd.md`, `plan-task.md` |
|
||||
| 리뷰 상태 | 수정 검증 완료 |
|
||||
|
||||
## 2. 리뷰 목적과 범위
|
||||
|
||||
### 목적
|
||||
|
||||
- Loading, success/login-required/error와 optional header 흐름이 구현·테스트에서 일치하는지 확인한다.
|
||||
- 완료 기록이 주장하는 상태 발행 순서가 실제 assertion으로 보호되는지 확인한다.
|
||||
|
||||
### 포함 범위
|
||||
|
||||
- `HomeFollowingViewModel.kt`, DI 등록, `HomeFollowingViewModelTest.kt`
|
||||
|
||||
### 제외 범위
|
||||
|
||||
- Fragment rendering과 pull refresh UI.
|
||||
|
||||
## 3. 판정 기준
|
||||
|
||||
- 확정 상태 전환 요구사항 위반은 High, 기능은 맞지만 완료 증거가 누락된 검증 문제는 Low로 판정했다.
|
||||
|
||||
## 4. 검토한 근거
|
||||
|
||||
### 문서와 코드
|
||||
|
||||
- `HomeFollowingViewModel.kt:38-78`
|
||||
- `HomeFollowingViewModelTest.kt:56-65`, `67-128`
|
||||
- Task 3.1의 “loading 후 content 상태를 발행한다” 테스트 케이스와 Task 3.2 완료 기록
|
||||
|
||||
### 실행 환경
|
||||
|
||||
```text
|
||||
OS: Darwin 25.0.0 x86_64
|
||||
JDK: OpenJDK 17.0.15
|
||||
Gradle wrapper: 8.14.3
|
||||
```
|
||||
|
||||
### 실행한 검증
|
||||
|
||||
| 명령 | 결과 | 핵심 증거 |
|
||||
|---|---|---|
|
||||
| `./gradlew --no-daemon :app:testDebugUnitTest --tests "...HomeFollowingViewModelTest"` | 성공 | 7개 테스트 실패 0 |
|
||||
| 테스트 assertion 수동 대조 | 문제 확인 | 첫 테스트는 최종 Content와 `isLoading=false`만 확인하고 `Loading` 이력은 수집하지 않음 |
|
||||
|
||||
## 5. 발견 사항 요약
|
||||
|
||||
| ID | 심각도 | 상태 | 제목 | 소유 Task | 후속 goal |
|
||||
|---|---|---|---|---|---|
|
||||
| `REV-P3-001` | Low | 수정 완료 | Loading → 결과 발행 순서가 테스트 이름과 완료 기록과 달리 검증되지 않음 | Task 3.4 | `P3-R1` 완료 |
|
||||
|
||||
## 6. 발견 사항 상세
|
||||
|
||||
### REV-P3-001 — Loading → 결과 발행 순서가 테스트로 보호되지 않음
|
||||
|
||||
- **심각도:** Low
|
||||
- **상태:** 수정 완료
|
||||
- **관련 요구사항:** Task 3.1 loading 후 content 상태 발행
|
||||
- **소유 Task:** 신규 Task 3.4
|
||||
|
||||
**관찰 내용**
|
||||
|
||||
production은 `Loading`을 먼저 설정하지만 테스트는 `loadFollowing()` 완료 후 LiveData의 마지막 값만 읽는다. 테스트가 통과해도 `Loading` 발행이 제거되는 회귀를 잡지 못한다.
|
||||
|
||||
**근거**
|
||||
|
||||
- 코드: `HomeFollowingViewModel.kt:43-57`
|
||||
- 테스트: `HomeFollowingViewModelTest.kt:56-65`
|
||||
- 문서: Task 3.1, Task 3.2 검증 기록
|
||||
|
||||
**재현 또는 검증 절차**
|
||||
|
||||
1. `loadFollowing은 loading 후 content 상태를 발행한다` 테스트를 확인한다.
|
||||
2. observer 이력 수집이나 `Loading` assertion이 없는지 대조한다.
|
||||
3. 실제 결과는 최종 `Content`와 `isLoading=false`만 검증된다.
|
||||
|
||||
**영향**
|
||||
|
||||
로딩 UI 계약이 회귀해도 Phase 3 focused test와 완료 기록은 계속 PASS할 수 있다.
|
||||
|
||||
**권장 조치**
|
||||
|
||||
observer가 수집한 상태 이력을 이용해 `Loading`, `Content` 순서를 한 테스트에서 검증한다. production 변경은 필요하지 않으며, 이미 존재하는 동작의 coverage 보강이므로 의도적인 RED를 만들지 않는다.
|
||||
|
||||
**판정 기록**
|
||||
|
||||
- 2026-07-30 — 테스트와 완료 기준을 직접 대조해 확정.
|
||||
- 2026-07-30 — Task 3.4에서 observer 상태 이력 assertion을 추가하고 focused/전체 회귀 PASS로 수정 완료.
|
||||
|
||||
## 7. 확정 항목의 plan·goal 전환
|
||||
|
||||
- `plan-task.md` Phase 3에 Task 3.4 / `P3-R1`을 추가했다.
|
||||
- objective: `[P3-R1]의 REV-P3-001을 테스트로 고정하고 Phase 3 회귀를 방지한다.`
|
||||
|
||||
## 8. 리뷰 종료 판정
|
||||
|
||||
| 판정 항목 | 결과 | 근거 |
|
||||
|---|---|---|
|
||||
| 리뷰 범위 전체 확인 | 충족 | ViewModel, DI, test 확인 |
|
||||
| 후보 항목 판정 완료 | 충족 | REV-P3-001 확정 |
|
||||
| 확정 항목 plan 반영 | 충족 | Task 3.4 추가 |
|
||||
| 검증 명령과 결과 기록 | 충족 | focused test 7개 PASS |
|
||||
|
||||
**최종 결론:** 수정 검증 완료
|
||||
|
||||
**남은 항목:** 없음
|
||||
|
||||
## 9. 수정 후 검증 기록
|
||||
|
||||
- 2026-07-30: `HomeFollowingViewModelTest`에 observer 상태 이력 assertion을 추가해 `Loading → Content` 발행 순서를 검증했다. production 변경 없이 focused test와 팔로잉 전체 회귀, `git diff --check` PASS.
|
||||
- 2026-07-31 재점검: ViewModel 7개 test와 Phase 1~13 focused 회귀 113개 test, resource merge, Kotlin compile, ktlint PASS. 추가 확정 발견 사항 없음.
|
||||
- 2026-07-31 최종 검증: ViewModel 상태 전이를 포함한 통합 20개 suite·306개 test와 Kotlin compile, ktlint가 PASS했다. 추가 확정 발견 사항 없음.
|
||||
- 2026-07-31 이번 리뷰 재검증: `Loading → Content`, optional auth, login-required, 초기 오류와 refresh fallback 상태를 다시 대조했다. 통합 16개 suite·120개 test와 Kotlin compile·ktlint가 PASS해 추가 확정 발견 사항이 없다.
|
||||
@@ -0,0 +1,247 @@
|
||||
# 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`
|
||||
|
||||
### 실행 환경
|
||||
|
||||
```text
|
||||
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 `liveId`는 `LiveActionCoordinator`, 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
|
||||
|
||||
**관찰 내용**
|
||||
|
||||
`Content`와 `Empty`는 `finishHomePullRefresh()`를 호출하지만 `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.kt`의 `home layout exposes...`부터 `following recent news adapter binds...`까지 영문 문장형 테스트명 11개
|
||||
- 가이드: `docs/agent-guides/build-test-style.md`와 `docs/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` 수정 완료 판정을 유지한다.
|
||||
@@ -0,0 +1,107 @@
|
||||
# Phase 5 통합 검증 리뷰
|
||||
|
||||
## 1. 리뷰 정보
|
||||
|
||||
| 항목 | 내용 |
|
||||
|---|---|
|
||||
| 리뷰 대상 | Phase 5 / Task 5.1~5.3 |
|
||||
| 기준 commit 또는 working tree | `f600d10e8b63b6fdc812b18a874b077dfe072ca8` + 2026-07-31 working tree |
|
||||
| 리뷰 일자 | 2026-07-31 |
|
||||
| 리뷰어 | Codex |
|
||||
| 기준 문서 | 대상 `prd.md`, `plan-task.md`, `docs/agent-guides/build-test-style.md` |
|
||||
| 리뷰 상태 | 판정 완료 / 수동 검증 보류 |
|
||||
|
||||
## 2. 리뷰 목적과 범위
|
||||
|
||||
### 목적
|
||||
|
||||
- Phase 5 자동 Gate를 현재 working tree에서 재실행하고 기록과 일치하는지 확인한다.
|
||||
- Task 5.3의 실기기 수동 확인 가능 여부를 추정 없이 판정한다.
|
||||
|
||||
### 포함 범위
|
||||
|
||||
- 팔로잉 전체 unit/source test, resource merge, compile, ktlint, diff check, ADB 연결 확인.
|
||||
|
||||
### 제외 범위
|
||||
|
||||
- 테스트 계정·서버 데이터를 임의 생성하는 행위와 연결 기기 없는 상태의 수동 화면 성공 추정.
|
||||
|
||||
## 3. 판정 기준
|
||||
|
||||
- 자동 Gate 실패는 High 이상, 환경이 필요한 미실행 검증은 보류로 판정했다.
|
||||
|
||||
## 4. 검토한 근거
|
||||
|
||||
### 실행 환경
|
||||
|
||||
```text
|
||||
OS: Darwin 25.0.0 x86_64
|
||||
JDK: OpenJDK 17.0.15
|
||||
Gradle wrapper: 8.14.3
|
||||
ADB: 연결 기기 없음
|
||||
```
|
||||
|
||||
### 실행한 검증
|
||||
|
||||
| 명령 | 결과 | 핵심 증거 |
|
||||
|---|---|---|
|
||||
| `./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*"` | 성공 | 39개 테스트, 실패 0 |
|
||||
| `./gradlew --no-daemon :app:mergeDebugResources :app:compileDebugKotlin :app:ktlintCheck` | 성공 | 3개 task PASS |
|
||||
| `git diff --check` | 성공 | 출력 없음 |
|
||||
| `adb devices` | 성공 / 기기 없음 | `List of devices attached` 아래 항목 없음 |
|
||||
|
||||
## 5. 발견 사항 요약
|
||||
|
||||
| ID | 심각도 | 상태 | 제목 | 소유 Task | 후속 goal |
|
||||
|---|---|---|---|---|---|
|
||||
| `REV-P5-001` | Low | 보류 | Figma/API 데이터 기반 실기기 수동 화면 검증 미완료 | 기존 Task 5.3 | 기기·계정 준비 후 재개 |
|
||||
|
||||
## 6. 발견 사항 상세
|
||||
|
||||
### REV-P5-001 — Figma/API 데이터 기반 실기기 수동 화면 검증 미완료
|
||||
|
||||
- **심각도:** Low
|
||||
- **상태:** 보류
|
||||
- **관련 요구사항:** Task 5.3
|
||||
- **소유 Task:** 기존 Task 5.3
|
||||
|
||||
**관찰 내용**
|
||||
|
||||
자동 Gate는 모두 통과했으나 현재 ADB 연결 기기가 없어 실제 팔로잉 데이터 화면, scroll, 겹침, item 터치를 직접 확인하지 못했다.
|
||||
|
||||
**영향**
|
||||
|
||||
실제 렌더링과 상호작용 문제는 source test와 컴파일만으로 완전히 배제할 수 없다.
|
||||
|
||||
**권장 조치**
|
||||
|
||||
기기/에뮬레이터와 팔로잉 데이터가 있는 테스트 계정이 준비되면 기존 Task 5.3 체크리스트를 그대로 수행한다.
|
||||
|
||||
**판정 기록**
|
||||
|
||||
- 2026-07-30 — `adb devices` 결과 기기 없음으로 보류 유지.
|
||||
- 2026-07-31 — Task 2.7 완료 후 `adb devices`를 재실행했으나 `List of devices attached` 아래 연결 기기가 없어 보류 유지.
|
||||
|
||||
## 7. 확정 항목의 plan·goal 전환
|
||||
|
||||
신규 전환 항목 없음. 기존 Task 5.3이 보류 범위와 재개 조건을 이미 소유한다.
|
||||
|
||||
## 8. 리뷰 종료 판정
|
||||
|
||||
| 판정 항목 | 결과 | 근거 |
|
||||
|---|---|---|
|
||||
| 리뷰 범위 전체 확인 | 충족 | 자동 Gate와 ADB 확인 완료 |
|
||||
| 후보 항목 판정 완료 | 충족 | REV-P5-001 보류 |
|
||||
| 확정 항목 plan 반영 | 해당 없음 | 신규 확정 수정 없음 |
|
||||
| 보류 항목의 담당·재개 조건 기록 | 충족 | Task 5.3, 기기·계정 준비 후 재개 |
|
||||
| 검증 명령과 결과 기록 | 충족 | 39개 테스트 및 빌드 품질 PASS |
|
||||
|
||||
**최종 결론:** 외부 조건 대기
|
||||
|
||||
**남은 항목:** `REV-P5-001` / Task 5.3
|
||||
|
||||
## 9. 수정 후 검증 기록
|
||||
|
||||
- 2026-07-31 재점검: Phase 1~13 focused 회귀 15개 suite/113개 test, resource merge, Kotlin compile, ktlint PASS. `adb devices`는 정상 실행됐으나 연결 기기가 없어 `REV-P5-001` / Task 5.3 보류 판정을 유지했다.
|
||||
- 2026-07-31 최종 검증: 통합 20개 suite·306개 test, resource merge, Kotlin compile, ktlint, Gradle task 목록, staged/unstaged diff 검사가 모두 PASS했다. `adb devices`에는 연결 기기가 없어 `REV-P5-001` / Task 5.3 보류 판정을 유지한다.
|
||||
- 2026-07-31 이번 리뷰 재검증: 통합 16개 suite·120개 test(failures/errors/skipped 0), resource merge, Kotlin compile, ktlint, `./gradlew --no-daemon tasks --all`, staged/unstaged diff 검사가 PASS했다. `adb devices`에서 기기 `2cec640c34017ece` 연결은 확인했지만 테스트 계정·API 데이터 기반 팔로잉 화면 조작과 Figma 대조를 수행하지 않았으므로 `REV-P5-001` / Task 5.3은 보류 유지한다.
|
||||
@@ -0,0 +1,227 @@
|
||||
# Phase 6 Figma 후속 수정 리뷰
|
||||
|
||||
## 1. 리뷰 정보
|
||||
|
||||
| 항목 | 내용 |
|
||||
|---|---|
|
||||
| 리뷰 대상 | Phase 6 / Task 6.1~6.8 |
|
||||
| 기준 commit 또는 working tree | `f600d10e8b63b6fdc812b18a874b077dfe072ca8` + 2026-07-31 working tree |
|
||||
| 리뷰 일자 | 2026-07-31 |
|
||||
| 리뷰어 | Codex |
|
||||
| 기준 문서 | 대상 `prd.md`, `plan-task.md` |
|
||||
| 리뷰 상태 | 수정 검증 완료 / 수동 검증 보류 |
|
||||
|
||||
## 2. 리뷰 목적과 범위
|
||||
|
||||
### 목적
|
||||
|
||||
- 크리에이터·최근 대화 UI 보정과 최근 소식 Feed 위젯 전환이 현재 코드에 유지되는지 확인한다.
|
||||
- 전환 후 사용되지 않는 전용 resource가 남았는지 확인한다.
|
||||
- 최근 대화 item의 XML 고정 폭이 adapter binding 이후에도 유지되는지 확인한다.
|
||||
- creator·최근 대화 source test가 현행 UI 표현 속성 테스트 금지 규칙을 준수하는지 확인한다.
|
||||
|
||||
### 포함 범위
|
||||
|
||||
- `fragment_v2_main_home.xml`, creator/chat/news adapter와 layout, Feed 위젯 참조, source test.
|
||||
|
||||
### 제외 범위
|
||||
|
||||
- Phase 7 이후 Feed 내부 spacing과 Phase 9 DTO 계약.
|
||||
|
||||
## 3. 판정 기준
|
||||
|
||||
- runtime 기능에는 영향이 없지만 잘못된 preview와 obsolete resource를 남긴 문제는 Low로 판정했다.
|
||||
|
||||
## 4. 검토한 근거
|
||||
|
||||
### 문서와 코드
|
||||
|
||||
- `HomeFollowingNewsAdapter.kt:32-55`: Feed layout 3종 사용
|
||||
- `fragment_v2_main_home.xml:359-368`: 과거 content layout preview 참조
|
||||
- `item_home_following_news_rank.xml`, `item_home_following_news_content.xml`
|
||||
- `HomeFollowingFragmentSourceTest.kt:185-218`
|
||||
- `item_home_following_chat.xml:4`: root width `284dp`
|
||||
- Task 6.7 수정 전 `HomeFollowingChatAdapter`와 `HomeRecyclerItemLayoutParams.kt:7-14`: inflate된 width를 `WRAP_CONTENT`로 교체
|
||||
- 현재 `HomeFollowingChatAdapter.kt:23-27`: inflate된 `RecyclerView.LayoutParams`의 width/height를 보존하고 end margin만 적용
|
||||
- `HomeFollowingFragmentSourceTest.kt:292-360`: creator/chat XML 크기·orientation·style·maxLines·ellipsize 문자열 assertion
|
||||
- `docs/agent-guides/code-style.md`: View 크기·margin·padding·constraint·visibility 등 UI 표현 속성 테스트 금지
|
||||
|
||||
### 실행한 검증
|
||||
|
||||
| 명령 | 결과 | 핵심 증거 |
|
||||
|---|---|---|
|
||||
| `rg -n "item_home_following_news_(rank|content)" ...` | 성공 | runtime adapter 참조 없음, preview/doc/test만 존재 |
|
||||
| `./gradlew --no-daemon :app:testDebugUnitTest --tests "...HomeFollowingFragmentSourceTest"` | 성공 | 16개 테스트 실패 0 |
|
||||
| resource merge/compile/ktlint | 성공 | BUILD SUCCESSFUL |
|
||||
| Task 6.7 수정 후 chat layout parameter 정적 대조 | 성공 | XML `284dp` width를 보존하고 end margin만 추가 |
|
||||
| 2026-07-31 Phase 1~13 통합 focused 회귀 | 성공 | 15개 suite, 113개 test, failures/errors 0 |
|
||||
|
||||
## 5. 발견 사항 요약
|
||||
|
||||
| ID | 심각도 | 상태 | 제목 | 소유 Task | 후속 goal |
|
||||
|---|---|---|---|---|---|
|
||||
| `REV-P6-001` | Low | 수정 완료 | Feed 전환 전 최근 소식 layout 2개와 preview 참조가 남음 | Task 6.5 | `P6-R1` 완료 |
|
||||
| `REV-P6-002` | Low | 수정 완료 | 삭제된 최근 소식 layout이 상단 파일 구조에 생성 대상으로 남음 | Task 6.6 | `P6-R2` 완료 |
|
||||
| `REV-P6-003` | Medium | 수정 완료 | 최근 대화 item의 XML `284dp` 폭이 런타임 `WRAP_CONTENT`로 덮임 | Task 6.7 | `P6-R3` 완료 |
|
||||
| `REV-P6-004` | Low | 수정 완료 | creator·최근 대화 UI 표현 속성을 source 문자열로 검증함 | Task 6.8 | `P6-R4` 완료 |
|
||||
|
||||
## 6. 발견 사항 상세
|
||||
|
||||
### REV-P6-001 — Feed 전환 전 최근 소식 layout이 남음
|
||||
|
||||
- **심각도:** Low
|
||||
- **상태:** 수정 완료
|
||||
- **관련 요구사항:** Task 6.4 Feed 위젯 재사용
|
||||
- **소유 Task:** Task 6.5
|
||||
|
||||
**관찰 내용**
|
||||
|
||||
runtime adapter는 `view_feed_rank/content/community`만 inflate하지만 과거 전용 news layout 두 개가 유지되고, RecyclerView preview는 그중 하나를 계속 가리킨다.
|
||||
|
||||
**근거**
|
||||
|
||||
- 코드: `HomeFollowingNewsAdapter.kt:38-55`
|
||||
- resource: `fragment_v2_main_home.xml:368`
|
||||
- 검색: `item_home_following_news_rank`는 runtime 참조 없음
|
||||
|
||||
**영향**
|
||||
|
||||
Layout Editor preview와 실제 UI가 다르고, 유지보수자가 사용 중인 resource로 오해할 수 있다.
|
||||
|
||||
**권장 조치**
|
||||
|
||||
preview를 `view_feed_content`로 바꾸고 obsolete layout 2개를 삭제한다.
|
||||
|
||||
**판정 기록**
|
||||
|
||||
- 2026-07-30 — 전체 resource 참조 검색으로 확정.
|
||||
- 2026-07-30 — Task 6.5에서 preview 교체와 obsolete layout 삭제 후 resource/회귀 검증을 완료.
|
||||
|
||||
### REV-P6-002 — 삭제된 최근 소식 layout이 파일 구조에 남음
|
||||
|
||||
- **심각도:** Low
|
||||
- **상태:** 수정 완료
|
||||
- **관련 요구사항:** Task 6.5, 계획 문서 범위 변경 선반영 규칙
|
||||
- **소유 Task:** Task 6.6
|
||||
|
||||
**관찰 내용**
|
||||
|
||||
Task 6.5와 현재 resource는 `item_home_following_news_rank.xml`, `item_home_following_news_content.xml`을 삭제했지만, `plan-task.md` 상단 `파일 구조`는 두 파일을 여전히 Create 대상으로 설명한다.
|
||||
|
||||
**근거**
|
||||
|
||||
- 문서: `plan-task.md` 상단 `파일 구조`와 Task 6.5
|
||||
- 코드: `HomeFollowingNewsAdapter`는 `view_feed_rank`, `view_feed_content`, `view_feed_community`를 사용
|
||||
- resource: 두 obsolete layout은 현재 working tree에서 삭제 상태
|
||||
|
||||
**영향**
|
||||
|
||||
후속 작업자가 삭제된 resource를 현재 필수 파일로 오인하거나 다시 생성할 수 있다.
|
||||
|
||||
**권장 조치**
|
||||
|
||||
상단 파일 구조를 현재 Feed 위젯 재사용 구조에 맞추되 Task 6.5의 삭제 이력은 유지한다.
|
||||
|
||||
**판정 기록**
|
||||
|
||||
- 2026-07-30 — 현재 파일 목록, adapter 참조, 계획 문서 상단 목록을 대조해 확정.
|
||||
- 2026-07-30 — Task 6.6에서 상단 파일 구조를 Feed layout 재사용/obsolete layout 삭제 이력 기준으로 갱신하고 대체 검증을 완료.
|
||||
|
||||
### REV-P6-003 — 최근 대화 고정 폭이 adapter에서 보존되지 않음
|
||||
|
||||
- **심각도:** Medium
|
||||
- **상태:** 수정 완료
|
||||
- **관련 요구사항:** Task 6.2의 Figma `284dp` box card, Task 6.3의 폭 보정 기록
|
||||
- **소유 Task:** Task 6.7
|
||||
|
||||
**관찰 내용**
|
||||
|
||||
`item_home_following_chat.xml` root는 `284dp`지만 `HomeFollowingChatAdapter.onCreateViewHolder()`가 inflate 직후 `recyclerItemLayoutParams(parent)`로 전체 layout parameter를 교체한다. 해당 helper는 width와 height를 모두 `WRAP_CONTENT`로 새로 생성하므로 문서에 기록된 “XML 폭 유지”가 실제 코드에서는 성립하지 않는다.
|
||||
|
||||
**근거**
|
||||
|
||||
- layout: `item_home_following_chat.xml:4-5`
|
||||
- adapter: `HomeFollowingChatAdapter.kt:23-26`
|
||||
- helper: `HomeRecyclerItemLayoutParams.kt:7-14`
|
||||
- 문서: Task 6.3의 최근 대화 item 폭 보정 검증 기록
|
||||
|
||||
**영향**
|
||||
|
||||
가로 목록에서 카드 폭이 Figma `284dp`가 아니라 자식 content의 wrap-content 측정값으로 결정되어 제목·메시지 영역과 item 간격이 설계와 다르게 보일 수 있다.
|
||||
|
||||
**권장 조치**
|
||||
|
||||
inflate된 root의 기존 width/height는 유지하고 end margin만 추가한다. 공통 helper 전체 리팩터링 없이 `HomeFollowingChatAdapter` 한 곳을 최소 수정하고, UI 크기 자동 테스트 대신 resource/compile/정적 대조와 Task 5.3 수동 확인을 사용한다.
|
||||
|
||||
**판정 기록**
|
||||
|
||||
- 2026-07-30 — XML root width, adapter 대입문, helper 반환값을 end-to-end로 대조해 확정.
|
||||
- 2026-07-30 — 구현 전 Phase 6 Task 6.7 / `P6-R3`로 전환.
|
||||
- 2026-07-30 — Task 6.7에서 inflate된 `RecyclerView.LayoutParams`의 width/height를 보존하고 end margin만 적용하도록 수정한 뒤 회귀 검증을 완료.
|
||||
|
||||
### REV-P6-004 — creator·최근 대화 UI 표현 속성을 source test로 고정함
|
||||
|
||||
- **심각도:** Low
|
||||
- **상태:** 수정 완료
|
||||
- **관련 요구사항:** `docs/agent-guides/code-style.md` 테스트 관례, Task 6.1~6.2
|
||||
- **소유 Task:** Task 6.8
|
||||
|
||||
**관찰 내용**
|
||||
|
||||
`HomeFollowingFragmentSourceTest`가 creator item의 `75dp` 폭/높이와 typography style, 최근 대화 section의 XML orientation, `284dp`/`62dp` 폭/높이, `maxLines`/`ellipsize`를 파일 문자열로 검증한다. 이는 로직 테스트만 추가하고 UI 레이아웃/표현 속성 테스트를 작성하지 않는 현행 가이드와 맞지 않는다.
|
||||
|
||||
**근거**
|
||||
|
||||
- test: `HomeFollowingFragmentSourceTest.kt:292-302`, `331-361`
|
||||
- guide: `docs/agent-guides/code-style.md` “신규 테스트는 로직에 대한 테스트 코드만 작성” 및 UI 표현 속성 검증 금지
|
||||
- 비교: 동일 리뷰의 Task 7.7, 8.4, 10.3, 12.4는 같은 종류의 assertion을 이미 제거함
|
||||
|
||||
**재현 또는 검증 절차**
|
||||
|
||||
1. `rg -n 'layout_(width|height)|orientation|maxLines|ellipsize|Typography' HomeFollowingFragmentSourceTest.kt`를 실행한다.
|
||||
2. Phase 6 creator/chat 테스트 범위에서 XML 표현 값 assertion을 확인한다.
|
||||
3. production 동작은 정상이지만 테스트 정책 위반은 재현된다.
|
||||
|
||||
**영향**
|
||||
|
||||
런타임 결함은 아니지만 디자인 값 조정이 로직 회귀 실패로 잘못 표시되고, 가이드에서 정한 수동/Figma 대조 경계를 흐린다.
|
||||
|
||||
**권장 조치**
|
||||
|
||||
XML 크기·방향·style·말줄임 문자열 assertion만 제거하고, creator header 제거 구조, Direct badge 결정, 상대 시간 formatter, 필수 field 바인딩은 유지한다. production UI 값은 변경하지 않는다.
|
||||
|
||||
**판정 기록**
|
||||
|
||||
- 2026-07-31 — test source 검색과 현행 가이드를 대조해 확정.
|
||||
- 2026-07-31 — production/test는 수정하지 않고 Phase 6 Task 6.8 / `P6-R4`로 전환.
|
||||
- 2026-07-31 — Task 6.8에서 금지된 UI 표현 속성 source assertion만 제거하고 구조·바인딩·클릭 계약 회귀 검증을 완료.
|
||||
|
||||
## 7. 확정 항목의 plan·goal 전환
|
||||
|
||||
- Phase 6에 Task 6.5 / `P6-R1`을 추가해 완료했다.
|
||||
- 재점검에서 Task 6.6 / `P6-R2`를 추가해 완료했다.
|
||||
- 추가 재점검에서 Task 6.7 / `P6-R3`를 추가해 완료했다.
|
||||
- 2026-07-31 재점검에서 Task 6.8 / `P6-R4`를 추가해 완료했다.
|
||||
|
||||
## 8. 리뷰 종료 판정
|
||||
|
||||
| 판정 항목 | 결과 | 근거 |
|
||||
|---|---|---|
|
||||
| 리뷰 범위 전체 확인 | 충족 | UI resource와 adapter 참조 검색 |
|
||||
| 후보 항목 판정 완료 | 충족 | REV-P6-001~004 판정 완료 |
|
||||
| 확정 항목 plan 반영 | 충족 | Task 6.5~6.8 |
|
||||
| 검증 명령과 결과 기록 | 충족 | source test 및 build PASS |
|
||||
|
||||
**최종 결론:** 확정 발견 사항 모두 수정 완료 / 실기기 검증은 외부 조건 대기
|
||||
|
||||
**남은 항목:** Phase 5 Task 5.3 실기기 확인
|
||||
|
||||
## 9. 수정 후 검증 기록
|
||||
|
||||
- 2026-07-30: 최근 소식 preview `tools:listitem`을 실제 runtime Feed layout인 `@layout/view_feed_content`로 교체하고 obsolete `item_home_following_news_rank.xml`, `item_home_following_news_content.xml`을 삭제했다. `rg` 기준 runtime 참조는 없고 문서/테스트 검증 참조만 남았다. `:app:mergeDebugResources`, `HomeFollowingFragmentSourceTest`, 팔로잉 전체 회귀, `:app:compileDebugKotlin`, `:app:ktlintCheck`, `git diff --check` PASS.
|
||||
- 2026-07-30: Task 6.6으로 `plan-task.md` 상단 파일 구조를 현재 resource 구성에 맞춰 갱신했다. obsolete layout 2개는 삭제 이력으로만 남기고, 최근 소식 runtime layout은 `view_feed_rank`, `view_feed_content`, `view_feed_community` 재사용으로 명시했다. `rg` 대조와 `git diff --check` PASS.
|
||||
- 2026-07-30: Task 6.7로 `HomeFollowingChatAdapter`가 새 `WRAP_CONTENT` layout parameter를 만들지 않고 inflate된 root의 `284dp` width와 height를 보존한 채 `spacing_12` end margin만 적용하도록 수정했다. focused test, 팔로잉 전체 회귀, resource merge, Kotlin compile, ktlint PASS. 연결 기기가 없어 실기기 확인은 Task 5.3 보류 상태를 유지했다.
|
||||
- 2026-07-31 재점검: Phase 1~13 focused 회귀 15개 suite/113개 test, resource merge, Kotlin compile, ktlint는 PASS했다. `REV-P6-004`는 가이드 대조로 확정했고, 이번 리뷰에서 production/test 코드는 수정하지 않았다.
|
||||
- 2026-07-31: `REV-P6-004` 보완으로 creator·최근 대화 source test에서 UI 표현 속성 문자열 assertion을 제거했다. creator header 제거, 필수 field id, Direct badge, 상대 시간 formatter, click listener 계약 검증은 유지했다. `rg` 대체 검증, `HomeFollowingFragmentSourceTest`, 팔로잉 전체 회귀, resource merge, Kotlin compile, ktlint PASS. 연결 기기가 없어 실기기 표현 확인은 Task 5.3 보류 상태를 유지했다.
|
||||
- 2026-07-31 최종 검증: creator·최근 대화 회귀를 포함한 통합 20개 suite·306개 test와 resource merge, Kotlin compile, ktlint가 PASS했다. 추가 확정 수정 사항은 없고 실기기 확인은 Phase 5 Task 5.3에 유지한다.
|
||||
- 2026-07-31 이번 리뷰 재검증: creator/chat 고정 폭 보존, Feed 위젯 재사용과 obsolete layout 제거 상태를 다시 대조했다. 통합 16개 suite·120개 test, resource merge, Kotlin compile, ktlint가 PASS해 `REV-P6-001~004` 수정 완료 판정을 유지하고, 시각 대조는 Phase 5 Task 5.3에 유지한다.
|
||||
@@ -0,0 +1,185 @@
|
||||
# Phase 7 ranking 문장과 content feed 리뷰
|
||||
|
||||
## 1. 리뷰 정보
|
||||
|
||||
| 항목 | 내용 |
|
||||
|---|---|
|
||||
| 리뷰 대상 | Phase 7 / Task 7.1~7.7 |
|
||||
| 기준 commit 또는 working tree | `f600d10e8b63b6fdc812b18a874b077dfe072ca8` + 2026-07-31 working tree |
|
||||
| 리뷰 일자 | 2026-07-31 |
|
||||
| 리뷰어 | Codex |
|
||||
| 기준 문서 | 대상 `prd.md`, `plan-task.md`, code style guide |
|
||||
| 리뷰 상태 | 수정 검증 완료 |
|
||||
|
||||
## 2. 리뷰 목적과 범위
|
||||
|
||||
### 목적
|
||||
|
||||
- ranking message/highlight와 compact content Feed가 Figma·locale 요구를 충족하는지 확인한다.
|
||||
- 과거 Task 7.3 ktlint 실패가 현재도 남았는지 재검증한다.
|
||||
|
||||
### 포함 범위
|
||||
|
||||
- `HomeFollowingNewsAdapter.kt`, `view_feed_content.xml`, `FeedContentView.kt`
|
||||
- 한국어/영어/일본어 string resource, `FeedViewTest`, following source test
|
||||
|
||||
### 제외 범위
|
||||
|
||||
- Phase 9 nested payload와 Phase 13 routing.
|
||||
|
||||
## 3. 판정 기준
|
||||
|
||||
- 특정 locale에서 잘못된 사용자 문자열이 노출되는 문제는 Medium으로 판정했다.
|
||||
|
||||
## 4. 검토한 근거
|
||||
|
||||
### 문서와 코드
|
||||
|
||||
- `HomeFollowingNewsAdapter.kt:74-108`
|
||||
- `values/strings.xml:318-319`, `values-en/strings.xml:319-320`, `values-ja/strings.xml:319-320`
|
||||
- `view_feed_content.xml`, `FeedContentView.kt:30-112`
|
||||
|
||||
### 실행한 검증
|
||||
|
||||
| 명령 | 결과 | 핵심 증거 |
|
||||
|---|---|---|
|
||||
| following source test + `FeedViewTest` | 성공 | 기존 layout/highlight source 계약 PASS |
|
||||
| resource/compile/ktlint | 성공 | 현재 working tree에서 Task 7.3 명령 모두 PASS |
|
||||
| locale message 수동 대입 | 문제 확인 | 영어·일본어 `%2$s`에 `"7위"`가 전달됨 |
|
||||
|
||||
## 5. 발견 사항 요약
|
||||
|
||||
| ID | 심각도 | 상태 | 제목 | 소유 Task | 후속 goal |
|
||||
|---|---|---|---|---|---|
|
||||
| `REV-P7-001` | Medium | 수정 완료 | 영어·일본어 ranking 문장에도 한국어 순위 단위 `"위"`가 노출됨 | Task 7.5 | `P7-R1` 완료 |
|
||||
| `REV-P7-002` | Low | 수정 완료 | 신규 ranking 테스트명과 단일 실행 가이드가 저장소 규칙을 충족하지 않음 | Task 7.6 | `P7-R2` 완료 |
|
||||
| `REV-P7-003` | Low | 수정 완료 | 가이드 제정 이후 content feed 크기·padding·margin source test를 추가함 | Task 7.7 | `P7-R3` 완료 |
|
||||
|
||||
## 6. 발견 사항 상세
|
||||
|
||||
### REV-P7-001 — ranking 순위 단위가 한국어로 고정됨
|
||||
|
||||
- **심각도:** Medium
|
||||
- **상태:** 수정 완료
|
||||
- **관련 요구사항:** 3개 locale string resource, ranking 문장형 message
|
||||
- **소유 Task:** Task 7.5
|
||||
|
||||
**관찰 내용**
|
||||
|
||||
adapter가 locale과 무관하게 `val rankText = "${ranking.rank}위"`를 만든다. 영어와 일본어 문장은 resource로 번역되지만 placeholder에는 한국어 `위`가 그대로 들어간다.
|
||||
|
||||
**근거**
|
||||
|
||||
- 코드: `HomeFollowingNewsAdapter.kt:77-88`
|
||||
- resource: 영어 `%1$s reached %2$s...`, 일본어 `ランキング%2$s...`
|
||||
- 테스트: source 문자열 존재만 검사하고 locale별 결과 문자열은 검증하지 않음
|
||||
|
||||
**재현 또는 검증 절차**
|
||||
|
||||
1. locale을 English 또는 Japanese로 설정한다.
|
||||
2. rank 7 item의 message를 생성한다.
|
||||
3. 실제 결과 placeholder는 `7위`.
|
||||
4. 요구 결과는 locale별 영어 표기 또는 일본어 `7位`다.
|
||||
|
||||
**영향**
|
||||
|
||||
영어·일본어 사용자에게 혼합 언어 문장이 노출되고 highlight 대상도 잘못된 단위를 포함한다.
|
||||
|
||||
**권장 조치**
|
||||
|
||||
rank format을 locale string resource로 분리하고 완성된 rank 문자열의 유효 index/highlight 범위를 테스트한다.
|
||||
|
||||
**판정 기록**
|
||||
|
||||
- 2026-07-30 — adapter와 세 locale resource를 대입해 확정.
|
||||
- 2026-07-30 — Task 7.5에서 locale rank format과 highlight 단위 테스트를 추가하고 회귀 검증을 완료.
|
||||
|
||||
### REV-P7-002 — 신규 ranking 테스트와 실행 가이드 규칙 미준수
|
||||
|
||||
- **심각도:** Low
|
||||
- **상태:** 수정 완료
|
||||
- **관련 요구사항:** `docs/agent-guides/code-style.md` 테스트 관례, `docs/agent-guides/build-test-style.md` 단일 실행 예시 갱신 규칙
|
||||
- **소유 Task:** Task 7.6
|
||||
|
||||
**관찰 내용**
|
||||
|
||||
새로 추가된 `HomeFollowingNewsAdapterTest`의 두 backtick 테스트명이 영문 문장이고, 새 테스트 클래스에 대응하는 단일 실행 예시가 `build-test-style.md`에 없다. Task 7.5 Files에는 가이드 수정이 명시되어 있지만 실제 변경에는 포함되지 않았다.
|
||||
|
||||
**근거**
|
||||
|
||||
- 테스트: `HomeFollowingNewsAdapterTest.kt:23`, `:30`
|
||||
- 가이드: `code-style.md`의 신규 테스트명 한글 규칙과 테스트 추가 시 실행 예시 갱신 규칙
|
||||
- 문서: Task 7.5 Files의 `docs/agent-guides/build-test-style.md`
|
||||
|
||||
**영향**
|
||||
|
||||
기능 동작에는 영향이 없지만 완료 체크리스트와 실제 변경이 불일치하고 신규 테스트 작성 관례가 깨진다.
|
||||
|
||||
**권장 조치**
|
||||
|
||||
신규 테스트명 2개만 한글화하고 `HomeFollowingNewsAdapterTest` 클래스 단위 실행 예시를 빌드 가이드에 추가한다. 기존 영어 테스트명 일괄 변경은 범위 밖으로 둔다.
|
||||
|
||||
**판정 기록**
|
||||
|
||||
- 2026-07-30 — 신규 테스트 diff와 현재 가이드 및 Task 7.5 Files를 대조해 확정.
|
||||
- 2026-07-30 — Task 7.6에서 신규 테스트명 2개를 한글화하고 `HomeFollowingNewsAdapterTest` 실행 예시를 추가했다.
|
||||
|
||||
### REV-P7-003 — content feed UI 표현 속성을 source test로 고정함
|
||||
|
||||
- **심각도:** Low
|
||||
- **상태:** 수정 완료
|
||||
- **관련 요구사항:** `docs/agent-guides/code-style.md` 테스트 관례
|
||||
- **소유 Task:** Task 7.7
|
||||
|
||||
**관찰 내용**
|
||||
|
||||
`FeedViewTest.content layout matches figma compact upload notice dimensions`는 `view_feed_content.xml`의 `padding`, `88dp` width/height, 두 margin 문자열을 직접 assertion한다. 이 테스트는 UI 크기·margin·padding 테스트 금지 규칙이 추가된 뒤 생성되었다.
|
||||
|
||||
**근거**
|
||||
|
||||
- 테스트: `FeedViewTest.kt:45-64`
|
||||
- 가이드: `docs/agent-guides/code-style.md:42-43`
|
||||
- 이력: 가이드 규칙 `566f76df` 이후 테스트 `61fe8a9f` 추가
|
||||
|
||||
**영향**
|
||||
|
||||
기능 로직이 아닌 Figma 표현값과 XML 구현 문자열이 회귀 Gate에 고정되어, 합법적인 UI 조정이나 구현 방식 변경만으로 테스트가 실패하고 현재 저장소 테스트 정책과 불일치한다.
|
||||
|
||||
**권장 조치**
|
||||
|
||||
해당 테스트만 제거하고 production layout/View는 유지한다. Figma 크기·간격은 정적 대조, resource merge, compile, Task 5.3 수동 화면 확인으로 검증한다.
|
||||
|
||||
**판정 기록**
|
||||
|
||||
- 2026-07-30 — test 추가 시점, assertion 내용, 현행 가이드를 대조해 확정.
|
||||
- 2026-07-30 — 구현 전 Phase 7 Task 7.7 / `P7-R3`로 전환.
|
||||
|
||||
## 7. 확정 항목의 plan·goal 전환
|
||||
|
||||
- Phase 7에 Task 7.5 / `P7-R1`을 추가해 완료했다.
|
||||
- 재점검에서 Task 7.6 / `P7-R2`를 추가해 완료했다.
|
||||
- 추가 재점검에서 Task 7.7 / `P7-R3`를 추가해 완료했다.
|
||||
- Task 7.3의 과거 ktlint 실패는 현재 재실행에서 PASS했으나 기존 기록과 체크박스는 유지했다.
|
||||
|
||||
## 8. 리뷰 종료 판정
|
||||
|
||||
| 판정 항목 | 결과 | 근거 |
|
||||
|---|---|---|
|
||||
| 리뷰 범위 전체 확인 | 충족 | adapter, shared Feed, locale resource 확인 |
|
||||
| 후보 항목 판정 완료 | 충족 | REV-P7-001~003 판정 완료 |
|
||||
| 확정 항목 plan 반영 | 충족 | Task 7.5, Task 7.6, Task 7.7 |
|
||||
| 검증 명령과 결과 기록 | 충족 | focused/통합 Gate PASS |
|
||||
|
||||
**최종 결론:** 확정 발견 사항 모두 수정 완료
|
||||
|
||||
**남은 항목:** 없음
|
||||
|
||||
## 9. 수정 후 검증 기록
|
||||
|
||||
- 2026-07-30: ranking 순위 단위를 `screen_home_following_ranking_rank_format` locale resource로 분리했다. 한국어는 `7위`, 영어는 `No. 7`, 일본어는 `7位`로 생성하며, 완성 문장에서 같은 문자열 범위를 `FeedRankHighlight`로 전달하도록 `HomeFollowingNewsAdapterTest`로 검증했다. focused test, Feed view test, 팔로잉 전체 회귀, resource merge, Kotlin compile, ktlint, `git diff --check` PASS.
|
||||
- 2026-07-30 리뷰 게이트 후 보완: subject에 rank 문자열이 먼저 포함되는 경우를 추가 테스트로 고정하고, highlight 시작점을 `lastIndexOf(rankText)`로 변경해 실제 삽입 rank 문자열을 강조하도록 보완했다. RED/GREEN focused test와 최종 회귀 검증 PASS.
|
||||
- 2026-07-30: Task 7.6으로 `HomeFollowingNewsAdapterTest`의 신규 ranking 테스트명 2개를 한글화하고 `docs/agent-guides/build-test-style.md`에 클래스 단위 실행 예시를 추가했다. focused test, ktlint, `git diff --check` PASS.
|
||||
- 2026-07-30: Task 7.7로 `FeedViewTest`의 content feed 크기·padding·margin source test만 제거하고 production layout/View 코드는 유지했다. Feed focused test, 팔로잉 전체 회귀, resource merge, Kotlin compile, ktlint PASS.
|
||||
- 2026-07-31 재점검: ranking locale/highlight와 Feed 회귀를 포함한 Phase 1~13 focused 113개 test, resource merge, Kotlin compile, ktlint PASS. 추가 확정 발견 사항 없음.
|
||||
- 2026-07-31 최종 검증: ranking·공용 Feed 회귀를 포함한 통합 20개 suite·306개 test와 resource merge, Kotlin compile, ktlint가 PASS했다. 추가 확정 발견 사항 없음.
|
||||
- 2026-07-31 이번 리뷰 재검증: 세 locale ranking 문장·highlight와 공용 Feed 표시 경로를 다시 대조했다. 통합 16개 suite·120개 test, resource merge, Kotlin compile, ktlint가 PASS해 추가 확정 발견 사항이 없다.
|
||||
@@ -0,0 +1,110 @@
|
||||
# Phase 8 팔로잉 크리에이터 전체 버튼 리뷰
|
||||
|
||||
## 1. 리뷰 정보
|
||||
|
||||
| 항목 | 내용 |
|
||||
|---|---|
|
||||
| 리뷰 대상 | Phase 8 / Task 8.1~8.4 |
|
||||
| 기준 commit 또는 working tree | `f600d10e8b63b6fdc812b18a874b077dfe072ca8` + 2026-07-31 working tree |
|
||||
| 리뷰 일자 | 2026-07-31 |
|
||||
| 리뷰어 | Codex |
|
||||
| 기준 문서 | 대상 `prd.md`, `plan-task.md` |
|
||||
| 리뷰 상태 | 수정 검증 완료 |
|
||||
|
||||
## 2. 리뷰 목적과 범위
|
||||
|
||||
### 목적
|
||||
|
||||
- creator가 있을 때 마지막 `전체` item을 추가하고 기존 목록 화면으로 이동하는 계약을 확인한다.
|
||||
|
||||
### 포함 범위
|
||||
|
||||
- `HomeFollowingCreatorAdapter.kt`, `item_home_following_creator_all.xml`, `HomeMainFragment.openFollowingCreatorAll()`, source test.
|
||||
|
||||
### 제외 범위
|
||||
|
||||
- `FollowingCreatorActivity` 내부 동작과 creator API pagination.
|
||||
|
||||
## 3. 판정 기준
|
||||
|
||||
- item count/view type/layout token/공통 로그인 접근 경로를 대조했다.
|
||||
|
||||
## 4. 검토한 근거
|
||||
|
||||
- `HomeFollowingCreatorAdapter.kt:18-45`, `61-73`
|
||||
- `item_home_following_creator_all.xml:2-28`
|
||||
- `HomeMainFragment.kt:115-118`, `689-693`
|
||||
- `HomeFollowingFragmentSourceTest.kt:304-334`
|
||||
|
||||
### 실행한 검증
|
||||
|
||||
| 명령 | 결과 | 핵심 증거 |
|
||||
|---|---|---|
|
||||
| `HomeFollowingFragmentSourceTest` | 성공 | 16개 테스트 실패 0 |
|
||||
| 팔로잉 전체 회귀 | 성공 | 39개 테스트 실패 0 |
|
||||
| resource/compile/ktlint/diff | 성공 | 모두 PASS |
|
||||
|
||||
## 5. 발견 사항 요약
|
||||
|
||||
| ID | 심각도 | 상태 | 제목 | 소유 Task | 후속 goal |
|
||||
|---|---|---|---|---|---|
|
||||
| `REV-P8-001` | Low | 수정 완료 | `전체` item 테스트가 금지된 UI 표현 속성을 source 문자열로 검증함 | Task 8.4 | `P8-R1` 완료 |
|
||||
|
||||
## 6. 발견 사항 상세
|
||||
|
||||
creator가 비어 있으면 all item도 숨고, 1개 이상이면 마지막 view type으로 추가된다. layout width/높이 spacer/padding/color와 로그인 가드 경로도 요구사항과 일치한다.
|
||||
|
||||
### REV-P8-001 — `전체` item 테스트가 UI 표현 속성 정책을 위반함
|
||||
|
||||
- **심각도:** Low
|
||||
- **상태:** 수정 완료
|
||||
- **관련 요구사항:** `docs/agent-guides/code-style.md` 테스트 관례
|
||||
- **소유 Task:** Task 8.4
|
||||
|
||||
**관찰 내용**
|
||||
|
||||
`following creators list appends all button as last item` 테스트는 adapter의 view type/item count/route 검증과 함께 XML의 width, height, padding, text color, visibility를 직접 assertion한다. 이 테스트는 UI 크기·padding·visibility 테스트 금지 규칙이 추가된 뒤 생성되었다.
|
||||
|
||||
**근거**
|
||||
|
||||
- 테스트: `HomeFollowingFragmentSourceTest.kt:311-341`
|
||||
- 가이드: `docs/agent-guides/code-style.md:42-43`
|
||||
- 이력: 가이드 규칙 `566f76df` 이후 테스트 `658b4f0a` 추가
|
||||
|
||||
**영향**
|
||||
|
||||
유효한 adapter 로직 검증에 금지된 UI 표현 문자열 검증이 섞여 있어, 단순 디자인/구현 변경도 기능 회귀처럼 실패하고 테스트 정책을 어긴다.
|
||||
|
||||
**권장 조치**
|
||||
|
||||
adapter view type·item count·route assertion은 유지하고 UI 표현 속성 assertion만 제거한다. 수정하는 테스트명은 한글화하고 XML 값은 정적 대조·resource merge·Task 5.3 수동 확인으로 검증한다.
|
||||
|
||||
**판정 기록**
|
||||
|
||||
- 2026-07-30 — 테스트 추가 시점과 assertion 범위를 현행 가이드와 대조해 확정.
|
||||
- 2026-07-30 — 구현 전 Phase 8 Task 8.4 / `P8-R1`로 전환.
|
||||
- 2026-07-30 — Task 8.4에서 UI 표현 source assertion만 제거하고 adapter item/route 검증을 유지했다.
|
||||
|
||||
## 7. 확정 항목의 plan·goal 전환
|
||||
|
||||
- Phase 8에 Task 8.4 / `P8-R1`을 추가해 완료했다.
|
||||
|
||||
## 8. 리뷰 종료 판정
|
||||
|
||||
| 판정 항목 | 결과 | 근거 |
|
||||
|---|---|---|
|
||||
| 리뷰 범위 전체 확인 | 충족 | adapter→layout→route 추적 |
|
||||
| 후보 항목 판정 완료 | 충족 | REV-P8-001 확정 |
|
||||
| 확정 항목 plan 반영 | 충족 | Task 8.4 |
|
||||
| 검증 명령과 결과 기록 | 충족 | focused/통합 PASS |
|
||||
|
||||
**최종 결론:** 확정 발견 사항 모두 수정 완료
|
||||
|
||||
**남은 항목:** 없음
|
||||
|
||||
## 9. 수정 후 검증 기록
|
||||
|
||||
- 2026-07-30: Task 8.4로 `전체` item 테스트명을 한글화하고 width/height/padding/visibility/color source assertion만 제거했다. adapter view type, item count, 마지막 item, `FollowingCreatorActivity` route 검증은 유지했다. focused test, 팔로잉 전체 회귀, resource merge, Kotlin compile, ktlint PASS.
|
||||
- 2026-07-31 재점검: creator all item/route를 포함한 Phase 1~13 focused 113개 test, resource merge, Kotlin compile, ktlint PASS. 추가 확정 발견 사항 없음.
|
||||
- 2026-07-31 최종 검증: creator 전체 item·route 회귀를 포함한 통합 20개 suite·306개 test와 resource merge, Kotlin compile, ktlint가 PASS했다. 추가 확정 발견 사항 없음.
|
||||
- 2026-07-31 이번 리뷰 재검증: creator가 있을 때 마지막 `전체` item 추가와 로그인 가드 이동 경로를 다시 추적했다. 통합 16개 suite·120개 test, resource merge, Kotlin compile, ktlint가 PASS해 추가 확정 발견 사항이 없다.
|
||||
@@ -0,0 +1,168 @@
|
||||
# Phase 9 최근 소식 nested payload 리뷰
|
||||
|
||||
## 1. 리뷰 정보
|
||||
|
||||
| 항목 | 내용 |
|
||||
|---|---|
|
||||
| 리뷰 대상 | Phase 9 / Task 9.1~9.7 |
|
||||
| 기준 commit 또는 working tree | `f600d10e8b63b6fdc812b18a874b077dfe072ca8` + 2026-07-31 working tree |
|
||||
| 리뷰 일자 | 2026-07-31 |
|
||||
| 리뷰어 | Codex |
|
||||
| 기준 문서 | 대상 `prd.md`, `plan-task.md` |
|
||||
| 리뷰 상태 | 수정 검증 완료 |
|
||||
|
||||
## 2. 리뷰 목적과 범위
|
||||
|
||||
### 목적
|
||||
|
||||
- type별 nested payload DTO, mapper 필터, nullable image, adapter binding과 target ID 보존을 확인한다.
|
||||
- Task 9.7의 미사용 `FeedAdapter`·`FeedImageViews` 제거가 실제 호출자 0건과 일치하는지 확인한다.
|
||||
|
||||
### 포함 범위
|
||||
|
||||
- `HomeFollowingModels.kt`, `HomeFollowingUiModels.kt`, `HomeFollowingMappers.kt`, `HomeFollowingNewsAdapter.kt`
|
||||
- 삭제된 `v2/widget/feed/FeedAdapter.kt`와 현재 재사용 중인 `FeedItem`, `FeedRankView`, `FeedContentView`, `FeedCommunityView`
|
||||
- mapper/source tests와 content ranking string resource
|
||||
|
||||
### 제외 범위
|
||||
|
||||
- 실제 서버 응답 샘플과 Phase 11/13 터치 목적지.
|
||||
|
||||
## 3. 판정 기준
|
||||
|
||||
- PRD의 nested payload 필드, matching payload null 제외, `contentImageUrl: String?`, `visibleFromAtUtc` 정책을 기준으로 판정했다.
|
||||
|
||||
## 4. 검토한 근거
|
||||
|
||||
- `HomeFollowingModels.kt:47-111`
|
||||
- `HomeFollowingMappers.kt:64-149`
|
||||
- `HomeFollowingUiModels.kt:55-103`
|
||||
- `HomeFollowingNewsAdapter.kt:68-167`
|
||||
- `HomeFollowingMapperTest.kt:88-182`
|
||||
|
||||
### 실행한 검증
|
||||
|
||||
| 명령 | 결과 | 핵심 증거 |
|
||||
|---|---|---|
|
||||
| mapper + Fragment source focused test | 성공 | mapper 10, source 16 테스트 실패 0 |
|
||||
| 팔로잉 전체 회귀 | 성공 | 39개 테스트 실패 0 |
|
||||
| resource/compile/ktlint/diff | 성공 | 모두 PASS |
|
||||
| nullable image binding·Coil 2.7.0 source·저장소 `dispose()` 사용례 대조 | 문제 확인 | blank 분기가 drawable만 비우고 View 요청을 해제하지 않음 |
|
||||
| DTO→mapper→Feed item의 ID 의미 대조 | 문제 확인 | content/post ID가 creator ID 필드에 대입됨 |
|
||||
| `rg -n "FeedAdapter|FeedImageViews" app/src/main/java app/src/test/java docs/20260625_메인_홈_팔로잉_탭 docs/agent-guides` | 성공 | production/test 호출자 0건, Task 9.7 이력만 남음 |
|
||||
|
||||
## 5. 발견 사항 요약
|
||||
|
||||
| ID | 심각도 | 상태 | 제목 | 소유 Task | 후속 goal |
|
||||
|---|---|---|---|---|---|
|
||||
| `REV-P9-001` | Medium | 수정 완료 | nullable 최근 소식 이미지 바인딩이 이전 Coil 요청을 해제하지 않음 | Task 9.5 | `P9-R1` 완료 |
|
||||
| `REV-P9-002` | Low | 수정 완료 | API에 없는 creator ID를 content/post ID로 합성해 Feed model에 전달함 | Task 9.6 | `P9-R2` 완료 |
|
||||
|
||||
## 6. 발견 사항 상세
|
||||
|
||||
matching payload가 null이면 `mapNotNull`로 제외되고, content image null은 UI model까지 보존된다. `visibleFromAtUtc` 기준 상대 시간과 payload별 target ID도 현재 계약과 일치한다. Task 9.7에서 삭제한 `FeedAdapter`와 `FeedImageViews`는 production/test 호출자가 없고, 최근 소식은 현재 `FeedItem`과 타입별 Feed view를 직접 재사용하므로 삭제에 따른 확정 발견 사항은 없다.
|
||||
|
||||
### REV-P9-001 — nullable 최근 소식 이미지 바인딩이 이전 Coil 요청을 해제하지 않음
|
||||
|
||||
- **심각도:** Medium
|
||||
- **상태:** 수정 완료
|
||||
- **관련 요구사항:** PRD `contentImageUrl`·`imageUrl` nullable 계약, Task 9.3 Feed image fallback
|
||||
- **소유 Task:** Task 9.5
|
||||
|
||||
**관찰 내용**
|
||||
|
||||
`HomeFollowingNewsAdapter.bindImage()`는 blank URL에서 `setImageDrawable(null)`만 호출한다. 같은 ViewHolder가 이미지가 있는 item에서 nullable image item으로 재사용될 때 이전 Coil 요청이 진행 중이면, 그 요청이 완료되면서 현재 item에 이전 이미지가 표시될 수 있다.
|
||||
|
||||
**근거**
|
||||
|
||||
- 코드: `HomeFollowingNewsAdapter.kt:187-203`의 blank 분기에 `dispose()`가 없음
|
||||
- 계약: `FollowingContentNewsResponse.contentImageUrl`, `FollowingContentRankingNewsResponse.contentImageUrl`, `FollowingCommunityPostNewsResponse.imageUrl`은 nullable
|
||||
- 테스트: `HomeFollowingMapperTest`는 null 보존만 확인하고 adapter 재사용 시 이미지 요청 상태는 검증하지 않음
|
||||
- 저장소 정상 사용례: `HomePopularCommunityAdapter.kt:67-70`은 blank image에서 `imageView.dispose()`와 drawable 초기화를 함께 수행함
|
||||
- Coil 2.7.0 로컬 source: `ImageView.dispose()`는 View의 현재 요청을 취소하고 분리함
|
||||
|
||||
**재현 또는 검증 절차**
|
||||
|
||||
1. 최근 소식 ViewHolder의 image view에 item A의 완료 전 Coil 요청을 연결한다.
|
||||
2. 같은 holder에 `contentImageUrl = null` 또는 `imageUrl = null`인 item B를 바인딩한다.
|
||||
3. 현재 blank 분기는 drawable만 비우므로 요청 A가 남는다.
|
||||
4. 요청 A가 완료되면 B에 A의 이미지가 표시될 수 있다. 요구 결과는 blank 바인딩 시 요청을 해제하고 빈 이미지 상태를 유지하는 것이다.
|
||||
|
||||
**영향**
|
||||
|
||||
빠른 스크롤이나 느린 이미지 응답 조건에서 ranking/content/community 최근 소식 카드에 다른 item의 이미지가 노출될 수 있다.
|
||||
|
||||
**권장 조치**
|
||||
|
||||
공유되는 `bindImage()` blank 분기에서 `imageView.dispose()` 후 drawable을 비운다. 한 대표 nullable content item의 ViewHolder 재사용을 Robolectric test로 고정하고 mapper/Feed 회귀를 실행한다.
|
||||
|
||||
**판정 기록**
|
||||
|
||||
- 2026-07-30 — nullable DTO·adapter binding·Coil request lifecycle·저장소 내 정상 해제 패턴을 대조해 확정.
|
||||
- 2026-07-30 — 구현 전 Phase 9 Task 9.5 / `P9-R1`로 전환.
|
||||
- 2026-07-30 — Task 9.5에서 `HomeFollowingNewsAdapter.bindImage()` blank 분기에 `dispose()`를 추가하고, Robolectric adapter binding test와 팔로잉 회귀 검증을 완료.
|
||||
|
||||
### REV-P9-002 — API에 없는 creator ID를 다른 target ID로 합성함
|
||||
|
||||
- **심각도:** Low
|
||||
- **상태:** 수정 완료
|
||||
- **관련 요구사항:** Task 6.4의 API 미제공 값 비합성 정책, Phase 9 nested payload 계약
|
||||
- **소유 Task:** 신규 Task 9.6
|
||||
|
||||
**관찰 내용**
|
||||
|
||||
`FollowingContentNewsResponse`와 `FollowingCommunityPostNewsResponse`에는 `creatorId`가 없지만 adapter가 `FeedItem.Content.creatorId`에는 `content.targetId`, `FeedItem.Community.creatorId`에는 `community.targetId`를 문자열로 넣는다. 두 target은 각각 `contentId`, `postId`이므로 creator ID가 아니다.
|
||||
|
||||
**근거**
|
||||
|
||||
- DTO: `HomeFollowingModels.kt`의 content/community nested payload에는 `creatorId` 없음
|
||||
- mapper: content `targetId = contentId`, community `targetId = postId`
|
||||
- adapter: `HomeFollowingNewsAdapter.kt`에서 두 `FeedItem.creatorId`에 각각 위 target ID를 대입
|
||||
- 현재 클릭 경로: adapter callback은 원본 `HomeFollowingNewsUiItem`을 캡처하므로 현행 상세 이동에는 잘못된 `creatorId`가 사용되지 않음
|
||||
|
||||
**재현 또는 검증 절차**
|
||||
|
||||
1. content/community nested payload와 UI model의 target ID 의미를 대조한다.
|
||||
2. 두 Feed item binding의 `creatorId` 대입값을 확인한다.
|
||||
3. 실제 결과는 content/post ID가 creator ID 필드에 들어가며, 요구 결과는 서버가 제공하지 않은 ID를 합성하지 않는 것이다.
|
||||
|
||||
**영향**
|
||||
|
||||
현재 화면 클릭에는 직접 영향이 없지만 Feed model의 의미가 잘못되고, 공통 Feed 위젯이 추후 creator ID를 사용하면 잘못된 크리에이터 이동이나 분석 값으로 이어질 수 있다.
|
||||
|
||||
**권장 조치**
|
||||
|
||||
서버 계약을 추정해 확장하지 말고 두 Feed item의 `creatorId`를 빈 값으로 전달한다. 실제 `contentId`, `postId`와 기존 원본 UI model click callback은 유지한다.
|
||||
|
||||
**판정 기록**
|
||||
|
||||
- 2026-07-31 — DTO→mapper→adapter→click callback을 추적해 확정하고 Phase 9 Task 9.6 / `P9-R2`로 전환.
|
||||
- 2026-07-31 — Task 9.6에서 `FeedItem.Content`와 `FeedItem.Community`의 `creatorId`를 빈 값으로 전달하도록 수정하고 focused/팔로잉 회귀 검증을 완료.
|
||||
|
||||
## 7. 확정 항목의 plan·goal 전환
|
||||
|
||||
- Phase 9에 Task 9.5 / `P9-R1`을 추가했으며 구현·검증을 완료했다.
|
||||
- 최종 재점검에서 Task 9.6 / `P9-R2`를 추가했으며 creator ID 합성 제거를 완료했다.
|
||||
- Task 9.7 / `P9-R3`의 미사용 `FeedAdapter` 제거와 문서 정리를 현재 호출자 검색·컴파일·회귀 결과로 확인했다.
|
||||
|
||||
## 8. 리뷰 종료 판정
|
||||
|
||||
| 판정 항목 | 결과 | 근거 |
|
||||
|---|---|---|
|
||||
| 리뷰 범위 전체 확인 | 충족 | DTO→mapper→adapter 추적과 Task 9.7 미사용 호출자 검색 |
|
||||
| 후보 항목 판정 완료 | 충족 | REV-P9-001~002 판정 완료 |
|
||||
| 확정 항목 plan 반영 | 충족 | Task 9.5, Task 9.6 추가 |
|
||||
| 검증 명령과 결과 기록 | 충족 | focused/통합 PASS |
|
||||
|
||||
**최종 결론:** 확정 발견 사항 모두 수정 완료
|
||||
|
||||
**남은 항목:** 없음
|
||||
|
||||
## 9. 수정 후 검증 기록
|
||||
|
||||
- 2026-07-30: `REV-P9-001` 보완으로 `HomeFollowingNewsAdapter.bindImage()`의 blank image 분기에서 기존 Coil 요청을 `dispose()`로 해제한 뒤 drawable을 비우도록 변경했다. 구현 전 `HomeFollowingNewsAdapterTest` RED, 구현 후 focused GREEN, 팔로잉 전체 회귀와 신규 프로필 테스트, `:app:mergeDebugResources`, `:app:compileDebugKotlin`, `:app:ktlintCheck`, `git diff --check` PASS.
|
||||
- 2026-07-31 재점검: nested payload mapper·nullable image 회귀를 포함한 Phase 1~13 focused 113개 test, resource merge, Kotlin compile, ktlint PASS. 추가 확정 발견 사항 없음.
|
||||
- 2026-07-31 최종 재점검: API에 없는 creator ID를 content/post ID로 대신 채우는 binding을 `REV-P9-002`로 확정하고, production/test 코드를 변경하기 전에 Task 9.6 / `P9-R2`로 전환했다.
|
||||
- 2026-07-31 최종 검증: nested payload·adapter 회귀를 포함한 통합 20개 suite·306개 test와 resource merge, Kotlin compile, ktlint가 PASS했다. 자동 검증 성공과 별개로 ID 의미 계약 불일치 `REV-P9-002`는 Task 9.6의 수정 항목으로 유지했다.
|
||||
- 2026-07-31: `REV-P9-002` 보완으로 `HomeFollowingNewsAdapter`의 content/community Feed model에서 API가 제공하지 않는 `creatorId`를 content/post ID로 합성하지 않고 빈 값으로 전달하도록 변경했다. RED focused test 실패를 확인한 뒤 GREEN으로 전환했고, focused test, 팔로잉 전체 회귀, `:app:compileDebugKotlin`, `:app:ktlintCheck` PASS.
|
||||
- 2026-07-31 이번 리뷰 재검증: nested payload·nullable image·ID 의미와 Task 9.7의 미사용 `FeedAdapter` 삭제 상태를 다시 대조했다. production/test `FeedAdapter|FeedImageViews` 호출자는 0건이며, 통합 16개 suite·120개 test, resource merge, Kotlin compile, ktlint가 PASS해 추가 확정 발견 사항이 없다.
|
||||
Reference in New Issue
Block a user