스프링에서 프록시 객체가 든 엔티티를 반환하면 여러 문제가 있더라도 동작은 한다. 포스트맨으로 응답 결과를 확인해보면 데이터도 잘 들어있기에 어딘가 getter를 호출했다고 짐작할 수 있다. 생각해보면 영속성 컨텍스트 바깥임에도 어떻게 프록시 객체를 초기화할 수 있었던 건지 궁금하다.

영속성 컨텍스트가 존재하지 않는 상황에서 지연 로딩을 시도하면 LazyInitializationException이 발생한다. 결론적으로 영속성 컨텍스트가 아직 안 닫혔기 때문에 가능한 것이다. 이는 OSIV 기능과 연관있다.

Open EntityManager in View (Open Session In View)


OSIV ON

OSIV ON

OSIV 전략은 트랜잭션 시작처럼 최초 데이터베이스 커넥션 시작 시점부터 API 응답이 끝날 때 까지 영속성 컨텍스트와 데이터베이스 커넥션을 유지한다. 그래서 프레젠테이션 계층에서 지연 로딩이 가능했던 것이다. 지연 로딩은 영속성 컨텍스트가 살아있어야 가능하고, 영속성 컨텍스트는 기본적으로 데이터베이스 커넥션을 유지한다.

스프링 부트는 기본적으로 Open EntityManager in View를 적용해서 웹 뷰에서 지연 로딩이 가능하도록 기본적으로 OpenEntityManagerInViewInterceptor를 등록합니다. 만약 이런 설정이 싫다면 설정 파일에서 spring.jpa.open-in-view: false로 설정하십시오

OpenEntityManagerInViewInterceptor


스프링 부트는 디폴트로 OSIV 옵션을 true로 가져간다. 그렇다면 OpenEntityManagerInViewInterceptor는 뭘까?

이 인터셉터는 트랜잭션 관리자가 자동으로 탐지하는 현재 스레드를 통해 JPA EntityManagers를 사용할 수 있도록 합니다.

설명에서는 필터 또는 인터셉터부터 영속성 컨텍스트가 시작한다. OpenEntityManagerInViewInterceptor은 EntityManagerFactoryAccessor라는 클래스를 상속받으니 이름대로 em을 열고 닫는 역할을 할 수 있을 것 같다.