# 크리에이터 채널 홈 API 구조 정렬 Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use `superpowers:subagent-driven-development` 또는 `superpowers:executing-plans`로 task 단위 구현을 진행한다. 각 단계는 체크박스(`- [ ]`)로 진행 상태를 갱신한다. **Goal:** `GET /api/v2/creator-channels/{creatorId}/home`의 공개 계약을 보존하면서 홈 API 공개 조립 계층을 `v2.api.creator.channel.home`으로 옮기고 도메인 조회 계층을 API 패키지 밖으로 정렬한다. **Architecture:** Controller, facade, response DTO는 `kr.co.vividnext.sodalive.v2.api.creator.channel.home` 하위에 두고, HTTP 계약과 공개 응답 변환만 담당한다. 조회 service, 순수 정책, domain model, port, repository는 `kr.co.vividnext.sodalive.v2.creator.channel.home` 하위에 두며 `v2.api.*`를 import하지 않는다. 기존 endpoint와 DTO 필드명은 그대로 유지하고, 기존 `v2.creator.channel.adapter.in.web.CreatorChannelHomeController`는 이동 후 남기지 않아 Spring mapping 충돌을 방지한다. **Tech Stack:** Kotlin, Spring Boot 2.7.14, Java 17, Spring MVC, Spring Data JPA, QueryDSL, JUnit 5, MockMvc, Gradle Wrapper, ktlint --- ## 0. 구현 전 확정 사항 - 작업 성격: 동작 보존 리팩토링 - 기존 공개 endpoint: `GET /api/v2/creator-channels/{creatorId}/home` - 기존 인증 정책: 인증 회원만 조회 가능, 비회원은 `common.error.bad_credentials` 계열 오류 - 공개 API 조립 패키지: - `kr.co.vividnext.sodalive.v2.api.creator.channel.home.adapter.in.web` - `kr.co.vividnext.sodalive.v2.api.creator.channel.home.application` - `kr.co.vividnext.sodalive.v2.api.creator.channel.home.dto` - 도메인 조회 패키지: - `kr.co.vividnext.sodalive.v2.creator.channel.home.application` - `kr.co.vividnext.sodalive.v2.creator.channel.home.domain` - `kr.co.vividnext.sodalive.v2.creator.channel.home.port.out` - `kr.co.vividnext.sodalive.v2.creator.channel.home.adapter.out.persistence` - 의존 방향: `v2.api.creator.channel.home -> v2.creator.channel.home` - 금지 사항: - endpoint 변경 금지 - 응답 필드명/의미 변경 금지 - 기능 추가 금지 - 라이브 탭 API 동작 변경 금지 - 불필요한 공용화 금지 ## 1. 현재 공개 계약 현재 `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/dto/CreatorChannelHomeResponse.kt` 기준 최상위 응답 필드는 아래와 같다. 구조 정렬 후에도 필드명과 의미를 유지한다. ```kotlin data class CreatorChannelHomeResponse( val creator: CreatorChannelCreatorResponse, val currentLive: CreatorChannelLiveResponse?, val latestAudioContent: CreatorChannelAudioContentResponse?, val channelDonations: List, val notices: List, val schedules: List, val audioContents: List, val series: List, val communities: List, val fanTalk: CreatorChannelFanTalkSummaryResponse, val introduce: String, val activity: CreatorChannelActivityResponse, val sns: CreatorChannelSnsResponse ) ``` 아래 `@JsonProperty` 기반 boolean 필드명은 이동 후에도 유지한다. - `creator.isAiChatAvailable` - `creator.isDmAvailable` - `creator.isFollow` - `creator.isNotify` - `currentLive.isAdult` - `latestAudioContent.isAdult` - `latestAudioContent.isPointAvailable` - `latestAudioContent.isFirstContent` - `latestAudioContent.isOriginalSeries` - `latestAudioContent.isOwned` - `latestAudioContent.isRented` - `audioContents[*].isAdult` - `audioContents[*].isPointAvailable` - `audioContents[*].isFirstContent` - `audioContents[*].isOriginalSeries` - `audioContents[*].isOwned` - `audioContents[*].isRented` - `series[*].isNew` - `series[*].isOriginal` ## 2. 파일 구조 계획 ### 공개 API 조립 계층 - Move: `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/adapter/in/web/CreatorChannelHomeController.kt` -> `src/main/kotlin/kr/co/vividnext/sodalive/v2/api/creator/channel/home/adapter/in/web/CreatorChannelHomeController.kt` - Create: `src/main/kotlin/kr/co/vividnext/sodalive/v2/api/creator/channel/home/application/CreatorChannelHomeFacade.kt` - Move: `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/dto/CreatorChannelHomeResponse.kt` -> `src/main/kotlin/kr/co/vividnext/sodalive/v2/api/creator/channel/home/dto/CreatorChannelHomeResponse.kt` ### 도메인 조회 계층 - Move: `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/application/CreatorChannelHomeQueryService.kt` -> `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/home/application/CreatorChannelHomeQueryService.kt` - Move: `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/domain/CreatorChannelHome.kt` -> `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/home/domain/CreatorChannelHome.kt` - Move: `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/domain/CreatorChannelHomeQueryPolicy.kt` -> `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/home/domain/CreatorChannelHomeQueryPolicy.kt` - Move: `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/port/out/CreatorChannelHomeQueryPort.kt` -> `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/home/port/out/CreatorChannelHomeQueryPort.kt` - Move: `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/adapter/out/persistence/CreatorChannelHomeQueryRepository.kt` -> `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/home/adapter/out/persistence/CreatorChannelHomeQueryRepository.kt` - Move: `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/adapter/out/persistence/DefaultCreatorChannelHomeQueryRepository.kt` -> `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/home/adapter/out/persistence/DefaultCreatorChannelHomeQueryRepository.kt` ### 테스트 - Move: `src/test/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/adapter/in/web/CreatorChannelHomeControllerTest.kt` -> `src/test/kotlin/kr/co/vividnext/sodalive/v2/api/creator/channel/home/adapter/in/web/CreatorChannelHomeControllerTest.kt` - Create: `src/test/kotlin/kr/co/vividnext/sodalive/v2/api/creator/channel/home/application/CreatorChannelHomeFacadeTest.kt` - Move: `src/test/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/application/CreatorChannelHomeQueryServiceTest.kt` -> `src/test/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/home/application/CreatorChannelHomeQueryServiceTest.kt` - Move: `src/test/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/domain/CreatorChannelHomeQueryPolicyTest.kt` -> `src/test/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/home/domain/CreatorChannelHomeQueryPolicyTest.kt` - Move: `src/test/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/adapter/out/persistence/DefaultCreatorChannelHomeQueryRepositoryTest.kt` -> `src/test/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/home/adapter/out/persistence/DefaultCreatorChannelHomeQueryRepositoryTest.kt` ### 문서 산출물 - Modify: `docs/20260617_크리에이터_채널_홈_API_구조정렬/plan-task.md` --- ### Phase 1: 현재 계약 고정과 이동 전 실패 확인 - [x] **Task 1.1: controller 테스트를 새 API 패키지 기준으로 이동해 실패 확인** - Files: - Move: `src/test/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/adapter/in/web/CreatorChannelHomeControllerTest.kt` -> `src/test/kotlin/kr/co/vividnext/sodalive/v2/api/creator/channel/home/adapter/in/web/CreatorChannelHomeControllerTest.kt` - Verify: `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/adapter/in/web/CreatorChannelHomeController.kt` - RED: 테스트 package와 import를 새 controller 위치인 `kr.co.vividnext.sodalive.v2.api.creator.channel.home.adapter.in.web.CreatorChannelHomeController` 기준으로 변경한다. 기존 endpoint `/api/v2/creator-channels/1/home`, 비회원 거부, 대표 JSON field path 검증은 유지한다. - 실패 확인: - Run: `./gradlew test --tests kr.co.vividnext.sodalive.v2.api.creator.channel.home.adapter.in.web.CreatorChannelHomeControllerTest` - Expected: 새 controller 패키지가 아직 없어 컴파일 실패한다. - GREEN: 아직 구현하지 않는다. 이 task는 이동 대상 controller 부재로 RED를 확인하는 단계다. - REFACTOR: 없음. - 기대 결과: 공개 API 조립 계층 이동 필요성이 테스트 실패로 고정된다. - 검증 기록(2026-06-17): `./gradlew test --tests kr.co.vividnext.sodalive.v2.api.creator.channel.home.adapter.in.web.CreatorChannelHomeControllerTest` 실행 결과 `src/test/kotlin/kr/co/vividnext/sodalive/v2/api/creator/channel/home/adapter/in/web/CreatorChannelHomeControllerTest.kt: (45, 13): Unresolved reference: CreatorChannelHomeController`로 실패했다. 새 API 패키지 controller가 아직 없어 실패한다는 RED 기대와 일치한다. - [x] **Task 1.2: facade 테스트를 추가해 공개 응답 변환 책임을 고정** - Files: - Create: `src/test/kotlin/kr/co/vividnext/sodalive/v2/api/creator/channel/home/application/CreatorChannelHomeFacadeTest.kt` - Verify: `src/main/kotlin/kr/co/vividnext/sodalive/v2/api/creator/channel/home/application/CreatorChannelHomeFacade.kt` - RED: `CreatorChannelHomeFacade`가 `CreatorChannelHomeQueryService.getHome(...)` 결과를 `CreatorChannelHomeResponse`로 변환하고 기존 필드명 의미를 유지하는지 검증하는 테스트를 작성한다. - 실패 확인: - Run: `./gradlew test --tests kr.co.vividnext.sodalive.v2.api.creator.channel.home.application.CreatorChannelHomeFacadeTest` - Expected: `CreatorChannelHomeFacade` 미존재로 컴파일 실패한다. - GREEN: 아직 구현하지 않는다. 이 task는 facade 책임 부재로 RED를 확인하는 단계다. - REFACTOR: 없음. - 기대 결과: API 조립 계층이 service 대신 response DTO 변환 책임을 갖는다는 기준이 고정된다. - 검증 기록(2026-06-17): `./gradlew test --tests kr.co.vividnext.sodalive.v2.api.creator.channel.home.application.CreatorChannelHomeFacadeTest` 실행 결과 `src/test/kotlin/kr/co/vividnext/sodalive/v2/api/creator/channel/home/application/CreatorChannelHomeFacadeTest.kt: (32, 22): Unresolved reference: CreatorChannelHomeFacade`로 실패했다. facade가 아직 없어 실패한다는 RED 기대와 일치한다. --- ### Phase 2: 공개 API 조립 계층 이동 - [x] **Task 2.1: response DTO를 `v2.api.creator.channel.home.dto`로 이동** - Files: - Move: `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/dto/CreatorChannelHomeResponse.kt` -> `src/main/kotlin/kr/co/vividnext/sodalive/v2/api/creator/channel/home/dto/CreatorChannelHomeResponse.kt` - Modify: `src/test/kotlin/kr/co/vividnext/sodalive/v2/api/creator/channel/home/application/CreatorChannelHomeFacadeTest.kt` - Modify: `src/test/kotlin/kr/co/vividnext/sodalive/v2/api/creator/channel/home/adapter/in/web/CreatorChannelHomeControllerTest.kt` - Modify: `src/test/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/application/CreatorChannelHomeQueryServiceTest.kt` - RED: Task 1.1, Task 1.2에서 response DTO 새 package import 기준 컴파일 실패를 확인한 상태를 유지한다. - GREEN: DTO 파일 package를 `kr.co.vividnext.sodalive.v2.api.creator.channel.home.dto`로 변경하고, domain model import는 새 도메인 패키지 이동 전까지 기존 경로를 임시로 사용한다. - 통과 확인: - Run: `./gradlew test --tests kr.co.vividnext.sodalive.v2.api.creator.channel.home.application.CreatorChannelHomeFacadeTest` - Expected: facade가 아직 없으면 실패가 유지된다. DTO 자체 import 오류는 해결되어야 한다. - REFACTOR: `@JsonProperty`가 이동 중 누락되지 않았는지 파일 diff로 확인한다. - 기대 결과: 공개 응답 DTO가 API 조립 계층에 위치한다. - 검증 기록(2026-06-17): `CreatorChannelHomeResponse.kt`를 `kr.co.vividnext.sodalive.v2.api.creator.channel.home.dto`로 이동하고 `CreatorChannelHomeQueryServiceTest`의 DTO import를 새 패키지로 갱신했다. 이후 `./gradlew test --tests kr.co.vividnext.sodalive.v2.creator.channel.application.CreatorChannelHomeQueryServiceTest` 실행 결과 `BUILD SUCCESSFUL`로 기존 DTO 변환 회귀 테스트 통과를 확인했다. - [x] **Task 2.2: `CreatorChannelHomeFacade`를 추가** - Files: - Create: `src/main/kotlin/kr/co/vividnext/sodalive/v2/api/creator/channel/home/application/CreatorChannelHomeFacade.kt` - Test: `src/test/kotlin/kr/co/vividnext/sodalive/v2/api/creator/channel/home/application/CreatorChannelHomeFacadeTest.kt` - RED: Task 1.2의 facade 미존재 실패를 사용한다. - GREEN: `CreatorChannelHomeFacade`를 추가하고 `CreatorChannelHomeQueryService`를 호출한 뒤 `CreatorChannelHomeResponse.from(...)`으로 변환한다. - 통과 확인: - Run: `./gradlew test --tests kr.co.vividnext.sodalive.v2.api.creator.channel.home.application.CreatorChannelHomeFacadeTest` - Expected: PASS - REFACTOR: facade에 조회 정책이나 repository 접근이 들어가지 않았는지 확인한다. - 기대 결과: 공개 API 조립 계층의 응답 변환 책임이 controller에서 facade로 이동한다. - 검증 기록(2026-06-17): `CreatorChannelHomeFacade`를 추가해 기존 `CreatorChannelHomeQueryService.getHome(...)` 결과를 `CreatorChannelHomeResponse.from(...)`으로 변환하도록 구현했다. `./gradlew test --tests kr.co.vividnext.sodalive.v2.api.creator.channel.home.application.CreatorChannelHomeFacadeTest` 실행 결과 `BUILD SUCCESSFUL`로 facade 단위 테스트 통과를 확인했다. - [x] **Task 2.3: controller를 `v2.api.creator.channel.home.adapter.in.web`으로 이동** - Files: - Move: `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/adapter/in/web/CreatorChannelHomeController.kt` -> `src/main/kotlin/kr/co/vividnext/sodalive/v2/api/creator/channel/home/adapter/in/web/CreatorChannelHomeController.kt` - Modify: `src/test/kotlin/kr/co/vividnext/sodalive/v2/api/creator/channel/home/adapter/in/web/CreatorChannelHomeControllerTest.kt` - RED: Task 1.1의 새 controller package 미존재 실패를 사용한다. - GREEN: controller package를 변경하고 직접 `CreatorChannelHomeQueryService` 대신 `CreatorChannelHomeFacade`를 주입한다. `@RequestMapping("/api/v2/creator-channels")`, `@GetMapping("/{creatorId}/home")`, `requireMember` 동작은 유지한다. - 통과 확인: - Run: `./gradlew test --tests kr.co.vividnext.sodalive.v2.api.creator.channel.home.adapter.in.web.CreatorChannelHomeControllerTest` - Expected: PASS - REFACTOR: 기존 경로에 `CreatorChannelHomeController.kt`가 남아 있지 않은지 확인한다. - Run: `rg -n "class CreatorChannelHomeController|/\\{creatorId\\}/home" src/main/kotlin/kr/co/vividnext/sodalive/v2` - Expected: home controller mapping은 새 API 패키지 controller 1건만 확인된다. - 기대 결과: Spring mapping 충돌 없이 홈 API controller가 API 조립 계층에 위치한다. - 검증 기록(2026-06-17): `CreatorChannelHomeController`를 `kr.co.vividnext.sodalive.v2.api.creator.channel.home.adapter.in.web`으로 이동하고 직접 query service 주입 대신 `CreatorChannelHomeFacade` 주입으로 변경했다. `./gradlew test --tests kr.co.vividnext.sodalive.v2.api.creator.channel.home.adapter.in.web.CreatorChannelHomeControllerTest` 실행 결과 `BUILD SUCCESSFUL`로 controller 테스트 통과를 확인했다. `rg -n "class CreatorChannelHomeController|@GetMapping\(\"/\{creatorId\}/home\"\)|package kr\.co\.vividnext\.sodalive\.v2\.creator\.channel\.adapter\." src/main/kotlin/kr/co/vividnext/sodalive/v2` 실행 결과 home controller class와 `@GetMapping("/{creatorId}/home")`은 새 API 패키지 controller 1건만 확인했다. --- ### Phase 3: 도메인 조회 계층 패키지 정렬 - [x] **Task 3.1: domain model과 query policy를 `v2.creator.channel.home.domain`으로 이동** - Files: - Move: `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/domain/CreatorChannelHome.kt` -> `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/home/domain/CreatorChannelHome.kt` - Move: `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/domain/CreatorChannelHomeQueryPolicy.kt` -> `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/home/domain/CreatorChannelHomeQueryPolicy.kt` - Move: `src/test/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/domain/CreatorChannelHomeQueryPolicyTest.kt` -> `src/test/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/home/domain/CreatorChannelHomeQueryPolicyTest.kt` - Modify: imports in moved API DTO, service, tests - RED: 이동한 테스트 package를 새 domain package 기준으로 바꾼 뒤 기존 main class 미이동 상태의 컴파일 실패를 확인한다. - 실패 확인: - Run: `./gradlew test --tests kr.co.vividnext.sodalive.v2.creator.channel.home.domain.CreatorChannelHomeQueryPolicyTest` - Expected: 새 domain package class 미존재로 컴파일 실패한다. - GREEN: domain model과 policy package를 변경하고 import를 갱신한다. - 통과 확인: - Run: `./gradlew test --tests kr.co.vividnext.sodalive.v2.creator.channel.home.domain.CreatorChannelHomeQueryPolicyTest` - Expected: PASS - REFACTOR: domain model이 `kr.co.vividnext.sodalive.v2.api`를 import하지 않는지 확인한다. - 기대 결과: 순수 domain 책임이 API 패키지 밖의 home 도메인 패키지에 위치한다. - 검증 기록(2026-06-17): `CreatorChannelHomeQueryPolicyTest`를 새 `kr.co.vividnext.sodalive.v2.creator.channel.home.domain` package로 먼저 이동한 뒤 `./gradlew test --tests kr.co.vividnext.sodalive.v2.creator.channel.home.domain.CreatorChannelHomeQueryPolicyTest`를 실행해 `Unresolved reference: CreatorChannelHomeQueryPolicy` 컴파일 실패를 확인했다. 이후 `CreatorChannelHome.kt`, `CreatorChannelHomeQueryPolicy.kt`를 새 domain package로 이동하고 API DTO, service, 관련 테스트 import를 갱신했다. 같은 테스트 재실행 결과 `BUILD SUCCESSFUL`을 확인했고, domain package의 API import 및 기존 domain package import 검색 결과 0건을 확인했다. - [x] **Task 3.2: port와 query service를 `v2.creator.channel.home` 하위로 이동** - Files: - Move: `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/application/CreatorChannelHomeQueryService.kt` -> `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/home/application/CreatorChannelHomeQueryService.kt` - Move: `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/port/out/CreatorChannelHomeQueryPort.kt` -> `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/home/port/out/CreatorChannelHomeQueryPort.kt` - Move: `src/test/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/application/CreatorChannelHomeQueryServiceTest.kt` -> `src/test/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/home/application/CreatorChannelHomeQueryServiceTest.kt` - Modify: `src/main/kotlin/kr/co/vividnext/sodalive/v2/api/creator/channel/home/application/CreatorChannelHomeFacade.kt` - RED: service 테스트 package와 imports를 새 경로로 바꾼 뒤 기존 main class 미이동 상태의 컴파일 실패를 확인한다. - 실패 확인: - Run: `./gradlew test --tests kr.co.vividnext.sodalive.v2.creator.channel.home.application.CreatorChannelHomeQueryServiceTest` - Expected: 새 service/port package class 미존재로 컴파일 실패한다. - GREEN: service와 port package를 변경하고 API facade가 새 service package를 import하도록 갱신한다. - 통과 확인: - Run: `./gradlew test --tests kr.co.vividnext.sodalive.v2.creator.channel.home.application.CreatorChannelHomeQueryServiceTest` - Run: `./gradlew test --tests kr.co.vividnext.sodalive.v2.api.creator.channel.home.application.CreatorChannelHomeFacadeTest` - Expected: PASS - REFACTOR: service가 API DTO를 import하지 않는지 확인한다. - 기대 결과: 도메인 application service가 API 조립 계층에 의존하지 않는다. - 검증 기록(2026-06-17): `CreatorChannelHomeQueryServiceTest`를 새 `kr.co.vividnext.sodalive.v2.creator.channel.home.application` package로 먼저 이동한 뒤 `./gradlew test --tests kr.co.vividnext.sodalive.v2.creator.channel.home.application.CreatorChannelHomeQueryServiceTest`를 실행해 `Unresolved reference: CreatorChannelHomeQueryService` 컴파일 실패를 확인했다. 이후 `CreatorChannelHomeQueryService.kt`와 `CreatorChannelHomeQueryPort.kt`를 각각 새 application/port package로 이동하고 facade, repository adapter, 관련 테스트 import를 갱신했다. `./gradlew test --tests kr.co.vividnext.sodalive.v2.creator.channel.home.application.CreatorChannelHomeQueryServiceTest` 실행 결과 `BUILD SUCCESSFUL`을 확인했고, 기존 service/port package 참조 검색 결과 0건을 확인했다. - [x] **Task 3.3: repository adapter를 `v2.creator.channel.home.adapter.out.persistence`로 이동** - Files: - Move: `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/adapter/out/persistence/CreatorChannelHomeQueryRepository.kt` -> `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/home/adapter/out/persistence/CreatorChannelHomeQueryRepository.kt` - Move: `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/adapter/out/persistence/DefaultCreatorChannelHomeQueryRepository.kt` -> `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/home/adapter/out/persistence/DefaultCreatorChannelHomeQueryRepository.kt` - Move: `src/test/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/adapter/out/persistence/DefaultCreatorChannelHomeQueryRepositoryTest.kt` -> `src/test/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/home/adapter/out/persistence/DefaultCreatorChannelHomeQueryRepositoryTest.kt` - Modify: imports in service and tests - RED: repository 테스트 package와 imports를 새 경로로 바꾼 뒤 기존 main class 미이동 상태의 컴파일 실패를 확인한다. - 실패 확인: - Run: `./gradlew test --tests kr.co.vividnext.sodalive.v2.creator.channel.home.adapter.out.persistence.DefaultCreatorChannelHomeQueryRepositoryTest` - Expected: 새 repository package class 미존재로 컴파일 실패한다. - GREEN: repository interface와 기본 구현체 package를 변경하고 port import를 새 경로로 갱신한다. - 통과 확인: - Run: `./gradlew test --tests kr.co.vividnext.sodalive.v2.creator.channel.home.adapter.out.persistence.DefaultCreatorChannelHomeQueryRepositoryTest` - Expected: PASS - REFACTOR: repository 조회 조건과 정렬 조건의 동작 변경이 diff에 포함되지 않았는지 확인한다. - 기대 결과: persistence adapter가 home 도메인 패키지 하위에 위치하고 기존 조회 정책을 유지한다. - 검증 기록(2026-06-17): `DefaultCreatorChannelHomeQueryRepositoryTest`를 새 `kr.co.vividnext.sodalive.v2.creator.channel.home.adapter.out.persistence` package로 먼저 이동한 뒤 `./gradlew test --tests kr.co.vividnext.sodalive.v2.creator.channel.home.adapter.out.persistence.DefaultCreatorChannelHomeQueryRepositoryTest`를 실행해 `Unresolved reference: DefaultCreatorChannelHomeQueryRepository` 컴파일 실패를 확인했다. 이후 repository interface/default 구현체를 새 persistence package로 이동하고 테스트의 hard-coded source path를 새 경로로 갱신했다. 같은 테스트 재실행 결과 Kotlin daemon fallback 경고 후 `BUILD SUCCESSFUL`을 확인했다. Phase 3 관련 5개 테스트 묶음 실행도 `BUILD SUCCESSFUL`로 통과했고, 기존 Phase 3 package 참조 검색 결과 0건을 확인했다. --- ### Phase 4: 의존 방향과 회귀 검증 - [x] **Task 4.1: 도메인 패키지의 API 패키지 의존 여부 확인** - Files: - Verify: `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator` - Verify: `src/main/kotlin/kr/co/vividnext/sodalive/v2/live` - Verify: `src/main/kotlin/kr/co/vividnext/sodalive/v2/content` - Verify: `src/main/kotlin/kr/co/vividnext/sodalive/v2/series` - RED: 해당 없음. 검색 기반 검증 task다. - TDD 예외 사유: package import 방향 검증은 실패 테스트보다 정적 검색이 더 직접적인 검증이다. - 대체 검증 방법: - Run: `rg -n "kr\\.co\\.vividnext\\.sodalive\\.v2\\.api" src/main/kotlin/kr/co/vividnext/sodalive/v2/creator src/main/kotlin/kr/co/vividnext/sodalive/v2/live src/main/kotlin/kr/co/vividnext/sodalive/v2/content src/main/kotlin/kr/co/vividnext/sodalive/v2/series` - Expected: 도메인 패키지에서 API 패키지 import 결과 0건 - GREEN: 검색 결과가 있으면 API DTO 의존을 제거하고 domain model 또는 port record 의존으로 되돌린다. - REFACTOR: 라이브 탭 API 패키지는 이번 범위에서 동작 변경하지 않았는지 diff로 확인한다. - 기대 결과: 의존 방향이 `v2.api.creator.channel.home -> 도메인 패키지`로 유지된다. - 검증 기록(2026-06-17): 계획서의 전체 검색 명령은 `src/main/kotlin/kr/co/vividnext/sodalive/v2/live`, `src/main/kotlin/kr/co/vividnext/sodalive/v2/content`, `src/main/kotlin/kr/co/vividnext/sodalive/v2/series` 경로가 현재 작업트리에 없어 경로 오류로 중단됨을 확인했다. 실제 `src/main/kotlin/kr/co/vividnext/sodalive/v2` 하위 경로는 `admin`, `api`, `can`, `chat`, `common`, `creator`, `ranking`, `recommendation`, `usercreatorchat`이며, `live`, `content`, `series`는 현재 작업트리에 없다. 실제 존재하는 `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator` 경로 대상으로 `rg -n "kr\\.co\\.vividnext\\.sodalive\\.v2\\.api" src/main/kotlin/kr/co/vividnext/sodalive/v2/creator`를 재실행했고 결과 0건으로 도메인 패키지의 API 패키지 의존이 없음을 확인했다. - [x] **Task 4.2: 홈 API 관련 단위/통합 회귀 테스트 실행** - Files: - Test: `src/test/kotlin/kr/co/vividnext/sodalive/v2/api/creator/channel/home/adapter/in/web/CreatorChannelHomeControllerTest.kt` - Test: `src/test/kotlin/kr/co/vividnext/sodalive/v2/api/creator/channel/home/application/CreatorChannelHomeFacadeTest.kt` - Test: `src/test/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/home/application/CreatorChannelHomeQueryServiceTest.kt` - Test: `src/test/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/home/domain/CreatorChannelHomeQueryPolicyTest.kt` - Test: `src/test/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/home/adapter/out/persistence/DefaultCreatorChannelHomeQueryRepositoryTest.kt` - RED: Phase 1부터 Phase 3의 실패 확인 기록을 유지한다. - GREEN: 아래 테스트를 모두 통과시킨다. - 통과 확인: - Run: `./gradlew test --tests kr.co.vividnext.sodalive.v2.api.creator.channel.home.adapter.in.web.CreatorChannelHomeControllerTest --tests kr.co.vividnext.sodalive.v2.api.creator.channel.home.application.CreatorChannelHomeFacadeTest --tests kr.co.vividnext.sodalive.v2.creator.channel.home.application.CreatorChannelHomeQueryServiceTest --tests kr.co.vividnext.sodalive.v2.creator.channel.home.domain.CreatorChannelHomeQueryPolicyTest --tests kr.co.vividnext.sodalive.v2.creator.channel.home.adapter.out.persistence.DefaultCreatorChannelHomeQueryRepositoryTest` - Expected: PASS - REFACTOR: 실패가 있으면 동작 변경 없이 package/import/bean wiring 문제만 수정한다. - 기대 결과: controller, facade, service, policy, repository 회귀 테스트가 모두 통과한다. - 검증 기록(2026-06-17): `./gradlew test --tests kr.co.vividnext.sodalive.v2.api.creator.channel.home.adapter.in.web.CreatorChannelHomeControllerTest --tests kr.co.vividnext.sodalive.v2.api.creator.channel.home.application.CreatorChannelHomeFacadeTest --tests kr.co.vividnext.sodalive.v2.creator.channel.home.application.CreatorChannelHomeQueryServiceTest --tests kr.co.vividnext.sodalive.v2.creator.channel.home.domain.CreatorChannelHomeQueryPolicyTest --tests kr.co.vividnext.sodalive.v2.creator.channel.home.adapter.out.persistence.DefaultCreatorChannelHomeQueryRepositoryTest` 실행 결과 `BUILD SUCCESSFUL`을 확인했다. - [x] **Task 4.3: ktlint와 문서 검증 기록 갱신** - Files: - Modify: `docs/20260617_크리에이터_채널_홈_API_구조정렬/plan-task.md` - RED: 해당 없음. 포맷과 문서 기록 검증 task다. - TDD 예외 사유: ktlint와 문서 기록은 구현 동작 테스트가 아니라 최종 품질 게이트다. - 대체 검증 방법: - Run: `./gradlew ktlintCheck` - Expected: PASS - Run: `./gradlew tasks --all` - Expected: Gradle task 목록 출력 성공 - GREEN: 검증 결과를 각 task 아래와 하단 검증 기록에 한국어로 누적 기록한다. - REFACTOR: `git diff --name-only`로 이번 범위 밖 파일 변경이 없는지 확인한다. - 기대 결과: 포맷 검증과 문서 유지보수 검증 결과가 기록된다. - 검증 기록(2026-06-17): `./gradlew ktlintCheck` 실행 결과 `BUILD SUCCESSFUL`을 확인했다. `./gradlew tasks --all` 실행 결과 Gradle task 목록 출력 후 `BUILD SUCCESSFUL`을 확인했다. `git diff --name-only` 실행 결과 `docs/20260617_크리에이터_채널_홈_API_구조정렬/plan-task.md` 1건만 출력되어 Phase 4 문서 범위 밖 변경이 없음을 확인했다. --- ## 3. 전체 검증 기록 - 문서 생성 검증(2026-06-17): `docs/agent-guides/작업절차.md`, `docs/agent-guides/문서유지보수.md` 규칙에 따라 `docs/20260617_크리에이터_채널_홈_API_구조정렬/prd.md`와 `docs/20260617_크리에이터_채널_홈_API_구조정렬/plan-task.md`를 생성했다. - Gradle 명령 유효성 검증(2026-06-17): sandbox 내 `./gradlew tasks --all`은 `~/.gradle` wrapper lock 파일 접근 권한 문제로 실패했다. 승인 후 동일 명령을 재실행해 `BUILD SUCCESSFUL`을 확인했다. - Phase 1 RED 검증(2026-06-17): controller 테스트를 새 API 패키지로 이동하고 facade 테스트를 추가한 뒤 각 Gradle test filter를 실행했다. `CreatorChannelHomeController`와 `CreatorChannelHomeFacade`의 새 API 패키지 production class 미존재로 `compileTestKotlin`이 실패해 Phase 1의 실패 확인 목표를 충족했다. - Phase 3 패키지 정렬 검증(2026-06-17): domain, service/port, repository adapter를 `kr.co.vividnext.sodalive.v2.creator.channel.home` 하위로 순차 이동했다. 각 task에서 테스트 파일 선이동 RED를 확인한 뒤 production package/import를 갱신했고, `./gradlew test --tests kr.co.vividnext.sodalive.v2.api.creator.channel.home.adapter.in.web.CreatorChannelHomeControllerTest --tests kr.co.vividnext.sodalive.v2.api.creator.channel.home.application.CreatorChannelHomeFacadeTest --tests kr.co.vividnext.sodalive.v2.creator.channel.home.application.CreatorChannelHomeQueryServiceTest --tests kr.co.vividnext.sodalive.v2.creator.channel.home.domain.CreatorChannelHomeQueryPolicyTest --tests kr.co.vividnext.sodalive.v2.creator.channel.home.adapter.out.persistence.DefaultCreatorChannelHomeQueryRepositoryTest` 실행 결과 `BUILD SUCCESSFUL`을 확인했다. - Phase 4 의존 방향 및 회귀 검증(2026-06-17): 실제 `src/main/kotlin/kr/co/vividnext/sodalive/v2` 하위 경로는 `admin`, `api`, `can`, `chat`, `common`, `creator`, `ranking`, `recommendation`, `usercreatorchat`이며, 계획서에 포함된 `live`, `content`, `series` 경로는 현재 작업트리에 없어 존재 경로 기준으로 검증 기록을 남겼다. `src/main/kotlin/kr/co/vividnext/sodalive/v2/creator` 대상 API 패키지 의존 검색 결과 0건을 확인했다. 홈 API 관련 5개 테스트 묶음, `./gradlew ktlintCheck`, `./gradlew tasks --all`은 모두 `BUILD SUCCESSFUL`로 통과했다. `git diff --name-only` 결과 Phase 4 문서 범위인 `docs/20260617_크리에이터_채널_홈_API_구조정렬/plan-task.md` 1건만 변경됐음을 확인했다.