feat(home): 최근 활동 이동 식별자를 보강한다
This commit is contained in:
193
docs/20260529_메인_홈_추천_API/reviews/phase-11-review.md
Normal file
193
docs/20260529_메인_홈_추천_API/reviews/phase-11-review.md
Normal file
@@ -0,0 +1,193 @@
|
||||
# Phase 11 코드 리뷰 보고서
|
||||
|
||||
## 1. 리뷰 정보
|
||||
|
||||
| 항목 | 내용 |
|
||||
|---|---|
|
||||
| 리뷰 대상 | Phase 11 / Task 11.1~11.2 / `P11-GATE` |
|
||||
| 기준 commit 또는 working tree | `b30447f0` 기준 working tree 변경 |
|
||||
| 리뷰 일자 | 2026-07-30 |
|
||||
| 리뷰어 | Codex |
|
||||
| 기준 문서 | `docs/20260529_메인_홈_추천_API/prd.md`, `docs/20260529_메인_홈_추천_API/plan-task.md` |
|
||||
| 리뷰 상태 | 수정 검증 완료 / 2차 정적 재점검 완료 |
|
||||
|
||||
## 2. 리뷰 목적과 범위
|
||||
|
||||
### 목적
|
||||
|
||||
- Phase 11 구현이 PRD Feature D의 `creatorId`와 상태별 LIVE `targetId` 계약을 충족하는지 정적으로 확인한다.
|
||||
- 완료된 Task·Gate 기록과 실제 코드·테스트 변경이 일치하는지 확인한다.
|
||||
|
||||
### 포함 범위
|
||||
|
||||
- 코드: `RecentlyActiveCreatorRecord`, 최근 활동 native query/row mapping, `HomeActiveCreatorItem`, facade 변환
|
||||
- 테스트: 최근 활동 repository 테스트, 홈 통합 API JSON 테스트, service fixture
|
||||
- 문서: PRD Feature D, plan-task Phase 11과 Verification Log
|
||||
- 수동 검증: working tree diff, 호출 흐름, Spring JSON path matcher 의미 대조
|
||||
|
||||
### 제외 범위
|
||||
|
||||
- Phase 1~10과 Phase 11 외 기능
|
||||
- 앱 클라이언트 네비게이션 및 라이브 입장 실패 fallback 구현
|
||||
- 사용자 지시에 따른 Gradle 컴파일·테스트 재실행
|
||||
|
||||
## 3. 판정 기준
|
||||
|
||||
| 심각도 | 기준 |
|
||||
|---|---|
|
||||
| Blocker | 핵심 흐름 불능, 보안·데이터 손실 또는 완료 판정을 무효화하는 문제 |
|
||||
| High | 확정 요구사항·공개 API 계약 위반 또는 주요 회귀 |
|
||||
| Medium | 제한된 조건의 기능·복구 문제 |
|
||||
| Low | 테스트 판별력, 유지보수성 또는 문서 정합성 문제 |
|
||||
|
||||
| 상태 | 의미 |
|
||||
|---|---|
|
||||
| 후보 | 근거 확인 전 |
|
||||
| 확정 | 코드·테스트·문서 근거로 확인됨 |
|
||||
| 오탐 | 요구사항 또는 코드 근거상 문제 아님 |
|
||||
| 보류 | 외부 결정·환경 필요 |
|
||||
| 수정 완료 | 수정과 검증 완료 |
|
||||
|
||||
## 4. 검토한 근거
|
||||
|
||||
### 문서와 코드
|
||||
|
||||
- 요구사항: PRD Feature D Requirements, Response Contract, Acceptance Criteria
|
||||
- 계획: `P11-T1`, `P11-T2`, `P11-GATE`
|
||||
- 내부 조회: `DefaultHomeRecommendationQueryRepository.kt:130-208`
|
||||
- 내부 record: `HomeRecommendationQueryPort.kt:105-112`
|
||||
- 공개 응답: `HomeRecommendationResponse.kt:38-45`
|
||||
- facade: `HomeRecommendationFacade.kt:247-254`
|
||||
- repository 테스트: `DefaultHomeRecommendationQueryRepositoryTest.kt:405-467`
|
||||
- API 테스트: `HomeRecommendationControllerTest.kt:527-545`
|
||||
|
||||
### 실행 환경
|
||||
|
||||
```text
|
||||
검토 방식: working tree 정적 리뷰
|
||||
기준 commit: b30447f0
|
||||
컴파일·테스트: 사용자 지시에 따라 실행하지 않음
|
||||
민감정보: 조회·기록하지 않음
|
||||
```
|
||||
|
||||
### 실행한 검증
|
||||
|
||||
| 명령 또는 수동 검증 | 결과 | 핵심 증거 |
|
||||
|---|---|---|
|
||||
| `git status --short`, `git diff --name-status` | 성공 | Phase 11 계획의 코드·테스트 7개 파일과 문서 변경 확인 |
|
||||
| Phase 11 관련 `git diff` 및 호출 흐름 대조 | 성공 | query select/row index, record/DTO/facade 필드가 계약과 일치 |
|
||||
| Spring 5.3.29 `JsonPathResultMatchers` 로컬 source jar 확인 | 성공 | `doesNotExist()`가 누락 path와 null 값 모두 허용함을 확인 |
|
||||
| Jackson null 제외 설정 검색 | 성공 | 대상 DTO와 전역 설정에 `NON_NULL` 적용이 없음을 확인 |
|
||||
| Gradle 컴파일·테스트 | 미실행 | 사용자가 현재 통과 상태를 제공하고 재실행을 금지함 |
|
||||
|
||||
## 5. 발견 사항 요약
|
||||
|
||||
| ID | 심각도 | 상태 | 제목 | 소유 Task | 후속 goal |
|
||||
|---|---|---|---|---|---|
|
||||
| `REV-P11-001` | Low | 수정 완료 | 종료 LIVE 테스트가 targetId 누락과 null을 구분하지 못함 | Task 11.3 | `P11-R1` |
|
||||
|
||||
구현 코드에서 확정된 기능 결함은 발견하지 않았다.
|
||||
|
||||
## 6. 발견 사항 상세
|
||||
|
||||
### REV-P11-001 — 종료 LIVE 테스트가 targetId 누락과 null을 구분하지 못함
|
||||
|
||||
- **심각도:** Low
|
||||
- **상태:** 수정 완료
|
||||
- **관련 요구사항:** PRD Feature D Acceptance Criteria
|
||||
- **관련 계약:** 종료된 LIVE는 `targetId = null`
|
||||
- **소유 Task:** Task 11.3 / `P11-R1`
|
||||
|
||||
**관찰 내용**
|
||||
|
||||
`HomeRecommendationControllerTest.shouldExposeNavigationIdsForRecentlyActiveLiveCreators`는 종료 LIVE의 `targetId`를 `doesNotExist()`로 검증한다. Spring 5.3.29에서 이 matcher는 JSON path가 없을 때와 값이 null일 때 모두 통과하므로, 필드를 생략하는 회귀를 탐지하지 못한다.
|
||||
|
||||
**근거**
|
||||
|
||||
- 코드: `HomeRecommendationControllerTest.kt:545`
|
||||
- 문서: PRD Feature D의 Response Contract와 Acceptance Criteria
|
||||
- 라이브러리: Spring Test 5.3.29 `JsonPathResultMatchers.doesNotExist()` 및 `JsonPathExpectationsHelper.doesNotExist(...)`
|
||||
|
||||
**재현 또는 검증 절차**
|
||||
|
||||
1. 종료 LIVE JSON assertion이 `doesNotExist()`만 사용하는지 확인했다.
|
||||
2. 로컬 Spring Test 5.3.29 source jar에서 `doesNotExist()` 구현을 확인했다.
|
||||
3. 해당 구현은 path 평가 실패를 정상 반환하고, path가 있으면 값이 null일 때 성공한다.
|
||||
4. 따라서 현재 assertion은 `targetId` 누락과 명시적 null을 구분하지 않는다.
|
||||
|
||||
**영향**
|
||||
|
||||
현재 production 구현은 nullable DTO를 사용하고 null 제외 설정이 없어 계약과 일치하는 구조다. 그러나 이후 Jackson null 제외 설정이나 DTO annotation이 추가되어 `targetId`가 생략돼도 이 테스트는 통과하므로 공개 응답 계약 회귀를 차단하지 못한다.
|
||||
|
||||
**권장 조치**
|
||||
|
||||
같은 JSON path에 `hasJsonPath()`를 추가하고 기존 `doesNotExist()`와 함께 검증한다. production 코드는 변경하지 않는다.
|
||||
|
||||
**판정 기록**
|
||||
|
||||
- 2026-07-30 — Spring 5.3.29 matcher 구현과 PRD 계약을 대조해 Low 확정.
|
||||
- 2026-07-30 — `hasJsonPath()`와 `doesNotExist()` 조합으로 JSON path 존재와 null 값을 모두 검증하도록 수정하고 focused/API 회귀/lint/문서 검증을 완료했다.
|
||||
|
||||
## 7. 확정 항목의 plan·goal 전환
|
||||
|
||||
### 신규 회귀 수정 Task
|
||||
|
||||
- Task 11.3: 종료 LIVE `targetId`의 명시적 null JSON 계약 검증 보강
|
||||
- Goal: `P11-R1`
|
||||
- 변경 범위: `HomeRecommendationControllerTest`, plan-task, 이 review 문서
|
||||
- production 코드 변경: 없음
|
||||
|
||||
### create_goal objective 초안
|
||||
|
||||
```text
|
||||
[P11-R1]의 확정 review 항목 REV-P11-001을 수정하고 회귀를 방지한다.
|
||||
plan-task.md의 Task 11.3만 수행한다.
|
||||
종료 LIVE targetId의 JSON path 존재와 null 값을 함께 검증하고 focused test, 홈 API 회귀, lint, 문서 검증과 기록이 모두 끝나기 전에는 complete로 표시하지 않는다.
|
||||
production DTO·facade·query 변경과 관련 없는 리팩터링은 범위 밖이다.
|
||||
```
|
||||
|
||||
## 8. 리뷰 종료 판정
|
||||
|
||||
| 판정 항목 | 결과 | 근거 |
|
||||
|---|---|---|
|
||||
| 리뷰 범위 전체 확인 | 충족 | Phase 11 문서·코드·테스트 diff 대조 |
|
||||
| 후보 항목 판정 완료 | 충족 | `REV-P11-001` Low 확정 |
|
||||
| 확정 항목 plan 반영 | 충족 | Task 11.3 / `P11-R1` 추가 |
|
||||
| 보류 항목의 담당·재개 조건 기록 | 해당 없음 | 보류 항목 없음 |
|
||||
| 검증 명령과 결과 기록 | 충족 | 정적 검증 기록, Gradle 미실행 사유 명시 |
|
||||
|
||||
**최종 결론:** 수정 완료
|
||||
|
||||
**남은 항목:** 없음
|
||||
|
||||
## 9. 수정 후 검증 기록
|
||||
|
||||
- 2026-07-30: `HomeRecommendationControllerTest.shouldExposeNavigationIdsForRecentlyActiveLiveCreators`에 종료 LIVE `targetId` `hasJsonPath()` assertion을 추가해 명시적 null JSON 계약을 고정했다. focused test는 120000ms timeout 후 240000ms로 재실행해 `BUILD SUCCESSFUL`로 통과했다. 이어서 `./gradlew test --tests kr.co.vividnext.sodalive.v2.api.home.HomeRecommendationControllerTest`, `./gradlew ktlintCheck`, `./gradlew tasks --all`, `git diff --check`를 실행했고 모두 `BUILD SUCCESSFUL` 또는 무출력 통과했다. production 코드는 변경하지 않았다.
|
||||
|
||||
## 10. 2차 정적 재점검 — 2026-07-30
|
||||
|
||||
### 범위와 방법
|
||||
|
||||
- 기준: `b30447f0` 기준 현재 working tree와 `P11-R1` 반영 상태
|
||||
- 문서: PRD Feature D, plan-task Phase 11·PRD Coverage Check·Verification Log
|
||||
- 코드 흐름: native query/row mapping → `RecentlyActiveCreatorRecord` → facade → `HomeActiveCreatorItem`
|
||||
- 테스트: repository의 전체 활동 타입·LIVE 상태 분기와 홈 API JSON 계약 assertion
|
||||
- 제외: 사용자 지시에 따라 Gradle 컴파일·테스트 재실행
|
||||
|
||||
### 정적 검증 결과
|
||||
|
||||
| 검증 | 결과 | 근거 |
|
||||
|---|---|---|
|
||||
| `git diff`로 Phase 11 변경 전체 대조 | 충족 | `creatorId` select/row index/DTO/facade 매핑과 LIVE `targetId` 분기가 PRD 계약과 일치 |
|
||||
| `rg`로 record·DTO 생성자와 조회 호출 지점 확인 | 충족 | 변경 타입의 모든 생성·매핑 지점이 신규 non-null `creatorId`를 반영 |
|
||||
| nullable JSON 설정과 assertion 대조 | 충족 | 대상 DTO·전역 설정에 null 제외가 없고 `hasJsonPath()` + `doesNotExist()`가 명시적 null 계약을 고정 |
|
||||
| 비 LIVE 회귀와 LIVE 상태 분기 테스트 대조 | 충족 | AUDIO·LIVE_REPLAY·COMMUNITY의 기존 `targetId`, 진행 중/종료 LIVE, 모든 활동의 `creatorId`를 검증 |
|
||||
| 변경 Kotlin 라인 길이와 `git diff --check` | 충족 | 130자 초과 신규 Kotlin 라인 없음, whitespace 오류 없음 |
|
||||
| 과설계·범위 확장 점검 | 충족 | 신규 dependency·상태 타입·추상화 없이 기존 record/DTO/query만 최소 변경 |
|
||||
|
||||
### 발견 사항과 종료 판정
|
||||
|
||||
- 신규 후보·확정·보류 항목 없음.
|
||||
- 기존 `REV-P11-001`은 Task 11.3 / `P11-R1`에서 수정 완료 상태를 유지한다.
|
||||
- 추가로 `plan-task.md`에 전환할 회귀 수정 Task/Goal 없음.
|
||||
- **최종 결론:** Phase 11 2차 정적 리뷰 완료, 확정 발견 사항 없음.
|
||||
Reference in New Issue
Block a user