티스토리 뷰

spring boot app을 실행하면 다음과 같은 WARN 경고가 뜨게 된다.

  • 2021-07-30 15:41:37.897  WARN 11366 ---[  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가 dafault로 사용가능하게 되어있으므로 view rendering시 db 쿼리가 수행될 것이며, 경고를 없애기 위해서는 명시적으로 spring.jpa.open-in-view로 설정해주면 경고창을 지울수 있다" 라고 볼수 있겠다.

 

그렇다면 open-in-view가 무엇이며 왜 기본으로 세팅이 되어있고 view 렌더링시에 db쿼리가 수행되는 것일까?


OSIV - 사용시

JPA는 DB에 커넥션을 얻어서 영속성 컨텍스트를 관리하는데 언제 DB에 커넥션을 가져와서 반환이 이뤄질까?

OSIV가 켜져있을 때 영속성 컨텍스트의 생존 범위

  • DB 트랜잭션을 시작할 때 JPA 영속성 컨텍스트가 DB 커넥션을 가져온다.
  • 이후 DB 커넥션을 반환해야 하는데 기본 OSIV 전략에서는 클라이언트의 요청에 대한 API 응답이 완전히 완료될 때까지 영속성 컨텍스트와 DB 커넥션을 유지한다.
    이 덕분에 view template, api Controller에서 지연로딩이 가능한 것이다.
  • 지연 로딩은 영속성 컨텍스트가 살아 있어야 가능하고, 영속성 컨텍스트는 응답을 완료할 때까지 DB 커넥션을 유지하는 것이다.

OSIV의 역활

OSIV 덕분에 영속성 컨텍스트가 DB 커넥션을 API 응답이 끝날때까지 가질수 있게 된다. 이를 이용해서 LAZY 로딩을 할 수 있게 되었다.

이후 api 응답이 완료되면 DB 커넥션도 끊기고 영속성 컨텍스트도 제거된다.

 

OSIV의 단점

OSIV 덕분에 DB커넥션을 오래 들고 있어서 지연로딩도 가능하지만 동일한 이유로 단점이 된다. 너무 오랜 시간 DB 커넥션 리소스를 사용하므로 실시간 트래픽이 중요한 애플리케이션에서는 커넥션이 부족할 수 있다.

 

예를들어 컨트롤에서 외부 API호출이 이뤄지는데 대기시간이 발생한다면 해당 시간동안 DB커넥션도 반환이 이뤄지지 못한채 응답이 완료 될때까지 유지해야 하는것이다. 이러한 장애가 반복적으로 발생하면 전체적인 장애로 이어질수 있다.

 

그렇다면 OSIV를 끄면 DB 커넥션으로 인한 리소스 문제는 해결할 수 있을 텐데 이로인해 어떤 문제가 발생하는지 보자.

 

OSIV - 미 사용시

OSIV가 꺼져있을 때 영속성 컨텍스트의 생존 범위

OSIV가 꺼져있으면 트랙잭션을 시작할 때 DB 커넥션을 얻고 트랙잭션이 끝날 때 영속성 컨텍스트도 끝나고 DB 커넥션도 같이 반환된다.

    @GetMapping("/api/v1/orders")
    public List<Order> ordersV1() {
        List<Order> all = orderRepository.findAllByString(new OrderSearch());
        for (Order order : all) {
            order.getMember().getName(); // LAZY 해제, 즉시로딩
            order.getDelivery().getAddress(); // LAZY 해제, 즉시로딩

            List<OrderItem> orderItems = order.getOrderItems();
            orderItems.forEach(o -> o.getItem().getName()); // LAZY 해제, 즉시로딩
        }
        return all;
    }

주문 목록을 가져오는 위의 코드에서 Order 객체만 DB에서 가져오고 이후에 Order 내 회원과 배달, 상품목록을 지연로딩으로 가져오게 된다. 하지만 OSIV가 꺼져있으면 이 작업이 불가능하게 된다.

따라서 DB커넥션이 살아 있을 때 Service내에서 LAZY 로딩을 하거나 아니면 FETCH JOIN을 해서 가져와야 한다. (컨트롤러에서 지연로딩으로 작업하는 것이 불가능해진다)


결론

DB 커넥션이 많이 발생하는 유저의 트래픽이 많은 서비스라면 OSIV를 꺼서 DB 커넥션을 관리해주고 Controller에서 LAZY 로딩이 불가능하므로 Service내에서 필요한 엔티티를 모두 조회해서 처리하도록 하거나 FETCH JOIN을 사용해야 한다.

 

그렇지 않다면 OSIV를 켜서 사용하는것이 더 구조상에서나 코드상으로 편하므로 켜서 사용하면 된다.

반응형
Comments
반응형
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday