@Transactional 어노테이션은 Spring에서 사용되는 어노테이션으로 주로 Service 계층에서 사용된다.
아무 생각 없이 사용하던 @Transactional이 어떻게 사용되고 어떻게 동작하는지에 대해서 알아보도록 하자.
@Transactional 어노테이션은 메서드나 클래스의 트랜잭션 경계를 선언하는 데 사용되는데, 여기서 트랜잭션이란 데이터베이스에서 일련의 작업들이 전부 성공하거나 전부 실패하도록 보장하는 것을 의미하고 이를 통해 데이터의 일관성과 무결성을 유지할 수 있다.
@Transactional 어노테이션이 사용된 클래스나 메서드는 Spring이 이들을 트랜잭션 경계 내에서 실행되도록 관리하게 해 준다.
주요 개념
- 트랜잭션 경계: 트랜잭션의 시작과 끝을 정의한다. 트랜잭션 경계 내에서 수행된 모든 작업은 전부 성공하거나 전부 실패해야 한다.
- 트랜잭션 관리: Spring은 선언적 트랜잭션 관리와 프로그래밍적 트랜잭션 관리를 지원한다.(@Transactional은 선언적 트랜잭션 관리 방식)
- 전파(propagation): 트랜잭션 전파는 메서드가 호출될 때 기존 트랜잭션을 사용할지 아니면 새로운 트랜잭션을 시작할지 결정한다.
- 격리 수준(isolation level): 동시에 실행되는 트랜잭션 간의 격리 수준을 결정한다. 이는 데이터 일관성을 유지하는 데 중요
- 롤백 정책(rollback policy): 트랜잭션이 실패했을 때 롤백할 조건을 정의한다.
사용 예
import org.springframework.transaction.annotation.Transactional;
@Service
public class MyService {
@Transactional
public void myTransactionalMethod() {
// 데이터베이스 작업
}
}
속성
@Transactional 어노테이션에는 여러 가지 속성을 설정할 수 있다.
- propagation: 트랜잭션 전파 동작을 정의. 기본값은 REQUIRED
- REQUIRED: 기존 트랜잭션이 존재하면 이를 사용하고, 없으면 새로운 트랜잭션을 생성
- REQUIRES_NEW: 항상 새로운 트랜잭션을 생성
- SUPPORTS: 트랜잭션이 존재하면 이를 사용하고, 없으면 트랜잭션 없이 실행
- isolation: 트랜잭션 격리 수준을 설정. 기본값은 DEFAULT
- DEFAULT: 데이터베이스의 기본 격리 수준을 사용
- READ_UNCOMMITTED: 다른 트랜잭션이 아직 커밋되지 않은 데이터를 읽을 수 있음.
- READ_COMMITTED: 다른 트랜잭션이 커밋된 데이터만 읽을 수 있음.
- REPEATABLE_READ: 한 트랜잭션이 시작된 후 다른 트랜잭션이 해당 트랜잭션이 읽은 데이터를 수정하거나 삭제할 수 없음.
- SERIALIZABLE: 가장 엄격한 격리 수준으로, 트랜잭션이 순차적으로 실행되는 것처럼 보이도록 함. 동시에 실행되는 트랜잭션이 서로 간섭하지 않음.
- timeout: 트랜잭션이 완료될 때까지 기다리는 최대 시간을 초 단위로 설정. 기본값은 -1로 무제한이다.
- readOnly: 트랜잭션이 읽기 전용임을 나타냄. 기본값은 false
- rollbackFor 및 rollbackForClassName: 트랜잭션을 롤백해야 하는 예외를 지정
- noRollbackFor 및 noRollbackForClassName: 트랜잭션을 롤백하지 않아야 하는 예외를 지정
사용 예
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED, timeout = 30, readOnly = false)
public void anotherTransactionalMethod() {
// 데이터베이스 작업
}
주의사항
- 프록시 사용: @Transactional은 Spring AOP를 사용하여 프록시 기반으로 동작한다. 따라서 동일한 클래스 내에서 @Transactional 메서드를 직접 호출하면 트랜잭션이 적용되지 않을 수 있다.
- 체크 예외: 기본적으로 체크 예외가 발생하면 트랜잭션이 롤백되지 않는다. 이를 원하지 않으면 rollbackFor 속성을 사용해야 한다.
- 프록시 객체 사용: 트랜잭션이 프록시 객체를 통해 관리되므로, 프록시 객체를 직접 사용하는 것과 동일한 동작을 보장해야 한다.
'Back-end > Spring' 카테고리의 다른 글
Spring에서의 예외 처리 (0) | 2024.07.10 |
---|---|
Spring Annotation (0) | 2024.03.13 |