[스프링과 JPA활용 2편] 실무 필수 최적화(OSIV)

sonnng·2023년 11월 5일
0

Spring

목록 보기
30/41
post-thumbnail

OSIV와 성능 최적화

(1) OSIV(default : true)

일반적으로 스프링 어플리케이션을 동작시키면 로그 중에 이런 warn으로 나오는 open-in-view와 관련된 경고메세지가 뜬다.

WARN 17736 --- [ restartedMain] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning

서비스 계층에서 트랜잭션이 시작하고 메서드 하나가 끝날 때까지 open-in-view가 true를 유지한다.

  • open-session-in-view는 api가 유저에게 반환될 때까지 끝까지 유지하는 특징이 있다.

유저의 요청이 들어와서 유저에게 완전히 response가 나갈때 까지이다. 영속성 컨텍스트와 DB 커넥션이 끝까지 살아있는다. 그래서 지금까지 View Template이나 API 컨트롤러에서 지연로딩이 가능했던 것이다. (큰 장점)

다만, 너무 오랫동안 데이터베이스 커넥션 리소스를 사용하므로 장애로 이어질 수 있다는 단점이 있다.

(2) OSIV (OFF설정일 때)

유저의 요청을 받아서 트랜잭션이 시작하고 끝날 때 영속성 컨텍스트도 닫고 데이터베이스 커넥션도 반환한다. 따라서 커넥션 리소스를 낭비하지 않는다.

😱 치명적인 단점

지연로딩을 하려면 데이터베이스 커넥션, 영속성 컨텍스트가 살아있어야 한다. 트랜잭션이 끝나는 순간 모두 끝나기 때문에, 트랜잭션이 끝나기 전에 지연로딩을 강제로 호출해야만 한다.

 	@GetMapping("/api/v1/orders")
    public List<Order> orderV1(){
        List<Order> all = orderRepository.findAllByString(new OrderSearch());
        //객체 그래프 초기화
        for (Order order : all) {
            order.getMember().getName();
            order.getDelivery().getAddress();

            //리스트 강제 초기화
            List<OrderItem> orderItems = order.getOrderItems();
            for (OrderItem orderItem : orderItems) {
                orderItem.getItem().getName();
            }
        }
        //엔티티가 직접 노출되는 문제가 있다. -> DTO로 바꿔서 응답해보자(v2)
        return all;
    }

getName()이 호출되는 순간, 프록시객체로 초기화해야 한다. 하지만 영속성 컨텍스트는 서비스 계층에서 트랜잭션이 시작하고 끝나는 순간 닫기 때문에 불가능하다.

🫸그러면 어떻게 해야 하냐?
트랜잭션이 끝나기 전에 지연로딩을 강제로 호출을 해두거나, 패치조인을 통해야만 한다.

고객 서비스의 실시간 api는 OSIV를 끄고, ADMIN처럼 커넥션을 많이 사용하지 않는 곳에서는 OSIV를 켠다.

0개의 댓글