@Transactional 사용법과 옵션
Spring 프레임워크에서 @Transactional 어노테이션은 트랜잭션 관리를 간편하게 해주는 도구로, 트랜잭션의 원자성, 일관성, 고립성, 내구성을 보장하도록 설정할 수 있다.
- propagation: 트랜잭션의 전파 방식을 결정 (기본값은 REQUIRED).
- isolation: 트랜잭션 격리 수준을 설정하여 트랜잭션 간 데이터 접근을 제어 (예: READ_COMMITTED, REPEATABLE_READ 등).
- timeout: 트랜잭션이 완료되기까지의 최대 시간을 설정.
- readOnly: 트랜잭션이 데이터 변경 없이 읽기 전용임을 선언.
@Transactional(isolation = Isolation.SERIALIZABLE, timeout = 10, readOnly = true)
public void processOrder(Order order) {
// 트랜잭션 내에서 실행될 비즈니스 로직
}
propagation
propagation은 트랜잭션의 전파 방식을 정의한다.
여기서 전파란, 트랜잭션 내에서 또 다른 트랜잭션이 시작될 때 그 트랜잭션이 기존 트랜잭션에 합쳐질지, 새로운 트랜잭션으로 시작될지를 결정하는 것이다.
- REQUIRED(기본값): 기존 트랜잭션이 존재하면 그 트랜잭션을 사용하고, 없으면 새로운 트랜잭션을 생성한다.
- 예시: 비즈니스 로직 메서드 A가 트랜잭션을 열고 있고, A에서 호출된 메서드 B가 @Transactional(propagation = Propagation.REQUIRED)로 설정되어 있다면, B는 새로운 트랜잭션을 생성하지 않고 A의 트랜잭션을 그대로 사용한다.
- REQUIRES_NEW: 항상 새로운 트랜잭션을 생성하며, 기존 트랜잭션이 있다면 일시적으로 중단한다.
- 예시: 비즈니스 로직 메서드 A의 트랜잭션이 열려 있을 때 메서드 B에서 REQUIRES_NEW가 설정되어 있으면, B는 새로운 트랜잭션을 생성하고 A의 트랜잭션은 일시적으로 중단된다. B가 완료되면 A의 트랜잭션이 재개된다.
- 이렇게 하면 A와 B는 독립적인 트랜잭션이 되어, 하나의 트랜잭션이 실패해도 다른 트랜잭션에는 영향을 미치지 않게 된다.
- NESTED: 중첩된 트랜잭션을 생성한다. 이 중첩 트랜잭션은 부모 트랜잭션에 종속되지만, 자식 트랜잭션의 작업이 별도의 커밋 지점을 가질 수 있다.
- 예시: 비즈니스 로직 메서드 A가 실행되면서 메서드 B를 호출하는데, B가 @Transactional(propagation = Propagation.NESTED)로 설정된 경우, B는 A의 자식 트랜잭션으로서 중첩된 트랜잭션을 생성한다.
- B의 트랜잭션이 실패해도 A의 다른 작업에 영향을 주지 않도록 부분 롤백이 가능하다.
- SUPPORTS: 트랜잭션이 필요하지 않지만, 기존 트랜잭션이 있다면 그 트랜잭션을 사용한다.
- 예시: 비즈니스 로직 메서드 A가 트랜잭션 없이 실행되는 동안 메서드 B에서 SUPPORTS가 설정되어 있다면, B는 트랜잭션 없이 실행된다.
- 반대로 A가 트랜잭션을 열고 있다면 B도 그 트랜잭션을 사용하게 된다.
- MANDATORY: 반드시 기존 트랜잭션이 있어야 하며, 그렇지 않으면 예외가 발생한다.
- 예시: 메서드 B가 MANDATORY로 설정된 경우, 호출한 메서드 A가 트랜잭션 없이 B를 호출하면 예외가 발생한다.
- 기존 트랜잭션에 참여할 때만 실행이 가능하므로 주로 트랜잭션 연속성을 보장하고자 할 때 사용됩니다.
- NEVER: 트랜잭션을 사용하지 않으며, 기존 트랜잭션이 존재할 경우 예외를 발생시킨다.
- 예시: 특정 메서드가 트랜잭션이 없는 상태에서만 실행되어야 한다면 NEVER를 설정하여, 기존 트랜잭션이 존재할 경우 예외를 발생시키게 할 수 있다.
- NOT_SUPPORTED: 트랜잭션을 중단하고 비트랜잭션(non-transactional) 모드로 실행한다.
- 예시: 비즈니스 로직 메서드 A가 트랜잭션을 열고 메서드 B를 호출하는데, B가 NOT_SUPPORTED로 설정되어 있으면, B는 트랜잭션 없이 실행된다.
isolation
isolation은 트랜잭션이 다른 트랜잭션으로부터 얼마나 격리되어야 하는지를 결정한다. 일반적으로 다음 네 가지 수준이 있으며, 트랜잭션이 데이터를 읽거나 쓰는 중 다른 트랜잭션이 영향을 미치는 정도를 조절한다.
- READ_COMMITTED(기본값): 커밋된 데이터만 읽을 수 있습니다.
- REPEATABLE_READ: 트랜잭션 내에서 동일한 데이터를 여러 번 읽어도 값이 변하지 않습니다.
- SERIALIZABLE: 가장 엄격한 격리 수준으로, 트랜잭션이 순차적으로 실행됩니다.
timeout
timeout 옵션은 트랜잭션이 수행될 최대 시간을 설정합니다. 지정된 시간이 초과되면 트랜잭션은 자동으로 롤백된다. 기본값은 무제한이다.
readOnly
readOnly = true 옵션을 사용하면 데이터베이스가 읽기 전용 모드로 실행되며, 읽기 작업에 최적화된다. 성능 최적화가 필요하거나 데이터 수정이 발생하지 않도록 보장하고 싶을 때 사용된다.