barded

[어디가게]Spring Security단에서 OPEN-SESSION-IN-VIEW 영속성 컨텍스트 본문

프로젝트/어디가게

[어디가게]Spring Security단에서 OPEN-SESSION-IN-VIEW 영속성 컨텍스트

barded 2024. 3. 18. 04:18

Spring Security의 Security Context에 고객의 정보를 넣고 인증 시 이를 사용하는 방식을 사용했다.

loadUserByUsername 메서드를 통해 DB에서 User를 조회해 온 뒤 UserDetails을 implements한 UserAdapter에 user 객체를 넣어주기 때문에 영속성 컨텍스트에 당연히 user객체가 있을줄 알았다.

하지만 OSIV가 OFF인 상태이다. 그래서 User 객체의 영속성 컨텍스트 생존 범위가 Service단에서만 살아있다.

OSIV (Open Session In View)란?

OSIV(Open Session In View)는 영속성 컨텍스트를 뷰까지 열어두는 기능이다. JPA에서는 OEIV(Open EntityManager In View), Hibernate에서는 OSIV(Open Session In View)라고 하는데, 관례상 둘 다 OSIV라고 부른다. 개발자는 OSIV를 임의로 켜거나 끌 수 있기 때문에 서비스 특성에 맞게 OSIV 전략을 활용할 필요가 있다.

OSIV on

  • 영속성 컨테이너를 뷰까지 열어두게 되면 트랜잭션이 끝나는 컨트롤러 계층에서도 지연 로딩(Lazy Loading)이 가능하기 때문에 이를 위해 사용한다.
  • 뷰 템플릿이나 API컨트롤러에서 지연 로딩을 해서 데이터를 불러오는 작업을 했던 것도, 바로 OSIV를 켰기 때문에 가능한 것이다

동작 원리는 다음과 같다.

  • 클라이언트의 요청이 들어오면 서블릿 필터나, 스프링 인터셉터에서 영속성 컨텍스트를 생성한다. 이 시점에서는 트랜잭션이 시작되지 않는다.
  • 서비스 계층에서 @Transactional로 트랜잭션을 시작하게 되면 1번에서 미리 생성해둔 영속성 컨텍스트를 찾아온다.
  • 서비스 계층이 끝나면 트랜잭션을 커밋하고 영속성 컨텍스트를 flush한다.
  • 컨트롤러와 뷰까지 영속성 컨텍스트가 유지되므로 조회한 엔티티는 영속 상태를 유지한다.
  • 서블릿 필터나, 스프링 인터셉터로 요청이 들어오면 영속성 컨텍스트를 종료한다. 이 때, flush를 하지 않고 바로 종료한다.

OSIV ON 전략은 오랜시간 동안 데이터베이스 커넥션 리소스를 사용하기 때문에, 실시간 트래픽이 중요한 애플리케이션에는 커넥션이 모잘랄 수 있다는 단점이 있다. ex) 컨트롤러에서 외부 API를 호출하게 되면 외부 API 대기 시간만큼 데이터베이스 리소스를 반환하지 못한다.

OSIV OFF

  • 위 그림을 보면, OSIV를 켰을 때와 달리 영속성 컨텍스트의 생존 범위가 트랜잭션 범위와 같아지는 것을 볼 수 있다. 즉, 트랜잭션을 종료할 때 영속성 컨텍스트를 닫고, 데이터베이스 커넥션도 반환된다.
  • 따라서 우리가 컨트롤러 계층에서 사용했던 모든 지연 로딩을 트랜잭션 안에서 처리되도록 해야 한다는 단점이 있다.(이를 위해 API개발을 위한 Service계층을 따로 만들어서 구현할 수 있을 것이다.)

따라서 OSIV를 켜야할까? 꺼야할까?

OSIV를 키면 데이터베이스 커넥션 이슈가 있긴 하지만 쿼리를 한번더 날릴 필요가 없으므로 편리하다.

하지만 단점으로 데이터베이스 커넥션 자원을 낭비하고, 인증 과정에서 무관한 정보를 불러온다는 것이 단점이기 때문에 off로 변경하고 매번 고객의 정보를 바탕으로 정보를 찾아오는 방식을 채택하여 진행하였다.

만약 ADMIN처럼 커넥션을 많이 사용하지 않는 곳에서는 OSIV를 켜서 편리함을 추구하는것도 좋은 방식이라고 할 수 있다.

loadUserByUsername 메서드를 통해 DB에서 User를 조회해 온 뒤 UserDetails을 implements한 UserAdapter에 user 객체를 넣어주기 때문에 영속성 컨텍스트에 당연히 user객체가 있을줄 알았다.

하지만 OSIV가 OFF인 상태이다. 그래서 User 객체의 영속성 컨텍스트 생존 범위가 Service단에서만 살아있다.

OSIV (Open Session In View)란?

OSIV(Open Session In View)는 영속성 컨텍스트를 뷰까지 열어두는 기능이다. JPA에서는 OEIV(Open EntityManager In View), Hibernate에서는 OSIV(Open Session In View)라고 하는데, 관례상 둘 다 OSIV라고 부른다. 개발자는 OSIV를 임의로 켜거나 끌 수 있기 때문에 서비스 특성에 맞게 OSIV 전략을 활용할 필요가 있다.

OSIV on

  • 영속성 컨테이너를 뷰까지 열어두게 되면 트랜잭션이 끝나는 컨트롤러 계층에서도 지연 로딩(Lazy Loading)이 가능하기 때문에 이를 위해 사용한다.
  • 뷰 템플릿이나 API컨트롤러에서 지연 로딩을 해서 데이터를 불러오는 작업을 했던 것도, 바로 OSIV를 켰기 때문에 가능한 것이다

동작 원리는 다음과 같다.

  • 클라이언트의 요청이 들어오면 서블릿 필터나, 스프링 인터셉터에서 영속성 컨텍스트를 생성한다. 이 시점에서는 트랜잭션이 시작되지 않는다.
  • 서비스 계층에서 @Transactional로 트랜잭션을 시작하게 되면 1번에서 미리 생성해둔 영속성 컨텍스트를 찾아온다.
  • 서비스 계층이 끝나면 트랜잭션을 커밋하고 영속성 컨텍스트를 flush한다.
  • 컨트롤러와 뷰까지 영속성 컨텍스트가 유지되므로 조회한 엔티티는 영속 상태를 유지한다.
  • 서블릿 필터나, 스프링 인터셉터로 요청이 들어오면 영속성 컨텍스트를 종료한다. 이 때, flush를 하지 않고 바로 종료한다.

OSIV ON 전략은 오랜시간 동안 데이터베이스 커넥션 리소스를 사용하기 때문에, 실시간 트래픽이 중요한 애플리케이션에는 커넥션이 모잘랄 수 있다는 단점이 있다. ex) 컨트롤러에서 외부 API를 호출하게 되면 외부 API 대기 시간만큼 데이터베이스 리소스를 반환하지 못한다.

OSIV OFF

  • 위 그림을 보면, OSIV를 켰을 때와 달리 영속성 컨텍스트의 생존 범위가 트랜잭션 범위와 같아지는 것을 볼 수 있다. 즉, 트랜잭션을 종료할 때 영속성 컨텍스트를 닫고, 데이터베이스 커넥션도 반환된다.
  • 따라서 우리가 컨트롤러 계층에서 사용했던 모든 지연 로딩을 트랜잭션 안에서 처리되도록 해야 한다는 단점이 있다.(이를 위해 API개발을 위한 Service계층을 따로 만들어서 구현할 수 있을 것이다.)

따라서 OSIV를 켜야할까? 꺼야할까?

OSIV를 키면 데이터베이스 커넥션 이슈가 있긴 하지만 쿼리를 한번더 날릴 필요가 없으므로 편리하다.

하지만 단점으로 데이터베이스 커넥션 자원을 낭비하고, 인증 과정에서 무관한 정보를 불러온다는 것이 단점이기 때문에 off로 변경하고 매번 고객의 정보를 바탕으로 정보를 찾아오는 방식을 채택하여 진행하였다.

만약 ADMIN처럼 커넥션을 많이 사용하지 않는 곳에서는 OSIV를 켜서 편리함을 추구하는것도 좋은 방식이라고 할 수 있다.