[JPA] OSIV(Open Session In View)
OSIV(Open Session In View)?
OSIV는 영속성 컨텍스트를 뷰까지 열어두는 기능이다.
영속성 컨텍스트가 뷰까지 유지된다면 엔티티가 영속 상태로 유지되어 있어, 뷰에서도 지연 로딩을 사용할 수 있다.
즉 OSIV가 활성화 된 상태에서는 다음과 같이 영속성 컨텍스트 생존 범위가 요청이 끝나는 시점까지 유지된다.
OSIV가 활성화 상태일 때 동작은 다음과 같다.
- 클라이언트의 요청이 들어오면 서블릿 필터나, 스프링 인터셉터에서 영속성 컨텍스트를 생성한다.
- 트랜잭션을 시작할 때 미리 생성해둔 영속성 컨텍스트를 찾아와서 트랜잭션을 시작한다.
- 서비스 계층이 끝나면 트랜잭션을 commit하고 영속성 컨텍스트를 flush한다. 이 시점에 트랜잭션은 끝나지만 영속성 컨텍스트는 종료되지 않는다.
- 컨트롤러와 뷰까지 영속성 컨텍스트가 유지되므로 조회한 엔티티는 영속 상태를 유지한다.
- 필터나 인터셉터로 요청이 돌아오면 영속성 컨텍스트를 종료한다. 이때 flush를 호출하지 않고 바로 종료한다.
영속성 컨텍스트 범위가 뷰까지 유지되어 있으므로, 트랜잭션이 끝난 컨트롤러와 뷰에서도 단순히 조회만 하는 것은 가능한데, 이를 '트랜잭션 없이 읽기'라고 한다.
그럼 OSIV가 비활성화 된 상태는 어떻게 될까?
먼저 OSIV를 비활성화 했다면 모든 Lazy Loading이 트랜잭션 안에서 이루어져야 한다. 만약 범위 외에서 이뤄진다면 다음과 같은 오류를 볼 수 있을 것이다.
(org.hibernate.LazyInitializationException: could not initialize proxy)
즉, 컨트롤러와 뷰 단에서는 지연로딩이 동작하지 않기 때문에 그 전에 모두 호출해두어야 한다는 단점이 있다.
하지만, OSIV를 비활성화하면 트랜잭션이 종료될 때 영속성 컨텍스트를 닫고 데이터베이스 커넥션도 반환하기 때문에, 리소스를 낭비하지 않는다는 장점이 있다.
OSIV 설정
OSIV는 스프링 부트에서 다음과 같이 설정할 수 있다. OSIV 설정의 default 값이 true이기 때문에 true로 설정하고 싶다면 따로 작성하지 않아도 된다.
[application.properties]
spring.jpa.open-in-view: true
[application.yml]
spring:
jpa:
open-in-view: true
OSIV 주의점
spring에서 osiv를 활성화시키면 다음과 같은 경고 문구가 뜬다.
JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
이 경고가 뜨는 이유는 리소스 때문이다.
OSIV를 사용하면 컨텍스트 유지 시간이 길어져 데이터베이스 커넥션을 오랫동안 유지하게 된다. 즉, 트래픽이 많아 질 경우 커넥션이 모자라는 상황이 생길 수 있는 것이다.
때문에, 실시간 트래픽이 많은 애플리케이션에서는 OSIV를 비활성화하는 것이 더 권장된다.
'Backend > JPA' 카테고리의 다른 글
[JPA] N+1 문제 (1) | 2023.04.03 |
---|