# PRD: 관리자 라이브 추천 크리에이터 배너 LazyInitializationException 수정 ## 1. Overview `spring.jpa.open-in-view=false` 환경에서 관리자 라이브 추천 크리에이터 배너 목록 조회 시 `RecommendLiveCreatorBanner.creator` lazy proxy 접근으로 발생하는 `LazyInitializationException`을 방지한다. --- ## 2. Problem - `AdminLiveController.getRecommendCreatorBanner(...)`는 `AdminLiveService.getRecommendCreator(...)`가 만든 관리자 추천 크리에이터 배너 목록 응답을 반환한다. - `AdminLiveRoomQueryRepository.getRecommendCreatorList(...)`는 `RecommendLiveCreatorBanner` 엔티티를 조회한다. - `RecommendLiveCreatorBanner.creator`는 `@ManyToOne(fetch = FetchType.LAZY)`이다. - `AdminLiveService.getRecommendCreator(...)`는 조회 결과를 응답 DTO로 변환하며 `it.creator!!.id`, `it.creator!!.nickname`을 읽는다. - 현재 `AdminLiveService.getRecommendCreator(...)`에는 조회 트랜잭션 경계가 없어, repository 호출 이후 영속성 컨텍스트가 닫힌 상태에서 `creator` lazy proxy 초기화를 시도하면 `org.hibernate.LazyInitializationException: could not initialize proxy [kr.co.vividnext.sodalive.member.Member#289] - no Session`이 발생할 수 있다. --- ## 3. Goals - OSIV off 환경에서도 관리자 라이브 추천 크리에이터 배너 목록 조회가 예외 없이 응답된다. - 기존 관리자 추천 크리에이터 배너 목록 API의 URL과 응답 스키마를 변경하지 않는다. - 기존 이미지 URL 조합, 기간 표시 포맷, 정렬 기준을 유지한다. - 실패 재현 테스트를 먼저 작성하고, 최소 수정으로 통과시킨다. --- ## 4. Non-Goals - OSIV 설정을 다시 켜지 않는다. - `RecommendLiveCreatorBanner.creator` fetch 전략을 전역 eager로 바꾸지 않는다. - 관리자 라이브 추천 크리에이터 배너 등록/수정/정렬 API 동작을 변경하지 않는다. - 사용자용 라이브 추천 크리에이터 조회 정책을 변경하지 않는다. - QueryDSL projection 기반으로 관리자 라이브 목록 조회 전체를 재설계하지 않는다. --- ## 5. Target Users - 관리자: 관리자 화면에서 라이브 추천 크리에이터 배너 목록을 조회하고 정렬/수정 대상을 확인하는 사용자 - 운영자: OSIV off 운영 환경에서도 관리자 배너 목록이 안정적으로 열리기를 기대하는 사용자 --- ## 6. User Stories - 관리자는 추천 크리에이터가 연결된 배너 목록을 조회할 때 서버 오류를 만나지 않아야 한다. - 관리자는 기존과 동일한 응답 필드로 크리에이터 ID, 닉네임, 이미지, 시작/종료 시간, 성인 여부를 확인할 수 있어야 한다. - 운영자는 OSIV off 설정을 유지하면서 lazy 초기화 예외를 회피할 수 있어야 한다. --- ## 7. Core Features ### Feature A. 관리자 라이브 추천 크리에이터 배너 조회 트랜잭션 보강 #### Requirements - `AdminLiveService.getRecommendCreator(...)`는 read-only 트랜잭션 경계 안에서 배너 조회와 `GetAdminRecommendCreatorResponse` 변환을 완료한다. - `AdminLiveService.getRecommendCreator(...)`는 기존처럼 `repository.getRecommendCreatorTotalCount()`와 `repository.getRecommendCreatorList(pageable)`를 사용한다. - `GetAdminRecommendCreatorResponse.totalCount`, `recommendCreatorList[].id`, `image`, `creatorId`, `creatorNickname`, `startDate`, `endDate`, `isAdult` 필드는 유지한다. - `startDate`, `endDate`는 기존처럼 UTC 저장값을 Asia/Seoul 기준 `yyyy-MM-dd HH:mm` 문자열로 변환한다. - 이미지 경로 조합은 기존처럼 `"$coverImageHost/${banner.image}"` 형식을 유지한다. #### Edge Cases - 배너가 없으면 `totalCount = 0`, `recommendCreatorList = []`를 반환한다. - 배너의 `creator`가 lazy proxy 상태로 조회되어도 서비스 트랜잭션 안에서 DTO 변환이 완료된다. - 페이지 파라미터에 따른 offset/limit와 기존 정렬(`orders asc`, `id desc`)을 유지한다. --- ## 8. Technical Constraints - Kotlin + Spring Boot 2.7.14 + Java 17 + Spring Data JPA 기준으로 구현한다. - 테스트 환경의 `spring.jpa.open-in-view=false` 설정을 유지한다. - 변경 범위는 관리자 라이브 추천 크리에이터 배너 목록 조회 흐름과 해당 테스트로 제한한다. - lazy proxy 재현은 실제 JPA 환경에서 확인할 수 있도록 서비스 통합 테스트로 검증한다. - 관리자 목록 API 응답은 실제 Spring Context, `MockMvc`, JPA fixture를 연결한 통합 테스트로 검증한다. --- ## 9. Metrics - `AdminLiveServiceIntegrationTest`에서 OSIV off 조건의 관리자 라이브 추천 크리에이터 배너 목록 응답 생성 테스트가 통과한다. - `AdminLiveControllerIntegrationTest`에서 관리자 라이브 추천 크리에이터 배너 목록 API 테스트가 통과한다. - 관련 단일 테스트와 `ktlintCheck`가 통과한다. --- ## 10. Open Questions - 없음. 해결 범위는 기존 채팅 배너 LazyInitializationException 수정과 같은 패턴의 관리자 목록 조회 안정화로 한정한다.