본문 바로가기

cs(with 매일메일)

[260325수] OSIV(Open Session In View) 옵션에 대해서 설명해주세요

영속성 컨텍스트를 뷰까지 열어둔다는 의미이다. 

영속성 컨텐스트가 살아있으면 엔티티는 계속 영속 상태를 유지할 수 있어서 뷰에서도 지연 로딩을 사용할 수 있다. 

 

OSIV ON vs OFF 비교

  OSIV ON (기본값 true) OSIV OFF
Session 범위 요청 전체 트랜잭션 범위만
Lazy 로딩 위치 Controller, View 어디서든 가능 Service 안에서만 가능
장점 편리함 DB 커넥션 반환이 빠름
단점 DB 커넥션을 오래 붙잡음 Lazy 로딩 위치 제한

Session이 빨리 닫히면 DB 커넥션 풀에 커넥션이 빨리 반환되는 건 좋음.

근데 Controller에서 Lazy 로딩을 쓰던 코드가 전부 예외를 터뜨림

그래서 OSIV OFF 시에는 Service 계층에서 미리 다 로딩해서 DTO로 변환해서 반환하는 패턴을 써야 한다.

 

구현 방법

1. 가장 단순한 구현은 클라이언트 요청이 들어올 때 필터나 인터셉터에서 트랜잭션을 시작하는 방법이다.  

> 치명적인 문제는 표현 계층에서도 엔티티를 수정할 수 있기 때문에 유지보수에 어려운 코드가 된다. 

 

2. 스프링 OSIV

  1) 클라이언트의 요청이 들어오면 서블릿 필터나 스프링 인터셉터에서 영속성 컨텍스트 생성

  2) 응용 계층에서 @Transactional로 트랜잭션을 시작할 때 미리 생성한 영속성 컨텍스트를 찾아와 트랜잭션 시작

  3) 응용 계층이 끝나면 트랜잭션을 커밋하고 영속성 컨텍스트를 플러시(종료 X)

  4) 컨트롤러와 뷰까지 영속성 컨텍스트가 유지되므로 조회한 엔티티는 영속 상태를 유지할 수 있음

  5) 필터, 인터셉터로 요청이 돌아오면 영속성 컨텍스트를 종료하는데 이때 플러시는 수행하지 않음. 

 

스프링 OSIV의 문제점은? 

- 상대적으로 오래 커넥션을 유지하기 때문에 커넥션 고갈 문제로 이어질 수 있음

- 표현 계층에서 엔티티를 수정하면 데이터베이스에 반영하지 않음. 이후 트랜잭션을 시작하는 응용 계층을 시작한 경우 문제 발생할 수 있음. 응용 계층 트랜잭션이 끝나고 영속성 컨텍스트를 플러시하는 과정에서 변경 감기가 동작할 수 있음

 

실무에서는?

Spring Boot 기본값은 OSIV ON인데, 트래픽이 많은 서비스에선 끄는 게 권장