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인 경우
- 서비스 클래스 메서드에
@Transactional
로 선언된 메서드가 끝나도 데이터베이스 커넥션 자원을 반환하지 않고 영속성 컨텍스트를 컨트롤러 단 까지 가져간다.- 영속성 컨텍스트는 기본적으로 데이터 베이스 커넥션을 유지한다.
- 지연 로딩으로 만들어진 프록시 객체를 초기화하기 위해서는 데이터베이스 커넥션을 통해 프록시 객체를 초기화 하고, 영속성 컨텍스트가 살아 있어야 한다.
- 일반적인 경우라면 트랜잭션(@Transactional)이 끝나는 시점에 데이터 베이스 커넥션을 반환하고 영속성 컨텍스트도 해제된다.
- 그러나 OSIV 설정이 true인 경우에는 영속성 컨텍스트가 컨트롤러단에서 응답할 때까지 살아있다.
- 그렇기 때문에 view template이나 API 컨틀롤러에서 지연 로딩으로 프록시 객체 초기화가 가능했던 것이다.
- 장점
- 개발 입장에서 중복을 줄이고 유연하게 개발 가능하며 유지보수가 좋다.
- 단점
- 오랜시간 데이터베이스 커넥션 리소스를 사용하기 때문에 실시간 트래픽이 중요한 애플리케이션에서는 커넥션이 마를 수 있고 장애로 이어질 수 있다.
- 예를 들어 컨트롤러에서 외부 API를 호출하면 외부 API 대기시간만큼 커넥션 리소스를 반환하지 못하고 유지해야 한다.
- 이 과정에서 블록킹이라도 걸리면 커넥션 리소스를 계속 차지하고 있게 된다.
OSIV가 false 경우
-
트랜잭션이 종료될 때 영속성 컨텍스를 닫고 데이터베이스 커넥션도 반환한다.
-
장점
- 데이터베이스 커넥션 리소스를 낭비하지 않으며 성능이 좋다.
-
단점
-
모든 지연로딩을 트랜잭션 안에서 처리해야한다. 즉, view template에서 지연로딩이 동작하지 않으며 트랜잭션이 끝나기 전에 지연로딩을 강제 호출해야한다.
-
해결방법은 일반적으로는 서비스 클래스의 트랜잭션(@Transactional) 내에서 모든 지연로딩을 호출하거나, 추가적으로는 fetch join으로 초기에 모든 데이터를 불러와 해결할 수 있다.
// 예시 OrderService : 핵심 비즈니스 로직 OrderQueryService : 화면이나 API에 맞춘 서비스 (주로 읽기전용 트랜잭션 사용)
-
정리
- 보통 서비스 계층에서 트랜잭션을 유지한다. 두 서비스 모두 트랜잭션을 유지하면서 지연 로딩을 사용할 수 있다.
- OSIV를 true로 설정
- 커넥션 리소스를 잡아먹어 성능에 좋지 않지만, 영속성 컨텍스트가 살아있어 지연로딩을 활용할 수 있어 편하고 유지보수성에 좋다.
- 트래픽이 많은 경우 커넥션 리소스 고갈로 장애가 발생할 수 있다.
- OSIV를 false로 설정
- 트랜잭션이 종료되는 시점에 커넥션 리소스를 바로 반환하여 성능에 좋다.
- 고객 트래픽이 많은 일반 서버의 경우 OSIV를 false로 설정하고 개발하는 걸 권장한다.
- 그러나 admin 시스템 서버처럼 트래픽이 적은 경우에는 OSIV를 true로 설정하고 편하게 작업해도 무방하다.
- 즉, 트래픽에 맞춰 적당히 선택해서 개발하면 되겠다.
댓글남기기