JPA #9 - OSIV

업데이트:


JPA 학습

API 개발 고급 - OSIV

OSIV가 무엇이고 설정에 따른 장단점을 알아보자

개요

  • Open Session In View : 하이버네이트
  • Open EntityManager In View : JPA
  • 관례상 OSIV라고 하며, spring.jpa.open-in-view: true 기본값이다.

소개

  • JPA가 언제 데이터베이스 커넥션을 획득할까?
  • 데이터베이스 트랜잭션이 시작할 때, JPA 영속성 컨텍스트가 데이터베이스 커넥션을 획득한다.
  • 그렇다면 언제 다시 데이터베이스 커넥션 자원을 반환 해야할까?
  • OSIV 설정에 따라 영속성 컨텍스트 유지와 데이터베이스 커넥션 반환 시점이 다르다.

OSIV가 true인 경우

image

  • 서비스 클래스 메서드에 @Transactional로 선언된 메서드가 끝나도 데이터베이스 커넥션 자원을 반환하지 않고 영속성 컨텍스트를 컨트롤러 단 까지 가져간다.
    • 영속성 컨텍스트는 기본적으로 데이터 베이스 커넥션을 유지한다.
  • 지연 로딩으로 만들어진 프록시 객체를 초기화하기 위해서는 데이터베이스 커넥션을 통해 프록시 객체를 초기화 하고, 영속성 컨텍스트가 살아 있어야 한다.
  • 일반적인 경우라면 트랜잭션(@Transactional)이 끝나는 시점에 데이터 베이스 커넥션을 반환하고 영속성 컨텍스트도 해제된다.
  • 그러나 OSIV 설정이 true인 경우에는 영속성 컨텍스트가 컨트롤러단에서 응답할 때까지 살아있다.
  • 그렇기 때문에 view template이나 API 컨틀롤러에서 지연 로딩으로 프록시 객체 초기화가 가능했던 것이다.
  • 장점
    • 개발 입장에서 중복을 줄이고 유연하게 개발 가능하며 유지보수가 좋다.
  • 단점
    • 오랜시간 데이터베이스 커넥션 리소스를 사용하기 때문에 실시간 트래픽이 중요한 애플리케이션에서는 커넥션이 마를 수 있고 장애로 이어질 수 있다.
    • 예를 들어 컨트롤러에서 외부 API를 호출하면 외부 API 대기시간만큼 커넥션 리소스를 반환하지 못하고 유지해야 한다.
    • 이 과정에서 블록킹이라도 걸리면 커넥션 리소스를 계속 차지하고 있게 된다.

OSIV가 false 경우

image

  • 트랜잭션이 종료될 때 영속성 컨텍스를 닫고 데이터베이스 커넥션도 반환한다.

  • 장점

    • 데이터베이스 커넥션 리소스를 낭비하지 않으며 성능이 좋다.
  • 단점

    • 모든 지연로딩을 트랜잭션 안에서 처리해야한다. 즉, view template에서 지연로딩이 동작하지 않으며 트랜잭션이 끝나기 전에 지연로딩을 강제 호출해야한다.

    • 해결방법은 일반적으로는 서비스 클래스의 트랜잭션(@Transactional) 내에서 모든 지연로딩을 호출하거나, 추가적으로는 fetch join으로 초기에 모든 데이터를 불러와 해결할 수 있다.

      // 예시
      OrderService : 핵심 비즈니스 로직
      OrderQueryService : 화면이나 API에 맞춘 서비스 (주로 읽기전용 트랜잭션 사용)
      

정리

  • 보통 서비스 계층에서 트랜잭션을 유지한다. 두 서비스 모두 트랜잭션을 유지하면서 지연 로딩을 사용할 수 있다.
  • OSIV를 true로 설정
    • 커넥션 리소스를 잡아먹어 성능에 좋지 않지만, 영속성 컨텍스트가 살아있어 지연로딩을 활용할 수 있어 편하고 유지보수성에 좋다.
    • 트래픽이 많은 경우 커넥션 리소스 고갈로 장애가 발생할 수 있다.
  • OSIV를 false로 설정
    • 트랜잭션이 종료되는 시점에 커넥션 리소스를 바로 반환하여 성능에 좋다.
  • 고객 트래픽이 많은 일반 서버의 경우 OSIV를 false로 설정하고 개발하는 걸 권장한다.
  • 그러나 admin 시스템 서버처럼 트래픽이 적은 경우에는 OSIV를 true로 설정하고 편하게 작업해도 무방하다.
  • 즉, 트래픽에 맞춰 적당히 선택해서 개발하면 되겠다.

Reference

댓글남기기