[Spring Boot] 트랜잭션(Transaction) 가이드
KUKJIN LEE • 1주 전 작성
Spring Boot에서 트랜잭션(Transaction)은 데이터의 일관성을 보장하고, 여러 작업을 하나의 논리적 단위로 묶어 처리할 수 있도록 지원합니다.
트랜잭션(Transaction)이란?
트랜잭션은 데이터베이스에서 일련의 작업 단위를 말하며, 작업이 모두 성공하거나, 실패 시 전부 롤백(rollback)되어야 하는 원자성을 보장합니다. 따라서 Spring Boot만을 위한 내용이 아니라, CS 지식으로 반드시 알고가야 하는 내용 중 일부입니다.
트랜잭션의 ACID 속성
-
Atomicity (원자성): 모든 작업이 성공하거나 실패 시 모두 취소됩니다.
-
Consistency (일관성): 작업 완료 후 데이터베이스 상태가 일관성을 유지합니다.
-
Isolation (격리성): 동시에 실행되는 트랜잭션이 서로에게 영향을 미치지 않습니다.
-
Durability (지속성): 트랜잭션이 완료되면 데이터는 영구적으로 저장됩니다.
Spring Boot에서 트랜잭션 설정
Spring Boot는 트랜잭션 관리를 간소화하며, @Transactional
어노테이션을 통해 쉽게 구현할 수 있습니다.
의존성 추가
Spring Boot에서 트랜잭션을 사용하려면 기본적으로 JPA나 JDBC 의존성이 필요합니다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
@EnableTransactionManagement
활성화
Spring Boot는 기본적으로 트랜잭션 관리를 활성화하지만, @EnableTransactionManagement
설정을 통해 커스터마이징 가능합니다.
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
public class TransactionConfig {
// 커스텀 트랜잭션 설정 (필요 시)
}
@Transactional
사용법
Spring Boot에서 트랜잭션 처리를 위해 주로 사용하는 어노테이션입니다.
기본 사용
트랜잭션을 적용하려는 메서드나 클래스에 @Transactional
을 추가합니다.
클래스에 적용
클래스 전체의 메서드에 트랜잭션을 적용합니다.
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional
public class UserService {
public void createUser(User user) {
// 모든 작업이 하나의 트랜잭션 내에서 처리됨
}
}
메서드에 적용
특정 메서드에만 트랜잭션을 적용합니다.
import org.springframework.transaction.annotation.Transactional;
@Transactional
public void updateUser(User user) {
// 트랜잭션 처리 로직
}
트랜잭션 속성
기본 설정으로 충분합니다. 특별한 이유가 없다면 기본 `@Transactional` 어노테이션으로 충분합니다. 이펙티브 수준을 원하시는 게 아니라면 그냥 읽고 넘어가도 좋습니다.
주요 속성
-
propagation
: 트랜잭션 전파 방식. -
isolation
: 트랜잭션 격리 수준. -
timeout
: 트랜잭션 제한 시간. -
readOnly
: 읽기 전용 여부.
@Transactional(
propagation = Propagation.REQUIRED,
isolation = Isolation.READ_COMMITTED,
timeout = 5,
readOnly = false
)
public void processTransaction() {
// 트랜잭션 내 처리
}
전파(Propagation) 옵션
트랜잭션의 전파 방식을 설정하여 기존 트랜잭션과의 관계를 정의합니다.
옵션 |
설명 |
---|---|
|
기본 값. 기존 트랜잭션이 있으면 참여, 없으면 새로 시작. |
|
항상 새로운 트랜잭션을 시작. 기존 트랜잭션은 보류. |
|
기존 트랜잭션 내에서 중첩 트랜잭션을 시작. |
|
기존 트랜잭션이 있으면 참여, 없으면 트랜잭션 없이 실행. |
|
트랜잭션 없이 실행. 기존 트랜잭션은 보류. |
|
반드시 기존 트랜잭션에 참여. 없으면 예외 발생. |
|
트랜잭션 없이 실행. 기존 트랜잭션이 있으면 예외 발생. |
격리 수준(Isolation Level)
트랜잭션 간 간섭을 방지하기 위한 격리 수준을 설정합니다.
옵션 |
설명 |
---|---|
|
데이터베이스 기본 격리 수준 사용. |
|
다른 트랜잭션의 미완료 변경 내용 읽기 허용. |
|
커밋된 데이터만 읽기 허용. (기본) |
|
트랜잭션 동안 동일한 데이터 읽기 보장. |
|
가장 높은 격리 수준. 트랜잭션 순차 실행. |
실무에서의 트랜잭션 활용
트랜잭션 롤백
Spring Boot에서 예외 발생 시 트랜잭션은 자동으로 롤백됩니다.
-
기본적으로
RuntimeException
및Error
는 롤백됩니다. -
CheckedException
은 기본적으로 롤백되지 않으므로, 명시적으로 설정해야 합니다.
@Transactional(rollbackFor = Exception.class)
public void processTransaction() throws Exception {
// 작업 수행 중 예외 발생 시 롤백
throw new Exception("Rollback Test");
}
읽기 전용 트랜잭션
읽기 전용 작업에는 readOnly = true
를 설정하여 성능을 최적화할 수 있습니다.
@Transactional(readOnly = true)
public List<User> getUsers() {
return userRepository.findAll();
}
트랜잭션 관리 주의사항
-
@Transactional
은 public 메서드에서만 동작-
Spring AOP 기반으로 동작하므로, private 메서드에서는 트랜잭션이 적용되지 않습니다.
-
-
자기 호출(self-invocation) 문제
-
같은 클래스 내에서
@Transactional
이 선언된 메서드를 호출하면 트랜잭션이 적용되지 않을 수 있습니다.
-
-
읽기 전용 설정
-
읽기 전용 작업에서 쓰기 작업을 수행하면 예외가 발생할 수 있습니다.
-
-
DB 락(lock) 주의
-
높은 격리 수준(예:
SERIALIZABLE
)은 데드락 가능성을 높일 수 있으므로 주의해야 합니다.
-