feat(home): 크리에이터 채널 홈 정책을 보강한다

This commit is contained in:
2026-07-31 01:46:39 +09:00
parent f1c2e6c50b
commit 13e0b42375
20 changed files with 1811 additions and 51 deletions

View File

@@ -0,0 +1,122 @@
# Phase 4 코드 리뷰 보고서
## 1. 리뷰 정보
| 항목 | 내용 |
|---|---|
| 리뷰 대상 | Phase 4 / Task 4.1~4.2 |
| 기준 commit 또는 working tree | `f1c2e6c5` + 2026-07-30 working tree |
| 리뷰 일자 | 2026-07-30 |
| 리뷰어 | Codex |
| 기준 문서 | `prd.md`, `plan-task.md`, 홈 API 구조 정렬 후속 문서, `docs/agent-guides/*.md` |
| 리뷰 상태 | 판정 완료 |
## 2. 목적과 범위
- service의 접근 검증, 조회자 context, 섹션 조립, 최종 정책 보정을 PRD와 대조했다.
- `CreatorChannelHomeQueryService.kt`, `MemberContentPreferenceService.kt`, 대응 service 테스트를 포함했다.
- 사용자 지시에 따라 컴파일·테스트는 실행하지 않았다.
## 3. 검토 근거
- `CreatorChannelHomeQueryService.kt:70-71``getStoredPreference(viewer)``canViewAdultContent(viewer)`를 이어서 호출한다.
- `MemberContentPreferenceService.kt:144-157`에서 `canViewAdultContent`ub294 `getStoredPreference(member).isAdult`를 다시 호출한다.
- 두 호출은 같은 요청에서 같은 `ViewerContentPreference`를 사용할 수 있으며, `getStoredPreference``REQUIRES_NEW` transaction이다.
## 4. 발견 사항
| ID | 심각도 | 상태 | 제목 | 소유 Task | 후속 goal |
|---|---|---|---|---|---|
| `REV-P4-001` | Low | 완료 | 홈 조회가 콘텐츠 선호를 같은 요청에서 두 번 조회한다 | Task 4.3 | `P4-R1` |
### REV-P4-001 — 홈 조회가 콘텐츠 선호를 같은 요청에서 두 번 조회한다
- **심각도:** Low
- **상태:** 확정
- **관련 요구사항:** Phase 4 조회자 성인 노출·콘텐츠 타입 context 조립
- **소유 Task:** Task 4.3 / `P4-R1`
**관찰 내용**
service가 이미 받은 `preference.isAdult`를 사용할 수 있지만 `canViewAdultContent(viewer)`를 다시 호출한다. 실제 bean에서는 이 메서드가 `getStoredPreference` 전체 경로를 반복한다.
**영향**
공개 응답은 바뀌지 않지만, 홈 조회마다 독립 transaction·선호·국가 context 조회가 중복된다.
**권장 조치**
`preference.isAdult`를 성인 필터에 재사용하고, service 테스트에서 별도 `canViewAdultContent` 호출이 없음을 고정한다.
**판정 기록**
- 2026-07-30 — 두 method의 정적 호출 관계와 transaction annotation으로 확정.
- 2026-07-30 — `CreatorChannelHomeQueryServiceTest` RED/GREEN으로 `preference.isAdult` 재사용과 `canViewAdultContent(viewer)` 미호출을 검증하고 완료.
## 5. plan·goal 전환
- `plan-task.md` Phase 4에 Task 4.3 / `P4-R1`을 추가했다.
- 실행 objective: `REV-P4-001`을 수정하고 service 조립 회귀를 방지한다.
## 6. 리뷰 종료 판정
| 판정 항목 | 결과 | 근거 |
|---|---|---|
| 리뷰 범위 전체 확인 | 충족 | service·선호 service·테스트 정적 대조 |
| 후보 항목 판정 완료 | 충족 | `REV-P4-001` 확정 |
| 확정 항목 plan 반영 | 충족 | Task 4.3 / `P4-R1` |
| 검증 명령과 결과 기록 | 충족 | 정적 검토만 실행, 테스트 미실행 사유 기록 |
**최종 결론:** 수정 goal 완료.
**남은 항목:** 없음.
## 7. 2차 리뷰 — 2026-07-30
### 7.1 리뷰 범위와 방법
- service/facade의 조회자 context 조립과 기본 `now` 생성 지점을 기존 라이브 목록, 홈 Following, UTC 응답·KST 월 경계 계약과 대조했다.
- 사용자 지시에 따라 테스트·컴파일·ktlint은 실행하지 않았다.
### 7.2 발견 사항
| ID | 심각도 | 상태 | 제목 | 소유 Task | 후속 goal |
|---|---|---|---|---|---|
| `REV-P4-002` | Medium | 완료 | 다른 크리에이터가 조회하면 입장 제한이 적용되지 않는다 | Task 4.4 | `P4-R2` |
| `REV-P4-003` | Medium | 완료 | 홈 기본 시각이 JVM timezone에 따라 달라진다 | Task 4.5 | `P4-R3` |
#### REV-P4-002 — 다른 크리에이터가 조회하면 입장 제한이 적용되지 않는다
- **관련 요구사항:** PRD Feature B/F의 기존 라이브 목록 동일 정책, Task 4.1
- **관찰:** service는 `isViewerCreator = viewerId == creatorId`로 계산한다. 반면 기존 라이브 목록과 `HomeFollowingQueryService`는 조회자의 `MemberRole.CREATOR` 여부를 사용하며, repository는 이 값이 true일 때 `isAvailableJoinCreator` 또는 자기 라이브 예외를 적용한다.
- **영향:** 크리에이터가 다른 크리에이터 채널을 볼 때 `isAvailableJoinCreator == false`인 현재/예약 라이브가 홈에 노출될 수 있다.
- **권장 조치:** 조회자의 role로 flag를 산출하고 다른 크리에이터 조회 회귀 테스트를 추가한다.
- **완료 기록:** 2026-07-30 — 다른 크리에이터/일반 회원/대상 본인 focused test로 `viewer.role == MemberRole.CREATOR` 계산을 검증했다.
#### REV-P4-003 — 홈 기본 시각이 JVM timezone에 따라 달라진다
- **관련 요구사항:** UTC 시간 계약, KST 기준 이번 달 후원, Task 4.1·6.4
- **관찰:** facade와 service의 기본값은 `LocalDateTime.now()`인 반면 repository는 입력 `now`를 UTC로 간주해 KST 월 경계로 변환하고 DTO도 UTC offset을 붙인다. JVM timezone을 고정하는 설정은 확인되지 않았고, 인접 `HomeFollowingQueryService`는 UTC clock을 명시한다.
- **영향:** JVM이 UTC가 아니면 공개/예약 콘텐츠 경계와 이번 달 후원 범위가 timezone offset만큼 이동하고, 응답 문자열도 실제 instant와 다를 수 있다. 현재 E2E fixture도 같은 `LocalDateTime.now()`를 사용해 이 조건을 드러내지 못한다.
- **권장 조치:** 인자 없는 조회의 `now`를 UTC로 생성하고 비 UTC JVM timezone 회귀 테스트를 추가한다.
- **완료 기록:** 2026-07-30 — facade 기본 호출을 `Asia/Seoul` JVM timezone에서 검증하고 facade/service 기본 `now`를 UTC로 고정했다.
### 7.3 plan·goal 전환과 종료 판정
- `plan-task.md` Phase 4에 Task 4.4 / `P4-R2`, Task 4.5 / `P4-R3`을 추가했다.
- **최종 결론:** Medium 2건 수정 완료.
- **남은 항목:** 없음.
## 8. 3차 리뷰 — 2026-07-31
- **대상:** 접근 검증 순서, 콘텐츠 선호 단일 조회, 조회자 role/effective gender 전달, facade·service 기본 UTC 시각과 전체 섹션 조립.
- **방법:** `CreatorChannelHomeQueryService`, `CreatorChannelHomeFacade`와 대응 service/facade 테스트를 Task 4.1~4.5 및 기존 라이브 목록 정책과 정적 대조했다. 사용자 지시에 따라 테스트·컴파일·ktlint은 실행하지 않았다.
- **결과:** `REV-P4-001`~`REV-P4-003` 수정 반영을 포함해 신규 확정 발견 사항 없음. Phase 4 후속 Task를 추가하지 않는다.
- **남은 항목:** 없음.
## 9. 4차 리뷰 — 2026-07-31
- **대상:** 접근 예외 순서, 콘텐츠 선호 단일 조회, 조회자 role/effective gender, UTC `now` 전달과 전체 섹션 조립.
- **방법:** query service/facade의 실제 호출 흐름과 service/facade 테스트를 기존 라이브 목록 정책 및 Task 4.1~4.5와 정적 대조했다. 사용자 지시에 따라 테스트·컴파일·ktlint은 실행하지 않았다.
- **결과:** 기존 `REV-P4-001`~`REV-P4-003` 보정이 유지되며 신규 확정 발견 사항 없음. Phase 4 후속 Task를 추가하지 않는다.
- **남은 항목:** 없음.