@Transactional(readOnly = true)
보통 조회용 메소드에 걸어주게 되는 어노테이션 @Transactional(readOnly = true)의 이점에 대해서 알아보자
JPA의 Dirty Checking
영속성 컨텍스트는 Entity 조회 시 초기 상태에 대한 Snapshot을 저장한다.
그리고 더티체킹으로 인해 마지막 flush 때 해당 엔티티의 변경 사항을 저장해주는데, 이 때 readOnly = true 설정을 해주면 스프링 프레임 워크는 JPA의 세션 플러시 모드를 MANUAL로 설정한다.
*MANUAL 모드는 수동으로 flush를 해주지 않으면 수행되지 않는 모드이다.
즉, 예기치 못한 수정사항을 방지할 수 있게된다.
또한, readOnly = true를 설정하게 되면 JPA는 해당 트랜잭션 내에서 조회하는 Entity는 조회용임을 인식하고 변경 감지를 위한 snapShot을 따로 보관하지 않으므로 메모리상 이점도 존재한다.
가독성의 상승
코드를 다 읽어보지 않고 바로 위에 달려있는 readOnly = true만으로 조회 메소드라는 것을 직관적으로 알 수 있어 코드의 가독성에서 이점을 가지게 된다.
Replication 부하 분산
기본적으로 간단한 프로젝트에서는 DB를 하나만 두지만
실제 운용되는 서비스에서는 DB의 장애를 빠르게 복구, 트래픽을 분산하기 위해 실시간 복제본 DB를 운용하는 레플리케이션(Replication) 방식을 사용하는데

CUD의 작업은 Master DB에서 작업 후 추가된 데이터를 Slave DB에 넘겨주고
조회 시 Slave DB에서 수행함으로써 트래픽을 분산할 수 있다
즉 이러한 DB 구조를 가져간다면, readOnly=true가 설정되어있는 메서드의 경우 Slave DB에서 데이터를 가져오도록 동장해, 이를 통해 레플리케이션의 목적에 맞게 트래픽 분산을 온전하게 처리할 수 있게된다.
그렇다면 그냥 조회에는 적용 안하면 안되나?
본인의 수준에서는 전혀 느낄 수 없는 점이지만
@Transactional 어노테이션을 붙이게 되면 해당 영역에서는 JPA의 스냅샷 유지, flush의 필요성, DB 커넥션을 오래 물고 있는 등의 관리적인 측면이 발생한다.
이에 따라, Lazy_Loading, replication과 같이 필요한 경우에 대해서 적절히 해당 어노테이션을 활용하는게 좋으며,
무분별한 @Transactional 사용 시, 스냅샷 유지/ flush의 필요 등 관리적,메모리적 측면에서의 부하와 커넥션을 오래 가지고 있어 커넥션 부족 등의 문제가 발생할 수 있다고 한다.
@Transactional(readOnly = true)를 왜 붙여야 하나요 — 기록을 통한 복습 (tistory.com)