Home OSIV
Post
Cancel

OSIV

OSIV

osiv

OSIV : Open Session In View

  • spring.jpa.open-in-view
  • JPA EntityManager를 request의 전체 처리 과정동안 thread에 binding한다.
  • request의 life cycle동안 lazy loading을 사용할 수 있게한다.

org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor

  • spring web request interceptor

org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter

  • servlet filter

osiv 옵션을 켜게 되면 위의 filter / interceptor에서 request가 오는 시점에 해당 thread에 entity manger를 매핑한다.

그리고 response가 나가는 시점에 해당 filter / interceptor에서 entity manager를 종료한다.

request의 전체 life cycle동안 lazy loading을 자유롭게 사용할 수 있는 장점이 있지만, database connection을 계속 들고 있다는 문제점이 있다.

사용자의 트래픽이 몰리거나 API 호출 과정에서 외부 API 호출과 같이 오버헤드가 큰 API라면 database connection이 부족해지는 상황이 발생할 수 있고, 이는 곧 장애로 이어질 수 있다.

OSIV 옵션을 끄게 되면 transaction 생성 ~ 종료 시점에만 entity manager를 가지고 있게 된다.

즉, 꼭 필요한 부분에서만 database connection을 사용하게 하는 것이다.

하지만 이때 transaction 밖에서 lazy loading을 사용하려고 하면 LazyInitializationException이 발생하게 된다.

이 문제를 해결하기 위해서는 transaction 안에서 entity들을 모두 초기화 시켜 놓아야 한다.

fetch join, @EntityGraph, Hibernate.initialize()와 같은 방법으로 위의 문제를 회피할 수 있다.

정리

각 기술은 trade-off가 있다.

OSIV 옵션을 사용하면 Lazy Loading의 자유로운 사용으로 개발 생산성을 향상시킬 수 있지만, 예상치 못한 곳에서 N + 1 문제를 마주할 수 있고, database connection 부족으로 장애가 발생할 수 있다는 문제가 있다.

OSIV 옵션을 사용하지 않으면, transaction안에서 모든 연관관계의 객체를 초기화시켜야 한다는 불편함이 있지만 꼭 필요한 곳에서만 database connection을 사용하고 반환하여 더 많은 사용자가 application을 이용할 수 있게 한다.

This post is licensed under CC BY 4.0 by the author.

save와 saveAll의 성능 차이

-