[JPA] Transactional(readOnley=true) 가 성능 향상이 되는 이유
들어가며
최근에 한 회사에서 주니어 백엔드 면접을 진행했습니다. 여기서 받은 질문이@Transactional(readOnly = true)는 무슨 역할이고 왜 쓰는 거죠??라는 질문을 받았다. 나는 질문의 답변으로 Transactional(readOnly = true)는 읽기 성능 향상을 위해서 사용했다고 단편적인 대답만 하였다. 정확한 개념과 그 원리를 알지 못한다고 스스로 느꼈기 때문에 이를 보완하고자 글을 작성한다.
@Transactional
먼저 Transactional 어노테이션을 조금더 정리해보자 해당 어노테이션은 스프링 프레임 워크가 제공하는 트랜잭션 기능과 99% 기능이 동일하며 JPA에 특화되어있다고 보기는 어렵다.
클래스, 인터페이스, 메소드에 사용할 수 있으며, 메서드에 가장 가까운 어노테이션이 우선순위를 가진다. Transactional 기본 옵션은 readOnly=true이며 @Transactional 설정을 하지 않은 메서드에 적용이 된다.
이 방식을 우리는 선언적 트랜잭션이라 부르며, 적용된 범위에서는 트랜잭션 기능이 포함된 프록시 객체가 생성되어 자동으로 commit 혹은 rollback을 진행해준다.
이 프락시 객체는 @Transactional 이 포함된 메서드가 호출될 겨우 PlatformTransactionManager를 사용하여 트랜잭션을 시작하고, 정상 여부에 따라 Commit 또는 Rollback 한다.
readOnly 옵션
- @Transactional의 readOnly 옵션은 해당 트랜잭션을 읽기 전용으로 설정한다.
- 해당 옵션은 성능 최적화를 위해서 사용할 수도 있고, 특정 트랜잭션 작업 안에서 쓰기 작업이 일어나는 것을 의도적으로 방지하기 위해서 사용할 수도 있다.
- 단, H2 DB와 같은 몇몇 DB에서는 지원이 되지 않는다.
readOnly=true가 성능 향상이 되는 이유
트랜잭션에 readOnly=true 옵션을 주면 하이버네이트의 Session Flush Mode를 FlushMode.MANUAL로 설정한다. MANUAL로 설정이 되면 강제로 플러시를 호출하지 않는 한 플러시가 일어나지 않게 된다.
따라서 트랜잭션을 커밋하여도 영속성 콘텍스트가 플러시 되지 않아서 엔티티의 등록, 수정, 삭제가 동작하지 않으며 추가적으로 영속성 콘텍스트는 변경 감지를 위한 스냅숏을 보관하지 않으므로 성능이보다 향상이 된다.