들어가며
스프링과 JPA를 사용할 때 @Transactional(readOnly = true) 설정이 실제로 어떤 동작을 수행하는지 내부 코드 분석을 통해 알아보았습니다.
실행환경
- Hibernate 6.6
- Spring Framework 6.2.6
📌 TL;DR (요약)
✅ 데이터베이스에 읽기 전용 트랜잭션임을 명시적으로 알립니다
✅ 트랜잭션이 종료될 때 영속성 컨텍스트의 변경사항을 flush하지 않습니다
🍖 데이터베이스에 읽기 전용 트랜잭션 알림
JpaTransactionManager
의 doBegin
메소드를 살펴보면:
protected void doBegin(Object transaction, TransactionDefinition definition) {
...
txObject.setReadOnly(definition.isReadOnly());
...
}
이 코드를 통해 트랜잭션 시작 시 데이터베이스에 읽기 전용 요청임을 명시적으로 알려줍니다.
🙇 트랜잭션 종료 시 flush 동작 분석
SessionImpl
클래스의 beforeTransactionCompletion
메소드를 살펴보겠습니다:
public void beforeTransactionCompletion() {
...
flushBeforeTransactionCompletion();
...
}
여기서 호출되는 flushBeforeTransactionCompletion()
메소드를 분석해보면:
public void flushBeforeTransactionCompletion() {
if ( mustFlushBeforeCompletion() ) {
try {
managedFlush();
}
catch ( RuntimeException re ) {
throw ExceptionMapperStandardImpl.INSTANCE
.mapManagedFlushFailure( "error during managed flush", re, this );
}
}
}
mustFlushBeforeCompletion()
가 true 면 flush 하고, 아니면 flush 하지 않는다는 의미입니다.
private boolean mustFlushBeforeCompletion() {
return isTransactionFlushable() && getHibernateFlushMode() != FlushMode.MANUAL;
}
getHibernateFlushMode() != FlushMode.MANUAL
를 주목합시다.
readOnly = true 설정시 getHibernateFlushMode()가 FlushMode.AUTO 라서 false 가 리턴됩니다.
따라서 이경우 flush 하지 않습니다.
영속성 컨텍스트는 어떨까?
예전 블로그에서 readOnly = true 인 트랜잭션이 진행되면 영속성 컨텍스트도 관리되지 않는다는 글을 본적이 있습니다. 하지만 실제론 그렇지 않았습니다.
SessionImpl
클래스의 StatefulPersistenceContext persistenceContext
필드를 살펴보면, readOnly 설정과 관계없이 엔티티는 영속성 컨텍스트에서 관리됩니다.
차이점은 영속성 컨텍스트에서 관리되느냐가 아니라, 트랜잭션 종료 시 변경사항을 flush하느냐의 여부입니다.
결론
@Transactional(readOnly = true) 설정은:
- 데이터베이스에 읽기 전용 트랜잭션임을 명시적으로 알립니다
- 트랜잭션이 종료될 때 영속성 컨텍스트의 변경사항을 flush하지 않지만, 엔티티는 여전히 영속성 컨텍스트에서 관리됩니다
'스프링' 카테고리의 다른 글
@ExceptionHandler는 어떻게 동작할까? Spring 예외 처리의 내부 동작 원리 파헤치기 (2) | 2025.06.25 |
---|---|
톰캣 NIOConnector는 어떻게 수많은 요청을 처리할까? (feat. Acceptor, Poller) (0) | 2025.06.02 |
Hibernate의 객체 매핑 성능 비밀: 내부 동작 원리 파헤치기 (0) | 2025.05.11 |