diff --git a/docs/20260617_크리에이터_채널_라이브_API/plan-task.md b/docs/20260617_크리에이터_채널_라이브_API/plan-task.md index 02134acc..10179b07 100644 --- a/docs/20260617_크리에이터_채널_라이브_API/plan-task.md +++ b/docs/20260617_크리에이터_채널_라이브_API/plan-task.md @@ -359,7 +359,7 @@ private fun LocalDateTime.toUtcIso(): String { ### Phase 4: Controller와 공개 응답 -- [ ] **Task 4.1: 라이브 탭 controller endpoint 추가** +- [x] **Task 4.1: 라이브 탭 controller endpoint 추가** - Files: - Create: `src/main/kotlin/kr/co/vividnext/sodalive/v2/api/creator/channel/live/adapter/in/web/CreatorChannelLiveController.kt` - Create: `src/main/kotlin/kr/co/vividnext/sodalive/v2/api/creator/channel/live/application/CreatorChannelLiveFacade.kt` @@ -373,17 +373,19 @@ private fun LocalDateTime.toUtcIso(): String { - GREEN: `CreatorChannelLiveController`에 `@GetMapping("/{creatorId}/live")`를 추가하고 `CreatorChannelLiveFacade`를 주입한다. query parameter는 `@RequestParam(defaultValue = "LATEST") sort: ContentSort`, `@RequestParam(defaultValue = "0") page: Int`, `@RequestParam(defaultValue = "20") size: Int`로 받는다. Facade는 `CreatorChannelLiveQueryService` 결과를 공개 API DTO로 변환한다. - 통과 확인: `./gradlew test --tests kr.co.vividnext.sodalive.v2.api.creator.channel.live.adapter.in.web.CreatorChannelLiveControllerTest --tests kr.co.vividnext.sodalive.v2.api.creator.channel.live.application.CreatorChannelLiveFacadeTest` - REFACTOR: 기존 `CreatorChannelHomeController`에는 라이브 endpoint를 추가하지 않는다. + - 검증 기록(2026-06-17): RED 단계에서 `CreatorChannelLiveController`, `CreatorChannelLiveFacade`, 라이브 탭 공개 DTO 미존재 컴파일 실패를 확인했다. GREEN 단계에서 `v2.api.creator.channel.live` 하위 controller/facade/DTO를 추가하고, 인증 회원 기본 요청이 `sort=LATEST`, `page=0`, `size=20`을 facade에 전달하며 `liveReplayContentCount`, `currentLive`, `liveReplayContents`, `sort`, `page`, `size`, `hasNext`, `isOwned`, `isRented` 응답 필드를 반환하는지 `./gradlew test --tests kr.co.vividnext.sodalive.v2.api.creator.channel.live.adapter.in.web.CreatorChannelLiveControllerTest --tests kr.co.vividnext.sodalive.v2.api.creator.channel.live.application.CreatorChannelLiveFacadeTest`로 확인했다. 비회원 요청은 기존 홈 API와 같은 테스트 보안 설정에서 401로 거부됨을 확인했다. -- [ ] **Task 4.2: 잘못된 page/size validation 표면 확인** +- [x] **Task 4.2: 잘못된 page/size validation 표면 확인** - Files: - Modify: `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/live/application/CreatorChannelLiveQueryService.kt` - Test: `src/test/kotlin/kr/co/vividnext/sodalive/v2/api/creator/channel/live/adapter/in/web/CreatorChannelLiveControllerTest.kt` - Test: `src/test/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/live/application/CreatorChannelLiveQueryServiceTest.kt` - - RED: `page=-1` 또는 `size=0` 요청이 400 계열 오류로 처리되는지 controller/service 테스트를 추가한다. + - RED: `page=-1` 또는 `size=0` 요청이 기존 `SodaExceptionHandler` 오류 표면인 HTTP 200 + `success=false`로 처리되는지 controller/service 테스트를 추가한다. - 실패 확인: `./gradlew test --tests kr.co.vividnext.sodalive.v2.api.creator.channel.live.adapter.in.web.CreatorChannelLiveControllerTest --tests kr.co.vividnext.sodalive.v2.creator.channel.live.application.CreatorChannelLiveQueryServiceTest` - GREEN: service에서 `CreatorChannelLiveReplayQueryPolicy.validatePage(page, size)`를 호출하고 invalid request 예외를 던진다. - 통과 확인: `./gradlew test --tests kr.co.vividnext.sodalive.v2.api.creator.channel.live.adapter.in.web.CreatorChannelLiveControllerTest --tests kr.co.vividnext.sodalive.v2.creator.channel.live.application.CreatorChannelLiveQueryServiceTest` - REFACTOR: Spring enum binding 실패(`sort=UNKNOWN`)는 별도 custom handling을 추가하지 않고 기존 MVC 오류 흐름을 사용한다. + - 검증 기록(2026-06-17): controller 테스트에 `page=-1`, `size=0` 요청 표면을 추가하고, 기존 `SodaExceptionHandler` 흐름에 맞춰 HTTP 200 + `success=false` 응답으로 확인했다. service invalid 요청은 Phase 2에서 port 조회 전 `common.error.invalid_request`로 중단되도록 구현되어 있어 `./gradlew test --tests kr.co.vividnext.sodalive.v2.api.creator.channel.live.adapter.in.web.CreatorChannelLiveControllerTest --tests kr.co.vividnext.sodalive.v2.creator.channel.live.application.CreatorChannelLiveQueryServiceTest`로 controller 표면과 service validation 회귀를 함께 확인했다. --- @@ -494,3 +496,4 @@ private fun LocalDateTime.toUtcIso(): String { - 2026-06-17 Phase 2 검증: `CreatorChannelLiveReplayQueryPolicyTest`와 `CreatorChannelLiveQueryServiceTest`를 먼저 추가해 RED 단계에서 Phase 2 production 클래스 미존재 컴파일 실패를 확인했다. GREEN 단계에서 라이브 탭 domain/page 정책, port, service 조립을 추가하고 `./gradlew test --tests kr.co.vividnext.sodalive.v2.creator.channel.live.domain.CreatorChannelLiveReplayQueryPolicyTest --tests kr.co.vividnext.sodalive.v2.creator.channel.live.application.CreatorChannelLiveQueryServiceTest`, `./gradlew ktlintCheck`, `git diff --check` 성공을 확인했다. Phase 3 port 구현 전 Spring context가 깨지지 않도록 service는 `ObjectProvider`로 port를 지연 조회하게 했고, `./gradlew test --tests kr.co.vividnext.sodalive.support.SpringBootIntegrationSampleTest` 성공으로 대표 context 기동을 확인했다. 추가 리뷰 반영으로 `page >= 0`, `20 <= size <= 50` 검증과 invalid 요청 시 port 조회 전 중단을 보강했고, 동일 targeted 테스트와 `ktlintCheck`, `git diff --check` 성공을 확인했다. 전체 `./gradlew test`는 실행 중 기존 SpringBoot 통합 테스트들의 bean/OOM 계열 실패와 timeout이 발생해 완료하지 못했으며, Phase 2 직접 변경 범위는 위 targeted/context 검증으로 확인했다. - 2026-06-17 Phase 3 검증: `DefaultCreatorChannelLiveQueryRepositoryTest`를 먼저 추가해 RED 단계에서 `DefaultCreatorChannelLiveQueryRepository` 미존재 컴파일 실패를 확인했다. GREEN 단계에서 live tab repository interface/default 구현체를 추가하고 count/list/pagination/sort/order state/current live policy를 구현했다. `./gradlew test --tests kr.co.vividnext.sodalive.v2.creator.channel.live.adapter.out.persistence.DefaultCreatorChannelLiveQueryRepositoryTest`, `./gradlew test --tests kr.co.vividnext.sodalive.v2.creator.channel.live.application.CreatorChannelLiveQueryServiceTest --tests kr.co.vividnext.sodalive.v2.creator.channel.live.adapter.out.persistence.DefaultCreatorChannelLiveQueryRepositoryTest --tests kr.co.vividnext.sodalive.support.SpringBootIntegrationSampleTest`, `./gradlew ktlintCheck`, `git diff --check` 성공을 확인했다. 리뷰 게이트에서 Phase 3 persistence adapter 범위와 시나리오 검증에 대한 unconditional approval을 받았다. - 2026-06-17 Phase 3 리뷰 보완 검증: `isFirstContent` 의미를 PRD에 명시하고, 라이브 다시듣기 repository 테스트에 다른 테마의 더 오래된 공개 오디오가 있을 때 `다시듣기` item의 `isFirstContent`가 `false`인지 확인하는 회귀 테스트를 추가했다. RED 단계에서 기존 구현이 실패하는 것을 확인했고, first content id 조회를 기존 홈 API와 같은 전체 공개 오디오 기준으로 수정했다. 검증은 `./gradlew test --tests kr.co.vividnext.sodalive.v2.creator.channel.live.adapter.out.persistence.DefaultCreatorChannelLiveQueryRepositoryTest`, `./gradlew ktlintCheck`, `./gradlew tasks --all`, `git diff --check`로 수행했고 모두 성공했다. 검증 중 Gradle 테스트 2개를 병렬 실행했을 때 한 세션에서 QueryDSL generated source compile race로 `compileJava`가 실패했으나, 단일 세션으로 재실행한 repository 전체 테스트는 성공했다. +- 2026-06-17 Phase 4 검증: 라이브 탭 공개 API 조립 계층을 `v2.api.creator.channel.live` 하위에 추가했다. RED 단계에서 controller/facade/DTO 미존재 컴파일 실패를 확인했고, GREEN 단계에서 `CreatorChannelLiveControllerTest`, `CreatorChannelLiveFacadeTest` 통과를 확인했다. invalid `page`/`size` 요청은 기존 오류 응답 표면인 HTTP 200 + `success=false`로 확인했고, `CreatorChannelLiveQueryServiceTest`와 함께 service validation 회귀를 확인했다. 검증은 `./gradlew test --tests kr.co.vividnext.sodalive.v2.api.creator.channel.live.adapter.in.web.CreatorChannelLiveControllerTest --tests kr.co.vividnext.sodalive.v2.api.creator.channel.live.application.CreatorChannelLiveFacadeTest`, `./gradlew test --tests kr.co.vividnext.sodalive.v2.api.creator.channel.live.adapter.in.web.CreatorChannelLiveControllerTest --tests kr.co.vividnext.sodalive.v2.creator.channel.live.application.CreatorChannelLiveQueryServiceTest`, `./gradlew ktlintCheck`, `git diff --check`로 수행했고 모두 성공했다.