-
@Transaction(readOnly = True)Spring 2022. 5. 8. 15:07
TL;DR
안 써도 됩니다. 하지만 사용하면 성능 최적화 및 실수로 데이터를 변경하는 일을 방지할 수도 있습니다.
본문
JPA 를 사용하다보면 @Transactional(readOnly=True) 가 종종 사용되는 것을 볼 수 있습니다. @Transactional 을 사용하면 Spring AOP 가 해당 메소드 앞, 뒤에 transaction 시작과 transaction.commit() 을 실행해주기 때문에 사용해야 한다는 것을 알았지만 @Transactional(readOnly = True) 는 사용을 하던 하지 않던 별 차이(사실 그동안 어떤 차이도 느끼지는 못했습니다.) 를 느끼지 못했기 때문에 왜 써야하는지 의문이 많이 들었습니다. 최근에 동욱님 책으로 공부를 하고 있을 때 모든 포스팅을 읽어오는 코드에서 @Transactional(readOnly = True) 가 있었기 때문에 이번 기회에 확실히 이해하면 좋을 거 같아 포스팅으로 기록을 남기기로 했습니다.
Baeldung
Baeldung 은 @Transactional(readOnly = True) 를 아래와 같이 설명하고 있습니다.
@Transactional(readOnly = True) 가 설정되어있다고 하더라도 insert 나 update 가 일어날 수도 있고 일어나지 않을 수도 있다고 합니다. @Transactional(readOnly = True) 는 DB Vendor에 따라 일어나는 결과가 달라진다는 것입니다. 따라서 사용하기 전에 본인이 사용하려고 하는 DB Vendor(MySQL, Oracle 등) 와 Version 을 확인하고 실험을 하는 것이 좋습니다.
stackoverflow
위 글을 보고 "만약 entity를 변경하는 연산이 들어간다고 해서 오류가 무조건 나지는 않는구나", "DB에 따라서 다르구나" 정도 알았습니다. 하지만 추가적인 답변을 위해 stackoverflow 에 글을 찾아봤고 아래와 같은 답을 얻을 수 있었습니다.
findAll() 및 findOne(...)과 같은 읽기 메서드는 @Transactional(readOnly = true)을 사용하고 있습니다. 이는 꼭 필요한 것은 아니지만 트랜잭션 인프라에서 몇 가지 최적화를 발생시킵니다. (FlushMode를 MANUAL로 설정하여 Persistence Provider 가 Entity Manager 를 닫을 때 더티 체킹를 건너뛸 수 있도록 합니다.). 그 외에도 플래그는 JDBC 연결에도 설정되어 해당 수준에서 추가 최적화를 유발합니다.
사용하는 데이터베이스에 따라 테이블 잠금을 생략하거나 실수로 트리거할 수 있는 쓰기 작업을 거부하는 용도로 사용할 수도 있습니다. 따라서 쿼리 메서드에 @Transactional(readOnly = true)을 사용하는 것이 좋습니다.
또한 일부 DB의 경우 master-slave 구조로 되어있다면 @Trasactional(readOnly = true) 를 사용하면 master DB를 읽는것이 아닌 읽기전용으로 slave DB를 읽게 설정할 수 있습니다. 즉, 상황에 따라 workload 분산을 해줄 수 있습니다.
결론
- DB 벤더(MySQL, Oracle 등......) 에 따라 @Transactional(readOnly=true) 를 했을 때 만약 update 나 insert 연산이 수행된다고 하여도 오류가 날 수 있고 나지 않을 수도 있습니다.
- @Transactional(readOnly=true) 를 하면 더티체킹을 건너뛰는등 여러 최적화 작업이 일어나기 때문에 성능이 향상됩니다.
- 만약 DB가 master-slave 구조로 되어있다면 추가 설정을 통해서 CUD(create, update, delete) 는 master DB 로 가게 설정하고 Read 는 slave 로 가게 설정하여 workload를 분산할 수 있습니다.
추가로 알아두면 좋을 점
- MySQL 의 InnoDB 는 어떻게 될까?
- @Transactional 없이 Read 를 하는 것과 없이 Read 를 하는 것은 어떤 차이가 있을까?
참고
'Spring' 카테고리의 다른 글
Spring에 비해 SpringBoot 가 가지는 특징 (0) 2022.07.03 Filter 와 Interceptor 의 차이 (0) 2022.06.26 Spring Cloud Sleuth(1) (0) 2022.01.29 Spring Annotation 정리 (1) 2021.05.04 Spring에서 HTML (0) 2020.08.10