@Transactional(readOnly = true) 을 사용하면 뭐가 좋을까?

BinaryHyeok·2023년 3월 28일
0
post-thumbnail

개요

스프링부트에서 Service단의 클래스에 @Transactional(readOnly = true) 를 붙여서 사용하고 있었고,
DB에 수정사항이 변경되는 메소드들에게는 따로 @Transactional 어노테이션을 달아서 사용하였다.
이렇게 사용하면 예상치 못한 엔티티의 등록, 수정, 삭제가 불가능하고 성능 최적화가 가능하다고 한다.
왜 그런 것일까?

Transaction

트랜잭션은 데이터베이스의 상태를 변화시키기 위해서 수행하는 작업의 단위이다. 만약 어떤 한 서비스 로직에서 다른 엔티티의 값을 변경할 때, 변경 도중 에러가 발생하면 나머지 변경사항도 초기화하여 없던 일로 만들어야 한다.
따라서 이러한 작업을 보장해주고 위해서 상태 변경이 일어나는 메소드들에 @Transactional 어노테이션을 사용하였다.

readOnly = true은 왜 사용하는가?

영속성 컨텍스트는 엔티티가 1차 캐시에 저장될 때, 저장되는 시점의 상태를 스냅샷으로 만들어서 1차캐시에 보관한다.
그리고 트랜잭션이 커밋되는 시점에 현재 엔티티와 스냅샷에 저장한 엔티티를 비교하여 변경사항이 있다면 JPA는 이를 감지하여 DB에 반영하게 된다.

하지만 readOnly옵션을 true로 사용하게 된다면, 이 동작을 수행하지 않으므로 메모리가 절약된다.
또한 flushMode가 MANUAL로 설정되서 직접 flush하지 않는다면 flush가 일어나지 않게 된다.

다만 readOnly라고 CUD 동작이 안되는 것은 아니므로 조심해야한다.

정리

readOnly 옵션을 사용하면 스냅샷, dirty check 등의 동작을 수행하지 않으므로 성능적으로 이득이 있다.
그리고 조회만 하는 메소드에 readOnly옵션을 사용하므로 누구나 이 메소드가 읽기를 수행하는 메소드라는 것을 알아차릴 수 있다고 생각한다.
지금까지는 클래스에서 @Transactional(readOnly=true)옵션을 사용하고, 데이터의 변경이 일어나는 메소드들에게만Transactional을 사용하여 조금이라도 중복된 코드를 줄이려는 시도를 했었는데, 앞으로는 누가보아도 알아볼 수 있도록 달아보는 것도 괜찮은 방법인 것 같다.

0개의 댓글