
저번 글에서 짧게 이야기 했던 부분을 다시 이야기 해보기 위해서 먼저 코드를 보여주고, 궁금한 점을 이야기 해보겠다.
UpdateMentoInfoHandler.class
@Component
@RequiredArgsConstructor
public class UpdateMentoInfoHandler {
private final MentoService mentoService;
public void execute(MentoInfoUpdateRequestDTO mentoInfoUpdateRequestDTO, Long Id) throws IOException {
mentoService.updateMentoInfo(mentoInfoUpdateRequestDTO, mentoService.findMento(Id));
}
}
MentoService.class
@Transactional
public void updateMentoInfo(MentoInfoUpdateRequestDTO updateRequest, Mento mento) {
if (updateRequest.getIntroduction() != null) {
mento.updateIntroduction(updateRequest.getIntroduction());
}
if (updateRequest.getCompany() != null) {
mento.updateCompany(updateRequest.getCompany());
}
if (updateRequest.getMajor() != null) {
Major.getMajor(updateRequest.getMajor().toString());
mento.updateMajor(updateRequest.getMajor());
}
}
저번 글에서 가지고 있던 궁금증이 해결되어서 즐거운 마음으로 있었으나, 또 다른 궁금증이 생겨서 부모 트랜잭션에 있는 @Transactional 어노테이션을 제거 해보았다.
나는 부모 트랜잭션을 제거하면, 같은 영속성 컨텍스트를 더 이상 공유하지 않기에 부모 메서드에서 영속성 컨텍스트에 저장했던 Mento 엔티티가 더 이상 Dirty Checking이 되지 않을 것이라고 생각했다…
그러나 여전히 Mento 엔티티가 Dirty Checking이 되는 것을 확인 할 수 있었다.
도대체 왜 Mento 엔티티가 Dirty Checking이 되는걸까?
답은 바로 OSIV였다.
그러면 OSIV가 뭐길래 이런 결과가 나왔는지 알아보자.
내가 카카오 테크 캠퍼스에서 강사님께 배웠던 OSIV의 개념이란 다음과 같다.
일반적으로 @Transactional이 붙은 레이어(서비스)에서 트랜잭션이 시작되고, 서비스가 종료될 때, 트랜잭션이 종료되며, 이것은 open in view를 false로 설정한 것과 동일하다.
"Open in View"를 사용하는 경우도 마찬가지로 트랜잭션의 시작은 서비스이고, 트랜잭션의 종료도 서비스가 종료될 때 종료된다.
하지만 DB에 select할 수 있는 세션이 view에 렌더링될 때까지 유지된다. 이 기능을 켜두고, 엔티티를 컨트롤러에서 응답하는 순간 Lazy Loading으로 인해 예상치 못한 결과가 발생할 수 있다.
그러면 OSIV 옵션을 켜고, 끌 때 각각의 특징에 대해서 살펴보자.
OSIV = true

OSIV = true → Select(DB 커넥션, 세션)가 처음부터(Controller부터) 가능하고, 데이터 수정, 추가, 삭제등은 Service부터 가능하다.OSIV = true의 장점
OSIV = false

"Open in View"를 사용하는 경우 주의해야 할 점은 장기간 트랜잭션 유지로 인해 데이터베이스 리소스가 오랜 시간 동안 점유될 수 있으며, 불필요한 쿼리나 성능 문제가 발생할 수 있다. 따라서 "Open in View"를 사용할 때는 성능 측면과 리소스 관리에 유의하여 적절한 사용 방식을 선택해야한다
Spring boot는 OSIV가 기본적으로 true로 켜져있고, 해당 OSIV를 false로 지정하면 더 이상 더티 체킹이 되지 않는 것을 확인할 수 있었다.
감사합니다. 이런 정보를 나눠주셔서 좋아요.