실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화 - 섹션5. API 개발 고급 - 실무 필수 최적화 (OSIV와 성능 최적화)
CS/김영한 스프링 강의

실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화 - 섹션5. API 개발 고급 - 실무 필수 최적화 (OSIV와 성능 최적화)

OSIV는 open session in view의 줄임말인데, 영속성 컨텍스트 즉, db 커넥션이 언제까지 살아있게 할거냐를 결정한다.

기본값은 true이므로, 지금 이게 되어있다고 warn 창이 계속 뜨는것이다.

OSIV가 켜저있으면 @Transactional를 벗어나서도 해당 객체가 컨트롤러 등 밖에서도 달라지거나 지연로딩으로 그때 새로 db에서 불러올 수 있기 때문에 계속 추적하는 것이다. 커넥션을 반환할 때는 글자 그대로 진짜 사용자에게 view까지 전부 다 보여지고 모든것이 끝난 다음에 커넥션을 반환하는 것. 문제는 추적하다가 바뀌거나 db에서 로딩을 하게되면 db 커넥션을 들고 있어야 바꾸거나 조회하거나 할 수 있기 때문에 @Transactional를 벗어나서도 db 커넥션을 계속 들고 있다. 즉, 작성자가 의도하지 않는 범위까지 계속 커넥션을 들고있어서 낭비가 된다. 만약 서비스가 끝나도 컨트롤러 안에서 다른 서버에 api 요청해서 막 3초 걸리고 있다고 하면 그때동안 계속 들고있어야 하니 커넥션 풀에서 커넥션들 다 마르고 할거다..

이를 방지하라고 warn이 뜨는 것.

실제 코드를 보면 무슨 말을 하는지 좀 감이 온다.

 

위 코드를 보면 컨트롤러 안에 서비스안의 @Transactional이 되어있는 함수를 사용하는데 만약 OSIV가 켜질 경우 저 컨트롤러가 다 끝나고 뷰까지도 전달이 다 끝나고 모든게 끝나야 그때 반환하지만, OSIV가 꺼져있을 경우 @Transactional이 있는 저 서비스 함수가 끝나면 바로 반환한다. 그래서 이 사이클을 지정하여 커넥션 관리를 더 유동적으로 할 수 있다는 것.

즉 OSIV를 끈 상태라면 @Transactional 안에서 모든 수정작업을 거치고 모든 지연 조회를 fetch를 통해서든 다 가져와야 한다.

 

 

 

서비스 밖에서도 조회를 요청하고 있다. 그래서 OSIV가 켜져있으면 되지만 끄면 밖에서도 불러온다고 에러가 뜬다.

 

 

 

 

추천하는 작성방법은 이런 비즈니스 로직적으로 필요하다기 보단 화면으로 뿌려주는 데에 집중하는 쿼리서비스를 따로 만들고 여기에서 @Transactional를 작성한다.