본문 바로가기

강의 내용 정리/스프링부트와 JPA 활용 2

5-1. OSIV와 성능 최적화

JPA에서 EntityManager가 하이버네이트에서는 Session이다. (예전엔 하버네이트만 있었다.)

 

진짜 중요한 내용

영속성컨텍스트는 동작을 하려면 DB커넥션을 내부적으로 사용을 해야 lazy로딩을하든 뭘 하든 할 수 있다. 그래서 영속성컨텍스트와 DB커넥션은 굉장히 밀접하게 매칭이 되어있다. 영속성 컨텍스트는 DB커넥션을 1:1로 쓰면서 동작해야함.

 

언제 JPA가 DB커넥션을 획득을 하냐 -> 기본적으로 DB트랜젝션 시작할 때 JPA의 영속성컨텍스트가 DB커넥션을가져옴.

-> DB커넥션 언제 돌려줘야 할까 (이 시점이 중요) -> 

 

 

서비스레이어에서 트랜젝션 시작할 때 DB커넥션 가져온다. osiv가 꺼져있다면 트랜젝션붙은 메서드가 끝날 때 트랜젝션이 닫히면서 영속성컨텍스트 또한 닫히게 된다. 만약 osiv 켜져있으면 @Transactional 끝나고 컨트롤러 밖으로 나가도 DB커넥션을 반환을 안함. -> 왜 안하냐? -> controller에서 lazy로딩으로 가져오기위해.

 

여기서도 80줄에서 order를 가져오고 82줄에서 

여기의 .getMember().getName() 나 .getDelivery().getAdress() 할 때 member, delivery가 LAZY 로딩 일어나서 프록시객체를 실제 객체로 채워야(초기화) 하기 때문에 영속성 컨텍스트가 DB커넥션을 물고 살아있어야함. -> OSIV : 트랜잭션이 끝나도 영속성 컨텍스트를 API응답이 될 때까지 , view라면 viewTemplate 가지고 렌더링할 때까지.

: 모두 응답하여 더이상 필요없는 단계까지 DB커넥션을 물고 있는다. (영속성 컨텍스트와 DB커넥션은 한 세트로 기억하자.)

 

 

--> 하지만 이 전략의 최대 단점. -> 너무 오래동안 DB커넥션을 물고 있는다. -> 실시간 트래픽이 중요한 애플리케이션의 경우 커넥션이 모자랄 수 있다. (= 커넥션이 말라버린다.) -> 결국 장애.

장점 : 컨트롤러나 뷰에서 지연로딩 할 수 있다.

 

 

 

 

#OSIV 껐을 때

이러면 트랜잭션 끝날 때 DB커넥션도 끊는다. -> 이후 컨트롤러에서 죽어도 못쓴다.

지연로딩을 하려면 당연하게도 영속성컨텍스트가 살아있어야함.

 

spring.jpa.open-in-view

OSIV 껐을 때 트랜젝션 밖에서 지연로딩하면

LazyInitializationException 터진다. cound not initial proxy

 

 

이 때 방법(중요하므로 하나하나 생각)

1. OSIV를 킨다.

2. 트랜잭션 내부에서 지연로딩을 다 시켜놓는다.

3. fetch join 으로 애초에 한번의 쿼리로 지연로딩할 객체를 다 가져온다.

4. 따로 Service를 만들어서 Controller의 변환코드들을 들고간다. 

위의 컨트롤러의 로직을 트랜잭션을 연 service로 데려와서 컨트롤러에 반환한다.

핵심 비지니스로직이 있는 service와 분리하자.

-> 이건 영한님이 선호하는 방법.

-> 이게 커맨드와 쿼리를 분리하는 방법이다.

 

 

 

결론 : 고객서비스기반의 트래픽이 많은 실시간 API를 많이 제공해야하는 API 서버의 경우 OSIV를 꺼논다.

이럴 경우 안끄면 커넥션풀 다 말라버린다. , ADMIN 처럼 커넥션을 많이 사용하지 않는 곳에서는 OSIV를 켠다.

(보통 ADMIN서버, API서버를 배포를 따로 하므로)

 

Recent Posts
Popular Posts
Recent Comments