Provider
에는 READ
, DML로 치면 SELECT
를 사용한 쿼리문을 가진 함수를 DAO에서 많이 불러온다. 그러니까 단순 조회
이므로 트랜잭션을 처리할 때 @Transactional(readOnly = true)
라는 어노테이션을 붙여 처리했다.
API를 제작하고 테스트하는 과정에서, 몇몇 Provider에 깜빡 잊고 @Transactional(readOnly = true)
를 지정하지 않았다. 뒤늦게 다른 오류를 수정할 때 이러한 상황을 알게되었다.
테스트 당시에는 해당 어노테이션과 옵션이 없어도 딱히 구분이 가지 않았기 때문에 굳이 이런 어노테이션이 왜 존재하는지 궁금했다. 따라서 해당 옵션의 필요성에 대해 정리해보려고 한다.
readOnly = true의 역할
- 스프링 프레임워크에서 어노테이션에서 트랜잭션을 읽기 전용 모드로 설정할 수 있는 어노테이션이다.
: 읽기 전용 모드이므로 예상치 못한 엔티티의 등록, 변경, 삭제를 예방
할 수 있고, 성능을 최적화
할 수 있다.
읽기 전용 쿼리의 성능 최적화
엔티티가 영속성 컨텍스트에 관리되면 1차 캐시부터 변경 감지까지 얻을 수 있는 혜택이 많다. 하지만 영속성 컨텍스트는 변경을 감지하기 위해서 스냅샷 인스턴스를 보관하므로 더 많은 메모리를 사용하는 단점이 존재한다.
- readOnly = true인 상태이면 영속성 컨텍스트의 관리를 받지 않아 스냅샷 저장/변경감지 등을 수행하지 않아 성능적으로 더 낫다.
- readOnly = true일 때는 master가 아닌 reader DB로 호출되는 장점이 있다. 따라서 서버의 부하를 줄일 수 있다.
- MySQL의 경우 해당 트랜잭션을 이용할 경우 SELECT 문에 대해서만 기능을 지원하며, Transaction ID 설정에 대한 오버헤드 해결 가능 : read only 트랜잭션에 대해서는 ID가 부여되지 않는다.
: 즉, 트랜잭션 ID 설정에 대한 오버헤드를 해결하고, 스냅샷을 통해 데이터 일관성을 보장
한다.
[참고] 영속성 컨텍스트
- 엔티티를 영구 저장하는 환경
- EntityManager를 통해서 영속성 컨텍스트에 접근한다.
- EntityManager가 생성되면 논리적 개념인 영속성 컨텍스트가 1:1 생성 된다.
📚 Reference
- [JPA] 영속성 컨텍스트란?
- 03. 당신의 @Transactional의 readOnly 옵션 잘 쓰고 있나요?
- @Transactional(readOnly = true)는 필요한가?