docs(osiv): lazy loading 검증 기록을 남긴다
This commit is contained in:
@@ -339,6 +339,33 @@ spring:
|
||||
- 어떻게: `src/main/resources/application.yml`, `src/test/resources/application.yml`의 `spring.jpa` 아래에 `open-in-view: false`를 추가했다.
|
||||
- 결과: 확인된 lazy loading 재현 실패가 없어 production code의 service/repository/controller 수정은 하지 않았다. 공개 API 스키마 변경도 없다.
|
||||
|
||||
- [x] **Task 0.5: 운영 LazyInitializationException 회귀 보완**
|
||||
- Files:
|
||||
- Add: `src/test/kotlin/kr/co/vividnext/sodalive/osiv/OsivLazyLoadingRegressionTest.kt`
|
||||
- Modify: `src/main/kotlin/kr/co/vividnext/sodalive/chat/character/repository/ChatCharacterRepository.kt`
|
||||
- Modify: `src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt`
|
||||
- Modify: `docs/20260618_유저크리에이터채팅_WebSocket전환/prd.md`
|
||||
- Modify: `docs/20260618_유저크리에이터채팅_WebSocket전환/plan-task.md`
|
||||
- RED: `ChatCharacterService.getCharacterDetail` 반환 후 `tagMappings.tag.tag`, `getOtherCharactersBySharedTags` 반환 후 `tagMappings.tag.tag`, `RankingRepository.getCreatorRankings` 반환 후 `Member.toExplorerSectionCreator`를 트랜잭션 밖에서 접근하는 테스트를 추가한다.
|
||||
- 실패 확인:
|
||||
- Run: `./gradlew --no-daemon test -Dkotlin.compiler.execution.strategy=in-process -Dspring.jpa.open-in-view=false --tests kr.co.vividnext.sodalive.osiv.OsivLazyLoadingRegressionTest`
|
||||
- Expected: 기존 코드에서는 `LazyInitializationException` 또는 동등한 실패가 발생한다.
|
||||
- GREEN: 응답 조립에 필요한 `ChatCharacter.tagMappings.tag`, `Member.tags.tag`를 조회 쿼리에서 fetch join으로 선로딩한다.
|
||||
- 통과 확인:
|
||||
- Run: `./gradlew --no-daemon test -Dkotlin.compiler.execution.strategy=in-process -Dspring.jpa.open-in-view=false --tests kr.co.vividnext.sodalive.osiv.OsivLazyLoadingRegressionTest`
|
||||
- Expected: `BUILD SUCCESSFUL`
|
||||
- REFACTOR: 공개 API 응답 스키마와 WebSocket 관련 구현은 변경하지 않는다.
|
||||
- 검증 기록:
|
||||
- 무엇: OSIV off 상태에서 운영 오류와 같은 lazy loading 경계를 재현하는 회귀 테스트를 추가하고, 필요한 연관을 fetch join으로 선로딩했다.
|
||||
- 왜: `ChatCharacterController.getCharacterDetail`에서 `ChatCharacterTagMapping.tag`, `HomeService.fetchData`에서 `Member.tags`가 트랜잭션 밖에서 열려 `LazyInitializationException`이 발생했기 때문이다.
|
||||
- 어떻게: `OsivLazyLoadingRegressionTest`를 추가해 `ChatCharacterService.getCharacterDetail`, `ChatCharacterService.getOtherCharactersBySharedTags`, `RankingRepository.getCreatorRankings` 반환 후 트랜잭션 밖 DTO 변환을 검증했다.
|
||||
- RED: `./gradlew --no-daemon test -Dkotlin.compiler.execution.strategy=in-process -Dspring.jpa.open-in-view=false --tests kr.co.vividnext.sodalive.osiv.OsivLazyLoadingRegressionTest` 실행 결과 3개 테스트 모두 `LazyInitializationException`으로 실패했다.
|
||||
- GREEN: 같은 명령을 재실행해 `BUILD SUCCESSFUL in 1m 6s`로 통과했다.
|
||||
- 인접 회귀: `./gradlew --no-daemon cleanTest test -Dkotlin.compiler.execution.strategy=in-process -Dspring.jpa.open-in-view=false --tests kr.co.vividnext.sodalive.osiv.OsivLazyLoadingRegressionTest --tests kr.co.vividnext.sodalive.api.home.HomeServiceTest --tests kr.co.vividnext.sodalive.chat.character.controller.ChatCharacterControllerTest`가 `BUILD SUCCESSFUL in 24s`로 통과했다.
|
||||
- 전체 테스트 중단: `./gradlew --no-daemon test -Dkotlin.compiler.execution.strategy=in-process -Dspring.jpa.open-in-view=false`는 `UserCreatorChatRedisIntegrationTest` 실행 중 `OutOfMemoryError`가 발생해 즉시 중단했다. 이후 검증 범위는 OSIV 회귀와 인접 테스트로 간결화했다.
|
||||
- lint: `./gradlew --no-daemon ktlintCheck`가 `BUILD SUCCESSFUL in 14s`로 통과했다.
|
||||
- 정적 점검: `rg -n "toExplorerSectionCreator\\(|tagMappings\\.map|tagMappings\\.joinToString|\\.tagMappings" src/main/kotlin/kr/co/vividnext/sodalive -S`로 동일 패턴 후보를 확인했다. `ExplorerService`는 클래스 단위 `@Transactional(readOnly = true)` 안에서 변환하고, `HomeService`/`RankingService`는 공통 `RankingRepository.getCreatorRankings` 선로딩으로 보완했다. `TranslationSourceExtractor`와 관리자/원작 DTO 변환의 `tagMappings` 접근은 운영 stacktrace 표면이 아니므로 별도 회귀 후보로 남겼다.
|
||||
|
||||
---
|
||||
|
||||
### Phase 1: WebSocket 의존성과 인증 handshake 기반 추가
|
||||
@@ -916,3 +943,10 @@ spring:
|
||||
- OSIV off 테스트: Phase 0 묶음 검증 명령에 포함
|
||||
- 수정 방향: JPA lazy loading 직접 검증은 아니며, WebMvc 표면 회귀만 확인
|
||||
- 처리 상태: XML 기준 `CreatorChannelHomeControllerTest` 2개, `CreatorChannelLiveControllerTest` 5개 모두 `failures=0`, `errors=0`
|
||||
- API/기능: 캐릭터 상세/홈 크리에이터 랭킹 운영 회귀
|
||||
- 파일: `src/main/kotlin/kr/co/vividnext/sodalive/chat/character/controller/ChatCharacterController.kt`, `src/main/kotlin/kr/co/vividnext/sodalive/chat/character/service/ChatCharacterService.kt`, `src/main/kotlin/kr/co/vividnext/sodalive/chat/character/repository/ChatCharacterRepository.kt`, `src/main/kotlin/kr/co/vividnext/sodalive/api/home/HomeService.kt`, `src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt`
|
||||
- 위험 유형: service/repository 반환 후 controller/service DTO 변환 중 nested lazy proxy 접근
|
||||
- lazy 접근 대상: `ChatCharacter.tagMappings.tag`, `Member.tags.tag`
|
||||
- OSIV off 테스트: `OsivLazyLoadingRegressionTest`
|
||||
- 수정 방향: 상세/공유 태그 캐릭터 조회와 크리에이터 랭킹 조회에서 필요한 연관을 fetch join으로 선로딩
|
||||
- 처리 상태: `OsivLazyLoadingRegressionTest` 3개 모두 통과
|
||||
|
||||
Reference in New Issue
Block a user