OSIV와 성능 최적화


Open Session In View: 하이버네이트
Open EntityManager In View: JPA

OSIV ON

컨텍스트와 데이터베이스 연결을 유지하는 것은 지연 로딩이 가능하게 해주는 요인이며, 이는 주로 View Template이나 API 컨트롤러에서 활용됩니다. 이러한 방식은 영속성 컨텍스트의 유지를 필요로 하는데, 이는 기본적으로 데이터베이스 연결을 계속해서 유지하게 됩니다. 이는 많은 이점을 가지고 있지만, 몇 가지 주의할 점들이 있습니다.

장시간 동안 데이터베이스 연결 리소스를 점유하는 이 전략은 실시간 트래픽이 많은 애플리케이션에서는 문제를 일으킬 수 있습니다. 바꿔 말하면, 이 방식은 연결이 부족하게 되어 결국에는 시스템 장애를 초래할 수 있습니다.

이를 명확하게 이해하기 위한 예로, 컨트롤러가 외부 API를 호출하는 경우를 생각해보겠습니다. 외부 API의 응답을 기다리는 동안, 해당 데이터베이스 연결 리소스는 반환되지 않고 유지 상태를 유지해야 합니다. 이렇게 되면 필요 이상으로 데이터베이스 연결을 점유하게 되어, 다른 요청들이 이 리소스를 활용하지 못하는 문제가 발생할 수 있습니다.

OSIV OFF

Spring의 spring.jpa.open-in-view: false 설정을 통해 Open Session in View(OSIV)를 비활성화할 수 있습니다. OSIV를 비활성화하면 트랜잭션을 종료할 때 영속성 컨텍스트를 닫고, 데이터베이스 연결을 반환하게 됩니다. 이렇게 함으로써 데이터베이스 연결 리소스를 효율적으로 관리하고 낭비를 줄일 수 있습니다.

그러나 OSIV를 비활성화하는 것은 몇 가지 단점이 있습니다. 첫째, 모든 지연 로딩은 트랜잭션 내에서 처리되어야 합니다. 이는 기존에 작성한 많은 지연 로딩 코드를 트랜잭션 내부로 이동시켜야 하는 작업을 필요로 합니다. 둘째, View Template에서는 지연 로딩이 작동하지 않게 됩니다.

결과적으로, 트랜잭션이 종료되기 전에 지연 로딩을 강제적으로 호출해야 하는 상황을 만들어낼 수 있습니다. 이는 애플리케이션의 전반적인 설계와 성능 최적화를 재검토할 필요가 있다는 신호로 받아들여져야 합니다.

커멘드와 쿼리 분리

실제 업무에서 Open Session in View(OSIV)를 비활성화한 상태에서 복잡성을 효과적으로 관리하는 좋은 전략 중 하나는 Command와 Query를 분리하는 것입니다. 이 원칙은 Command–Query Separation (CQS)라고 알려져 있습니다. (자세한 정보는 위키백과의 해당 항목을 참조하세요: https://en.wikipedia.org/wiki/Command–query_separation)

일반적으로 비즈니스 로직은 특정 엔티티의 생성 또는 수정 등과 같이 한정된 작업을 수행하기 때문에 성능 문제가 크게 나타나지 않습니다. 그러나 복잡한 화면을 구성하는 쿼리의 경우, 화면에 맞게 성능을 최적화하는 것이 중요하며, 이 과정은 종종 복잡해질 수 있습니다. 그러나 이러한 복잡성은 핵심 비즈니스 로직에 크게 영향을 주지 않습니다.

따라서 대규모이고 복잡한 애플리케이션을 개발하는 경우, 이 두 관심사인 Command와 Query를 명확하게 분리하는 것이 유지보수 관점에서 매우 유용합니다.

일반적으로 서비스 계층에서 트랜잭션을 유지하며, 이 서비스에서도 지연 로딩을 사용할 수 있습니다. 참고로, 제 개인적인 경험에 따르면, 고객 서비스와 같은 실시간 API에서는 OSIV를 비활성화하고, ADMIN과 같이 데이터베이스 연결을 많이 사용하지 않는 부분에서는 OSIV를 활성화하는 편입니다.

소스코드

참조