스프링 트랜잭션은 데이터베이스에서 수행되는 여러 작업들을 하나의 작업단위로 묶어서 관리하는 기능이다. 트랜잭션 내의 모든 작업이 성공하면 커밋하고, 하나라도 실패를 하게되면 작업을 롤백시킬 수 있다.
스프링은 PlatformTransactionManager라는 인터페이스를 통해 트랜잭션을 추상화 한다.
public interface PlatformTransactionManager extends TransactionManager {
TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException;
void commit(TransactionStatus status) throws TransactionException;
void rollback(TransactionStatus status) throws TransactionException;
}
ACID 특성
ACID는 트랜잭션이 안전하게 수행된다는 것을 보장하기 위한 성질을 가리키는 약어이다.
• 원자성(Atomicity)
트랜잭션 내의 모든 작업이 완전히 수행되거나, 하나라도 실패할 경우 전체 작업이 취소된다.
• 일관성(Consistency)
트랜잭션이 성공적으로 완료되면 데이터베이스는 일관된 상태를 유지한다.
• 독립성(Isolation)
각 트랜잭션은 다른 트랜잭션으로 부터 독립적으로 수행되며, 트랜잭션이 완료되기 전까지는 다른 트랜잭션이 그 결과를 참조할 수 없다.
• 지속성(Durability)
트랜잭션이 완료된 후의 변경사항은 영구적으로 데이터베이스에 저장된다.
트랜잭션 사용방법
트랜잭션 사용법은 간단하다. 트랜잭션을 적용시킬 위치에 @Transactional 어노테이션을 추가해주면 되는데, 어노테이션을 어디에 적용하는지에 따라서 트랜잭션의 범위와 적용대상이 달라진다.
1. 클래스 레벨
클래스 레벨에 트랜잭션을 적용하면, 해당 클래스의 모든 메서드에 트랜잭션이 적용된다. 아래 코드로 보면 transactionTest1(), transactionTest2() 메서드에 모두 트랜잭션이 적용되게 된다.
@Service
@Transactional
public class MainService {
public void transactionTest1() {
// 서비스 로직..
}
public void transactionTest2() {
// 서비스 로직..
}
}
2. 메소드 레벨
메소드 레벨에 트랜잭션을 적용하면 해당 위치의 메소드만 트랜잭션이 적용된다.
@Service
public class MainService {
@Transactional
public void transactionTest() {
// 서비스 로직..
}
}
트랜잭션 옵션 소개
트랜잭션 어노테이션은 다양한 옵션을 통해 트랜잭션의 동작을 세밀하게 제어할 수 있다. 트랜잭션의 전파, 격리수준, 타임아웃, 읽기 전용 여부등을 설정하는데 사용한다.
여기서는 대표적인 옵션들만 간단히 정리해보고, 자세한 내용은 다른피드를 통해 정리해보도록 하겠다.
• 전파수준(Propagation)
트랜잭션 전파 수준은 메소드가 트랜잭션내에서 호출될 떄 어떻게 동작할지를 결정한다.
public enum Propagation {
REQUIRED(0),
SUPPORTS(1),
MANDATORY(2),
REQUIRES_NEW(3),
NOT_SUPPORTED(4),
NEVER(5),
NESTED(6);
private final int value;
private Propagation(int value) {
this.value = value;
}
public int value() {
return this.value;
}
}
- REQUIRED (기본값) : 현재 트랜잭션이 존재하면 그 트랜잭션을 사용하고, 존재하지 않으면 새 트랜잭션을 시작한다.
- REQUIRED_NEW : 항상 새로운 트랜젝션을 시작하며, 기존 트랜잭션이 있다면 일시 정지한다.
- SUPPORTS : 현재 트랜잭션이 있으면 그 트랜잭션을 사용하고, 없으면 트랜잭션 없이 실행한다.
- NOT_SUPPORTED : 트랜잭션이 있으면 일시정지하고, 트랜잭션 없이 메소드를 실행한다.
- MANDATORY : 현재 트랜잭션이 있어야 하며, 없으면 예외를 발생시킨다.
- NEVER : 현재 트랜잭션이 있으면 예외를 발생시키고, 없으면 트랜잭션 없이 실행한다.
- NESTED : 현재 트랜잭션이 있으면 중첩 트랜잭션을 시작하고, 없으면 새 트랜잭션을 시작합니다.
사용 예)
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void transactionTest() {
// 서비스 로직...
}
• 읽기 전용 여부(Read-Only)
트랜잭션이 데이터베이스에서 읽기전용 작업만 수행할 것인지를 결정한다. 읽기전용 트랜잭션에서 성능 최적화를 할 수 있게 도와준다.
- @Transactional(readOnly = true) : 읽기전용 트랜잭션
- @Transactional(readOnly = false) : 읽기, 쓰기 둘다 가능(기본값)
사용 예)
@Transactional(readOnly = true)
public void transactionTest() {
// 서비스 로직...
}
이번 피드에서는 간단하게 스프링 트랜잭션에 대해서 알아보았는데, 앞으로 피드를 통해 스프링 트랜잭션에 대해 자세히 정리하는 시간을 가져보겠습니다.
'노빠꾸 개발일지 > SPRING' 카테고리의 다른 글
[Spring Data JPA] 쿼리 메소드 @Query 어노테이션 JPQL 쿼리 (0) | 2023.06.15 |
---|---|
[Spring Data JPA] 쿼리 메소드(Query Method) 방식 알아보기 (0) | 2023.06.14 |
[Spring Boot] 스프링부트 H2 DB 연결해보기 (0) | 2023.06.13 |
[스프링] 의존성 주입(Dependency Injection) 방법 (0) | 2023.06.12 |
스프링 프레임워크(Spring Framework)와 스프링 부트(Spring Boot) (0) | 2023.06.03 |