Spring/Spring Jpa

OSIV란? (feat.OSIV를 통한 성능 최적화)

윤밥밥 2024. 9. 25. 16:47

OSIV(Open Session In View)란?


OSIVLazy 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하여 편리함을 챙겨도 된다.