OSIV(Open Session In View)란?
OSIV란 Lazy Loading에 관련된 설정으로
세션(세션이란 영속성 컨텍스트와 DB 커넥션을 관리하는 주체이다.)을 유저에게 응답할 때(View단, Controller단)까지 열어두거나, 닫아 두는 기능이다.
OSIV를 켜면 트랜잭션(@Transactional)이 종료된 이후에도 데이터베이스 세션이 열려있기 때문에, 뷰에서 지연 로딩이 발생할 수 있다.
- 디폴트로 열어져(On) 있다. 개발자는 임의로 키거나 끌 수 있다.
- Jpa에서는 OEIV(Open Entity In View)라고 부른다.
- Hibernate에서는 그대로 OSIV(Open Session In View)라고 부른다.
OSIV를 설정해야 하는 이유
OSIV on 해두는 경우,
요청에서 응답까지의 시간이 오래 걸리는 API의 경우 과도하게 DB 커넥션을 유지하고 있을 수 있다.
이런 경우 커넥션이 부족하게 되어 에러가 발생할 수 있다.
따라서 OSIV 설정을 통해 상황에 맞는 전략을 취해야 한다.
OSIV on
application.yml
spring:
jpa:
open-in-view: true
applcation.properties
spring.jpa.open-in-view=true
- OSIC on을 하면 유저에게 응답할 때까지 세션이 연결되어 있기 때문에 트랜잭션 밖(View단, Controller단 등)에서도 지연로딩이 가능하다.
- 기본적으로 on 되어 있기 때문에, 별도의 설정 없이도 View 단, Controller 단에서 지연 로딩된 정보를 DB에서 가져올 수있다.
- 다만 OSIV를 on하면 실시간 요청이 많은 API에서 요청에서 응답까지의 시간이 오래 걸린다면 커넥션 부족으로 에러가 날 수 있다.
동작원리는 다음과 같다.
- HTTP 요청 시작: 클라이언트가 서버로 HTTP 요청을 보내면, Spring의 Filter가 작동하여 Hibernate 세션을 연다.(이 세션이 영속성 컨텍스트, DB Connection을 관리한다.)
- 영속성 컨텍스트 생성: 세션과 함께 영속성 컨텍스트도 생성된다.(영속성 컨텍스트는 엔티티를 관리한다.)
- 서비스 계층 실행: 서비스 계층에서 트랜잭션이 시작되면서 DB 커넥션도 생성되고, 엔티티들이 조회된다. 여기서 엔티티들은 영속 상태로 유지되고, 지연 로딩 관계들은 아직 초기화되지 않는다. (예: @OneToMany나 @ManyToOne 같은 관계)
- 트랜잭션 종료 후에도 세션 유지: 트랜잭션이 종료되면 DB Connection은 닫히고, 세션, 영속성 컨텍스트는 열려 있다. 즉, 데이터베이스와 연결된 세션이 뷰 렌더링이 완료될 때까지 유지된다.
- 뷰에서 지연 로딩 사용 가능: 컨트롤러나 뷰에서 지연 로딩된 엔티티를 참조할 때, 아직 초기화되지 않은 필드들이 데이터베이스로부터 가져와진다. 이때 트랜잭션이 끝난 이후에도 세션이 열려 있기에 지연 로딩된 필드에 접근할 수 있다. 지연 로딩된 필드에 접근하면 다시 DB Connection이 열린다.
- HTTP 응답 완료 후 세션 닫힘: 뷰 렌더링이 끝나고 HTTP 응답이 완료되면, OpenEntityManagerInViewInterceptor는 Hibernate 세션을 닫고, 영속성 컨텍스트, DB Connection을 해제한다.
OSIV off
application.yml
spring:
jpa:
open-in-view: false
applcation.properties
spring.jpa.open-in-view=false
- 영속성 컨텍스트의 생존범위가 트랜잭션과 동일해지기 때문에, 트랜잭션이 종료될 때 영속성 컨텍스트와 DB 커넥션 모두 반환된다.
- off 되면, 모든 지연 로딩을 트랜잭션 내에서 처리해야 한다.
- 만약 지연 로딩을 트랜잭션 밖에서 처리하려고 한다면 에러가 발생한다.
요약
OSIV를 설정해야 하는 이유는 지연로딩에 있다.
OSIV를 꺼두면, 트랜잭션(@Transactional)이 끝나면 영속성 컨텍스트도 종료되기 때문에 트랜잭션 밖(View단, Controller단 등)에서 지연 로딩된 Proxy 객체에 대해 정보를 가져올 수 없게 된다.
OSIV를 켜두면, 트랜잭션(@Transactional) 밖에서도 지연 로딩된 정보를 가져올 수 있다.
OSIV on vs OSIV off
그럼 OSIV를 켜야할까 꺼야 할까?
- 실시간 요청이 많은 경우, OSIV를 off하여 커넥션 최적화를 해야 한다.
- ADMIN 전용 기능 처럼 요청이 적은 경우, OSIV를 on하여 편리함을 챙겨도 된다.
'Spring > Spring Jpa' 카테고리의 다른 글
LazyInitializationException과 LazyLoading의 동작원리 (0) | 2025.02.19 |
---|---|
@ManyToMany를 사용하면 안 되는 이유 (0) | 2024.10.15 |
Eager Loading(즉시 로딩) vs Lazy Loading(지연 로딩) 중 어느 전략을 사용해야 할까? (0) | 2024.09.24 |
spring jpa를 활용한 데이터 저장 성능 향상(saveAll(), bulk insert) (1) | 2024.05.16 |