# 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차 정적 리뷰 완료, 확정 발견 사항 없음.