728x90
트랜잭션 설정 방법
1. @Transactional
어노테이션 사용
import org.springframework.transaction.annotation.Transactional
- 가장 일반적인 트랜잭션 선언 방식
- AOP 기반 Proxy 방식으로 동작
- 선언 위치: 클래스 또는 메서드 단위
주의사항
- Proxy 방식으로 동작
@Transactional
은 프록시 객체(대리 객체) 를 생성하여 트랜잭션을 적용합니다.- 내부에서 자기 자신의 메서드 호출 시 프록시를 우회하게 되어 트랜잭션이 동작하지 않음
- 즉, 같은 클래스 내부에서
@Transactional
메서드를 호출하면 트랜잭션 적용되지 않음
// 잘못된 예시: 내부 메서드 호출로 트랜잭션이 적용되지 않음
class MemberService {
fun create(member: Member): Member {
return getMember(member) // 트랜잭션 적용 안 됨
}
@Transactional
fun getMember(member: Member): Member {
val saved = repository.save(member)
val error = 1 / 0 // 예외 발생, rollback 기대
return saved
}
}
해결 방법
- 해당 메서드를 외부에서 호출되도록 구조 변경
- 또는
getMember()
를 다른 클래스로 분리해서 별도의 빈으로 만들고 호출
2. TransactionTemplate
사용
val result = transactionTemplate.execute {
// 트랜잭션 내 로직
repository.save(...)
...
}
- 명시적 트랜잭션 제어
@Transactional
보다 정교한 제어 가능- 실무에서는 잘 사용하지 않음 (복잡한 경우에 한함)
- execute를 하여 트랜잭션 처리를 하지만 잘 사용하지 않는다.
3. MySQL 직접 쿼리에서 트랜잭션 사용
START TRANSACTION;
-- 트랜잭션에 포함할 쿼리
UPDATE users SET balance = balance - 100 WHERE id = 1;
UPDATE users SET balance = balance + 100 WHERE id = 2;
COMMIT;
- 롤백 시:
ROLLBACK;
- JDBC 또는 MyBatis에서 수동 트랜잭션 제어 가능
트랜잭션 사용 시 주의사항
- 트랜잭션 범위는 최대한 짧게
- 대량 데이터 트랜잭션은 성능 저하 및 락 문제 유발 가능
- 서비스 계층에서 비즈니스 단위로 선언
참고
@Transactional
의 기본 전파 속성:REQUIRED
- 롤백 조건: 기본적으로
RuntimeException
,Error
에서만 롤백됨@Transactional(rollbackFor = [Exception::class])
등으로 조정 가능
- 프록시 기반이므로 내부 메서드 호출 시 주의 필요
728x90
'BackEnd > Spring Boot' 카테고리의 다른 글
Spring Boot 어노테이션 실행 순서 정리 (0) | 2025.06.24 |
---|---|
QueryDSL 1:N처리[수정예정] (0) | 2025.01.30 |
[간단한 성능 테스트] 간단한 성능 테스트_1 (DB Insert) (0) | 2024.01.20 |
Propagation (0) | 2023.09.07 |
구독 QueryDSL 및 Redis 사용 개발 (0) | 2023.08.27 |