[SpringBoot-JPA 활용편1] 자바 ORM 표준 JPA 프로그래밍 - 활용편2: 5. API 개발 고급 - 실무 필수 최적화
실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화 강의 - 인프런
스프링 부트와 JPA를 활용해서 API를 개발합니다. 그리고 JPA 극한의 성능 최적화 방법을 학습할 수 있습니다., 스프링 부트, 실무에서 잘 쓰고 싶다면? 복잡한 문제까지 해결하는 힘을 길러보세요
www.inflearn.com
해당 강의는 Inflearn에 등록된 김영한님의 Spring Boot 강의입니다.
이번 시간에는 OSIV와 성능 최적화에 대해 공부하자.
1. OSIV와 성능 최적화
Open Session In View: 하이버네이트
Open EntityManager In View: JPA
스프링 부트 실행 시 경고문(warn)을 지금까지 하면서 계속 봤을 것이다. 이는 OSIV와 관련이 있다.
OSIV(Open Session In View)는 하이버네이트나 JPA 같은 ORM(Object-Relational Mapping) 프레임워크에서 사용되는 패턴 중 하나이다. 이 패턴은 데이터베이스 세션(또는 엔티티 매니저)을 HTTP 요청의 시작부터 끝까지 열어 두는 것을 의미한다.
즉, 사용자의 요청이 시작될 때 세션이 열리고, 요청이 완전히 처리되어 응답이 반환될 때까지 세션이 유지된다.
OSIV ON 도식화
그러면 트랜잭션은 시작은 어디일까? 예를 들어보겠다.
위 이미지는 회원 등록의 한 예이다. 이렇게 회원 등록시 트랜잭션이 시작되는데 회원 id를 반환하면서 트랜잭션이 종료된다. 이렇게 트랜잭션 내에서는 영속상태(em.persist()했으면)라고도 하고, 데이터가 변경되는 곳이다.
다음은 OSIV를 True로 설정해서 warn이 생기는 이유이다.
위의 설명과 같이 db를 api 응답이 끝날때까지 커넥션을 유지하면 많은 시간고 자원이 소모되고, 실시간 트래픽 처리 api 같은 경우에는 성능 측면에서 매우 안좋다.
이를 위해 api 응답시점까지 db를 커넥션을 유지 하지 말고, 트랜잭션이 끝나는 순간 커넥션, 즉 영속상태를 끝냄으로써 성능을 올린다.
OSIV OFF 도식화
application.yml
커멘드와 쿼리 분리
OrderApiController
private final OrderQueryService orderQueryService;
@GetMapping("/api/v7/orders")
public List<jpabook.jpashop.service.query.OrderDto> ordersV7()
{
return orderQueryService.ordersV7();
}
OrderQueryService
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
//트랜잭션 안에서 실행
public class OrderQueryService {
private final OrderRepository orderRepository;
public List<OrderDto> ordersV7() {
List<Order> orders = orderRepository.finAllWithItem(); //fetch join
List<OrderDto> collect = orders.stream()
.map(o -> new OrderDto(o))
.collect(toList());
return collect;
}
}
위 예제를 위해 패키지를 하나만들고 DTO도 해당 패키지 내부에 옮겼다.
트랜잭션 내에서 실행예시
이와 같이 실시간으로 사용되는 api 서비스는 osiv를 off한채로 서비스 계층에서 트랜잭션을 유지한다. 두 서비스 모두 트랜잭션을 유지하면서 지연 로딩을 사용할 수 있다.
API 특성 별 서버별 OSIV를 ON,OFF해서 최대한 성능을 최적화 할 수 있다. 다음은 사용예시이다.
Admin 서버: on
트래픽 많은 서버:off
OSIV의 장단점
장점:
- 지연 로딩 활성화: 요청 처리의 어느 시점에서든지 필요한 연관 객체를 로드할 수 있다.
단점:
- 리소스 사용 증가: HTTP 요청이 처리되는 전체 시간 동안 데이터베이스 세션이 열려 있어야 하므로, 리소스 사용이 증가할 수 있다.
- 트랜잭션 범위의 모호함: 비즈니스 로직에서의 명확한 트랜잭션 범위가 모호해질 수 있습니다. 이는 데이터 일관성 문제를 야기할 수 있다.
- 성능 저하: 데이터베이스 커넥션이 요청의 전체 수명 주기 동안 유지되므로, 고성능이 요구되는 애플리케이션에서는 성능 저하를 초래할 수 있다.