test #433
@@ -247,7 +247,7 @@
|
||||
- Test: `src/test/kotlin/kr/co/vividnext/sodalive/v2/recommendation/adapter/out/persistence/DefaultHomeRecommendationQueryRepositoryTest.kt`
|
||||
- RED: 라이브 최신순 20개, 활성 배너 orders 정렬 최대 20개, 동일 `orders` 배너의 랜덤 tie-breaker 정렬, 크리에이터당 최신 활동 1개만 반환하는 테스트를 작성한다. 라이브 노출 정보는 크리에이터 닉네임/프로필 이미지/라이브 번호를 포함하고, 활동 크리에이터 노출 정보는 크리에이터 프로필 이미지/닉네임/활동 타입/UTC 활동 시간/이동 대상 id를 포함하며 라이브 활동의 이동 대상 id는 nullable임을 검증한다. 배너는 비활성 이벤트 대상 `EVENT`, 비활성 크리에이터 대상 `CREATOR`, 비활성 시리즈 대상 `SERIES`, 비활성 시리즈 소유 회원 대상 `SERIES`가 제외되고, `LINK` 배너는 별도 대상 엔티티 검증 없이 배너 자체 활성 상태만으로 노출되는 repository 테스트를 함께 작성한다.
|
||||
- 실패 확인: `./gradlew test --tests kr.co.vividnext.sodalive.v2.recommendation.application.HomeRecommendationQueryServiceTest --tests kr.co.vividnext.sodalive.v2.recommendation.adapter.out.persistence.DefaultHomeRecommendationQueryRepositoryTest`
|
||||
- GREEN: `LiveRoom`, `AudioContentBanner`, `AudioContent`, `CreatorCommunity` 기반 QueryDSL 조회를 구현한다. application service는 `HomeRecommendationQueryPort`에만 의존하고 persistence 구현체가 port를 구현한다. 배너는 기존 콘텐츠 홈 배너의 앱 이동 필드를 유지하고, 동일 `orders` 값은 후보군 축소 후 랜덤화하거나 랜덤 tie-breaker를 적용한다. 배너 대상 활성 조건은 service 후처리가 아니라 repository 조회 조건으로 고정한다. 활동 타입 enum 값은 `LIVE`, `AUDIO`, `COMMUNITY`, `LIVE_REPLAY` 영문 code 그대로 유지한다. 최근 활동 `COMMUNITY`의 이동 대상 id는 커뮤니티 게시글 id가 아니라 해당 게시글 작성자 크리에이터 id를 사용한다.
|
||||
- GREEN: `LiveRoom`, `AudioContentBanner`, `AudioContent`, `CreatorCommunity` 기반 QueryDSL 조회를 구현한다. application service는 `HomeRecommendationQueryPort`에만 의존하고 persistence 구현체가 port를 구현한다. 배너는 기존 콘텐츠 홈 배너의 앱 이동 필드를 유지하고, 동일 `orders` 값은 후보군 축소 후 랜덤화하거나 랜덤 tie-breaker를 적용한다. 배너 대상 활성 조건은 service 후처리가 아니라 repository 조회 조건으로 고정한다. 활동 타입 enum 값은 `LIVE`, `AUDIO`, `COMMUNITY`, `LIVE_REPLAY` 영문 code 그대로 유지한다. 최근 활동 `COMMUNITY`의 이동 대상 id는 후속 Phase 10 기준으로 `creator_community.id`를 사용한다.
|
||||
- REFACTOR: 차단 관계, 비활성 회원, 비활성 콘텐츠/배너 제외 조건을 공통 private 조건 함수로 정리한다. 단순 조회와 대상 활성 조건은 QueryDSL/JPA 우선으로 표현하고, native SQL은 SQL 고급 기능이 필요한 쿼리에만 남긴다.
|
||||
- 기대 결과: 특정 섹션 데이터가 부족해도 service가 가능한 개수만 반환한다.
|
||||
|
||||
@@ -639,12 +639,38 @@
|
||||
|
||||
---
|
||||
|
||||
### Phase 10: 최근 활동 커뮤니티 이동 대상 id 변경
|
||||
|
||||
- [x] **Task 10.1: `COMMUNITY` 활동 `targetId`를 `creator_community.id`로 변경**
|
||||
- Files:
|
||||
- Modify: `docs/20260529_메인_홈_추천_API/prd.md`
|
||||
- Modify: `docs/20260529_메인_홈_추천_API/plan-task.md`
|
||||
- Modify: `src/main/kotlin/kr/co/vividnext/sodalive/v2/recommendation/adapter/out/persistence/DefaultHomeRecommendationQueryRepository.kt`
|
||||
- Test: `src/test/kotlin/kr/co/vividnext/sodalive/v2/recommendation/adapter/out/persistence/DefaultHomeRecommendationQueryRepositoryTest.kt`
|
||||
- RED: `findRecentlyActiveCreators` repository 테스트에서 `COMMUNITY` 활동의 `targetId`가 기존 크리에이터 id가 아니라 `creator_community.id`여야 함을 먼저 검증한다.
|
||||
- 실패 확인: `./gradlew test --tests kr.co.vividnext.sodalive.v2.recommendation.adapter.out.persistence.DefaultHomeRecommendationQueryRepositoryTest.shouldFindOneLatestActivityPerCreatorWithActivityType`
|
||||
- GREEN: native SQL의 `COMMUNITY` 활동 `target_id` select 값을 `m.id`에서 `cc.id`로 변경한다.
|
||||
- REFACTOR: 응답 DTO 스키마, 활동 타입 enum, 오디오/라이브 다시듣기 target id 의미는 변경하지 않는다.
|
||||
- 검증 기준:
|
||||
- Run: `./gradlew test --tests kr.co.vividnext.sodalive.v2.recommendation.adapter.out.persistence.DefaultHomeRecommendationQueryRepositoryTest.shouldFindOneLatestActivityPerCreatorWithActivityType`
|
||||
- Run: `./gradlew test --tests kr.co.vividnext.sodalive.v2.recommendation.adapter.out.persistence.DefaultHomeRecommendationQueryRepositoryTest`
|
||||
- Run: `./gradlew ktlintCheck`
|
||||
- Run: `./gradlew tasks --all`
|
||||
- 기대 결과: 홈 추천 `recentlyActiveCreators[]` 중 `activityType = COMMUNITY`인 item의 `targetId`가 클라이언트가 이동에 사용할 수 있는 `creator_community.id`로 내려간다.
|
||||
- 검증 기록(2026-07-10):
|
||||
- 무엇을: 홈 추천 `recentlyActiveCreators` 조회에서 `COMMUNITY` 활동의 `targetId`가 `creator_community.id`로 내려가는지 확인했다.
|
||||
- 왜: 클라이언트 이동 방식이 크리에이터 id가 아니라 커뮤니티 게시글 id를 사용하도록 변경되었기 때문이다.
|
||||
- 어떻게: RED에서 `DefaultHomeRecommendationQueryRepositoryTest.shouldFindOneLatestActivityPerCreatorWithActivityType`의 `COMMUNITY` 기대값을 `community.id`로 변경해 기존 구현이 실패하는 것을 확인했다. GREEN에서 native SQL의 `COMMUNITY` `target_id` select 값을 `m.id`에서 `cc.id`로 변경한 뒤 단일 테스트와 repository 테스트 클래스 전체를 재실행했다.
|
||||
- 결과: RED 단일 테스트는 `DefaultHomeRecommendationQueryRepositoryTest.kt:437` assertion 실패로 재현됐고, GREEN 후 `./gradlew test --tests kr.co.vividnext.sodalive.v2.recommendation.adapter.out.persistence.DefaultHomeRecommendationQueryRepositoryTest.shouldFindOneLatestActivityPerCreatorWithActivityType`, `./gradlew test --tests kr.co.vividnext.sodalive.v2.recommendation.adapter.out.persistence.DefaultHomeRecommendationQueryRepositoryTest`, `./gradlew ktlintCheck`, `./gradlew tasks --all`이 모두 `BUILD SUCCESSFUL`로 통과했다. `ktlintCheck`와 `tasks --all`은 sandbox의 `~/.gradle` lock 파일 접근 제한으로 최초 실패했고 권한 상승 재실행으로 통과했다.
|
||||
|
||||
---
|
||||
|
||||
## PRD Coverage Check
|
||||
|
||||
- Feature A: Phase 3, Phase 6, Phase 7에서 통합 조회, limit, 인증/비회원, 팔로우 제외, 콘텐츠 조회 이력, 본인인증 여부, 차단 필터, 스냅샷 빈 배열 처리를 검증한다.
|
||||
- Feature B: Task 3.1, Task 6.3에서 라이브 최신순/전체보기/비활성 회원 제외와 크리에이터 닉네임/프로필 이미지/라이브 번호 노출 필드를 검증한다.
|
||||
- Feature C: Task 3.1과 Task 7.7에서 기존 콘텐츠 홈 배너 재활용, orders 정렬, 동일 orders 랜덤 정렬, 활성 배너/콘텐츠 조건, `EVENT`/`CREATOR`/`SERIES` 대상 비활성 제외, `CREATOR`/`SERIES` 대상 양방향 차단 제외, `LINK` 배너의 자체 활성 상태 기준 노출, 앱 이동 필드 유지를 검증한다.
|
||||
- Feature D: Task 1.3, Task 3.1에서 활동 타입 영문 enum, 최신 활동 1개, 크리에이터 프로필 이미지/닉네임, UTC 시간, 이동 대상 id nullable을 검증한다.
|
||||
- Feature D: Task 1.3, Task 3.1, Task 10.1에서 활동 타입 영문 enum, 최신 활동 1개, 크리에이터 프로필 이미지/닉네임, UTC 시간, 이동 대상 id nullable, `COMMUNITY` 활동의 `creator_community.id` 이동 대상 id를 검증한다.
|
||||
- Feature E: Task 1.1, Task 1.2, Task 3.2, Task 6.3에서 데뷔일/점수/동점 랜덤 정렬/프로필 이미지와 닉네임 노출/전체보기를 검증한다.
|
||||
- Feature F: Task 1.1, Task 3.2, Task 6.3, Task 9.1에서 첫 오디오 콘텐츠 판정, 최신성 점수 구간, 예약 공개 제외, native query Boolean 계산 컬럼 매핑을 검증한다.
|
||||
- Feature G: Task 1.1, Task 2.2, Task 2.6, Task 2.7, Task 2.8, Task 2.9, Task 3.3, Task 6.3, Task 8.1, Task 8.2에서 AI 캐릭터 점수, 캐릭터 생성일 기준 신규 부스트, 스냅샷, AI 채팅 집계 범위, DB-side exact scoring, 응답 필드, 오리지널 작품명 조건, 전체보기, AI 캐릭터에 대응하는 `creatorId` 노출을 검증한다.
|
||||
@@ -659,6 +685,7 @@
|
||||
|
||||
## Verification Log
|
||||
|
||||
- 2026-07-10: 사용자 피드백에 따라 홈 추천 최근 활동 크리에이터의 `COMMUNITY` 활동 `targetId`를 기존 크리에이터 id에서 `creator_community.id`로 변경했다. PRD Feature D와 plan-task Phase 10을 보강했고, RED/GREEN으로 repository 테스트를 갱신했다. 검증으로 `./gradlew test --tests kr.co.vividnext.sodalive.v2.recommendation.adapter.out.persistence.DefaultHomeRecommendationQueryRepositoryTest.shouldFindOneLatestActivityPerCreatorWithActivityType`, `./gradlew test --tests kr.co.vividnext.sodalive.v2.recommendation.adapter.out.persistence.DefaultHomeRecommendationQueryRepositoryTest`, `./gradlew ktlintCheck`, `./gradlew tasks --all`을 실행해 모두 `BUILD SUCCESSFUL`을 확인했다. `ktlintCheck`와 `tasks --all`은 sandbox의 `~/.gradle` lock 파일 접근 제한으로 최초 실패해 권한 상승으로 재실행했다.
|
||||
- 2026-06-27: Phase 9 코드 리뷰 및 검증을 진행했다. 변경 범위가 첫 오디오 콘텐츠 native query row 매핑의 Boolean 변환 보정과 운영 회귀 테스트/문서 보강에 한정되어 있는지 확인했고, `isPointAvailable`, `isAdult`, `isOriginalSeries`가 `Boolean` 또는 `Number(0/1)` 모두에서 명시적으로 Boolean으로 변환되는지 점검했다. 리뷰 결과 수정이 필요한 결함은 발견하지 못했다. 검증으로 `./gradlew test --tests kr.co.vividnext.sodalive.v2.recommendation.adapter.out.persistence.DefaultHomeRecommendationQueryRepositoryTest.shouldMapNumericNativeBooleanFromFirstAudioContentRows`, `./gradlew test --tests kr.co.vividnext.sodalive.v2.recommendation.adapter.out.persistence.DefaultHomeRecommendationQueryRepositoryTest`, `./gradlew ktlintCheck`, `./gradlew tasks --all`, `git diff --check`, `git diff --check --cached`, `./gradlew test`를 실행했고 모두 `BUILD SUCCESSFUL` 또는 통과를 확인했다. `ktlintCheck`와 `tasks --all`은 sandbox의 `~/.gradle` lock 파일 접근 제한으로 최초 실패해 권한 상승으로 재실행했다.
|
||||
- 2026-06-23: Phase 8 코드 리뷰 및 검증을 진행했다. 변경 범위가 `creatorId` additive schema 추가에 한정되어 있는지 확인했고, `HomeAiCharacterRecommendationRecord.creatorId` → `HomeAiCharacterItem.creatorId` 매핑, `ChatCharacter.creatorMember` inner join과 활성/CREATOR/AI_CHARACTER 필터, 홈 통합/AI 캐릭터 전체보기 JSON 응답 검증 테스트를 점검했다. 리뷰 결과 수정이 필요한 결함은 발견하지 못했다. 검증으로 `./gradlew test --rerun-tasks --tests kr.co.vividnext.sodalive.v2.recommendation.application.HomeRecommendationQueryServiceTest --tests kr.co.vividnext.sodalive.v2.recommendation.adapter.out.persistence.DefaultHomeRecommendationQueryRepositoryTest --tests kr.co.vividnext.sodalive.v2.api.home.dto.recommendation.HomeRecommendationResponseTest --tests kr.co.vividnext.sodalive.v2.api.home.HomeRecommendationControllerTest`, `./gradlew ktlintCheck`, `./gradlew tasks --all`, `git diff --check`, `./gradlew test`를 실행했고 모두 `BUILD SUCCESSFUL` 또는 통과를 확인했다. `ktlintCheck`와 `tasks --all`은 sandbox의 `~/.gradle` lock 파일 접근 제한으로 최초 실패해 권한 상승으로 재실행했다.
|
||||
- 2026-06-23: Phase 8 구현을 진행했다. RED에서 `HomeAiCharacterRecommendationRecord`와 `HomeAiCharacterItem`의 `creatorId` 미구현으로 `compileTestKotlin`이 실패하는 것을 확인했고, GREEN에서 `HomeAiCharacterRecommendationRecord.creatorId`, AI 캐릭터 상세 조회의 `ChatCharacter.creatorMember` inner join 및 활성/CREATOR/AI_CHARACTER 조건, `HomeAiCharacterItem.creatorId`, facade 매핑을 추가했다. 회귀 검증으로 `./gradlew test --tests kr.co.vividnext.sodalive.v2.recommendation.application.HomeRecommendationQueryServiceTest --tests kr.co.vividnext.sodalive.v2.recommendation.adapter.out.persistence.DefaultHomeRecommendationQueryRepositoryTest --tests kr.co.vividnext.sodalive.v2.api.home.dto.recommendation.HomeRecommendationResponseTest --tests kr.co.vividnext.sodalive.v2.api.home.HomeRecommendationControllerTest`, `./gradlew ktlintCheck`, `./gradlew tasks --all`, `git diff --check`, `./gradlew test`를 실행해 모두 성공을 확인했다. `ktlintCheck`는 최초 실행에서 import 정렬 오류로 실패했고 import 순서 보정 후 `BUILD SUCCESSFUL`로 통과했다. 리뷰어 지적에 따라 `creatorMember` 누락 row 제외 테스트를 추가했고, 해당 단일 테스트와 Phase 8 대상 테스트 묶음, `ktlintCheck`를 재실행해 모두 성공한 뒤 리뷰어 재검토에서 승인받았다.
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
- 라이브 다시듣기는 콘텐츠 업로드 시 `다시듣기` 테마로 올린 경우를 의미한다.
|
||||
- 노출 정보는 크리에이터 프로필 이미지, 닉네임, 활동 타입, UTC 기반 활동 시간, 이동 대상 id를 포함한다.
|
||||
- 라이브 활동은 별도 이동 대상 id가 필요하지 않다.
|
||||
- 라이브 외 활동은 오디오/라이브 다시듣기 콘텐츠 id를 내려주며, 커뮤니티 활동은 커뮤니티 게시글 작성자 크리에이터 id를 내려준다.
|
||||
- 라이브 외 활동은 오디오/라이브 다시듣기 콘텐츠 id를 내려주며, 커뮤니티 활동은 `creator_community.id`를 내려준다.
|
||||
- 크리에이터당 최신 활동 1개만 노출한다.
|
||||
|
||||
#### Edge Cases
|
||||
|
||||
Reference in New Issue
Block a user