Spring

[Spring JPA] JPA에서 OSIV와 커맨드,쿼리의 분리

윤진노 2024. 7. 18. 16:13

 

 

이번 포스팅에서는 OSIV란 무엇인지 알아보고, 장단점을 이용한 성능에 도움을 줄 방법을 정리해 봐야곘다.

 

 

 


 

 

 

OSIV란?

OSIV(Open Session In View)란 말그대로 세션 뷰까지 열어두는 기능이다. 여기서 세션은 하이버네이트에서의 세션 즉, 영속성 컨텍스트를 의미한다. 이렇게 되면 엔티티를 영속성 컨텍스트에서 사용 가능하고, 우리가 앞서 봤던 것처럼 지연 로딩을 사용할 수 있게 된다. JPA에서는 OEIV(Open EntityManager In View) 라 부르고, 하이버네이트에서는 OSIV라고 부르는데, 그냥 OSIV라고 부르면 된다.

 

 

 

 

OSIV가 활성화 됐을 때의 그림을 보자.

원래 영속성 컨텍스트의 생존 범위는 트랜잭션 내이다. 하지만 우리가 OSIV을 활성화 시킨다면, 영속성 컨텍스트는 뷰에 응답이 갈 때까지 생존한다. 기본이 true로 설정되어 있기 때문에 우리가 따로 설정을 하지 않는다면, 지연로딩을 사용하더라도 에러가 나타나지 않는다.

 

OSIV 전략은 트랜잭션 시작처럼 최초 데이터베이스 커넥션 시작 시점부터 API 응답이 끝날 때 까지 영속성 컨텍스트 와 데이터베이스 커넥션을 유지한다. 그래서 지금까지 영속성 컨텍스트의 생존범위를 분명 벗어났음에도 불구하고 View Template이나 API 컨트롤러에서 지연 로딩이 가능했던 것이다.

 

 

< OSIV 활성화시 영속성 컨텍스트 처리 과정>

  • 클라이언트의 요청이 들어오면 서블릿 필터나, 스프링 인터셉터에서 영속성 컨텍스트를 생성한다. 단 이 시점에서 트랜잭션은 시작하지 않는다.
  • 서비스 계층에서 트랜잭션을 시작할 때 미리 생성해둔 영속성 컨텍스트를 찾아와서 트랜잭션을 시작한다.
  • 서비스 계층이 끝나면 트랜잭션을 커밋하고 영속성 컨텍스트를 플러시한다. 이 시점에 트랜잭션은 끝내지만 영속성 컨텍스트는 종료되지 않는다.
  • 컨트롤러와 뷰까지 영속성 컨텍스트가 유지되므로 조회한 엔티티는 영속 상태를 유지한다.
  • 서블릿 필터나, 스프링 인터셉터로 요청이 돌아오면 영속성 컨텍스트를 종료한다. 이때 플러시를 호출하지 않고 바로 종료한다. 즉, 트랜잭션 이후에 건드는 영속성 컨텍스트는 반영이 안된다는 것이다.

 

하지만, 이 전략은 너무 오랜시간동안 데이터베이스 커넥션 리소스를 사용하기 때문에, 실시간 트래픽이 중요한 애플리 케이션에서는 커넥션이 모자랄 수 있다. 만약 컨트롤러에서 외부 API를 호출하면 외부 API 대기 시간 만큼 커넥션 리소스를 반환하지 못하고, 유지해야 한다.

 

 

 

 

 

OSIV를 끄면 트랜잭션을 종료할 때 영속성 컨텍스트를 닫고, 데이터베이스 커넥션도 반환한다. 따라서 커넥션 리소스 를 낭비하지 않는다. 이렇게 되면 문제점을 해결하긴 하지만, 앞선 OSIV가 가져가는 영속성 컨텍스트를 뷰까지 가져가는 장점을 택하지 못하게 될것이다.

 

OSIV를 끄면 모든 지연로딩을 트랜잭션 안에서 처리해야 한다. 따라서 지금까지 작성한 많은 지연 로딩 코드를 트랜잭 션 안으로 넣어야 하는 단점이 있다. 그리고 view template에서 지연로딩이 동작하지 않는다. 결론적으로 트랜잭션이 끝나기 전에 지연 로딩을 강제로 호출해 두어야 한다. 

 

 

OSIV를 사람들이 동시 접속할 가능성이 많은 실시간 API는 OSIV를 끄고, 관리자API 같은 경우에는 OSIV를 켜두는 것도 좋은 전략이다.

 

 

 

 

 

 

커맨드와 쿼리의 분리

OSIV를 끈 채로 복잡성을 관리할 수 있는 방법으로 커맨드와 쿼리를 분리하는 방법이 있다.

 

https://en.wikipedia.org/wiki/Command

 

 

Command - Wikipedia

From Wikipedia, the free encyclopedia Look up command in Wiktionary, the free dictionary. Command may refer to: Computing[edit] Military[edit] Other uses[edit] See also[edit] Topics referred to by the same term <!-- NewPP limit report Parsed by mw‐web.eq

en.wikipedia.org

 

 

 

말 그대로 비즈니스 로직과 쿼리를 사용하는 로직을 분리한다. 대부분의 쿼리는 조회에서 사용될 것이다.

예를 들어,

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

 

이렇게 나누면 보통 서비스 계층에서 트랜잭션을 유지하므로, 두 서비스 모두 트랜잭션을 유지하며 지연로딩을 사용할 수 있다.