기술과 산업/언어 및 프레임워크
Spring Boot 고급 시리즈 1편 – @Transactional 완전 정복: 실무 트랜잭션 설계 전략
B컷개발자
2025. 4. 17. 21:28
728x90
Spring Boot에서 @Transactional을 제대로 이해하고 사용하는 방법을 정리했습니다. 트랜잭션 전파, 롤백 전략, 예외 처리까지 실무 중심으로 설명합니다.
Spring Boot 고급 시리즈 1편 – @Transactional 완전 정복: 실무 트랜잭션 설계 전략
Spring Boot 개발에서 @Transactional은 마법처럼 보이지만, 그 이면을 제대로 이해하지 않으면 데이터 정합성 이슈나 롤백 실패라는 큰 문제에 직면할 수 있습니다.
이번 글에서는 @Transactional의 내부 동작 원리부터 전파 속성, 예외 처리 전략, 그리고 테스트 설계까지 실무에서 반드시 알아야 할 트랜잭션 처리 방식을 깊이 있게 분석합니다.
📌 1. @Transactional 기본 개념
@Transactional
public void createUser(UserDto dto) {
userRepository.save(dto.toEntity());
}
- @Transactional은 메서드나 클래스에 선언 가능
- 시작 시 트랜잭션을 열고, 종료 시 커밋 또는 롤백
- 내부적으로는 **스프링 AOP(프록시 기반)**로 동작
🔄 2. 트랜잭션 전파(Propagation) 완벽 이해
전파 속성은 트랜잭션이 있는 상황에서 다른 트랜잭션을 호출할 때 어떻게 동작할지를 정의합니다.
속성 설명
| REQUIRED | 기본값, 기존 트랜잭션 있으면 참여, 없으면 새로 시작 |
| REQUIRES_NEW | 항상 새로운 트랜잭션 시작, 기존 트랜잭션은 일시 중단 |
| NESTED | 내부 트랜잭션, savepoint 지원 (DB가 지원해야 함) |
| SUPPORTS | 있으면 참여, 없으면 트랜잭션 없이 실행 |
| MANDATORY | 반드시 기존 트랜잭션 있어야 실행, 없으면 예외 |
| NOT_SUPPORTED | 트랜잭션 무시하고 실행 |
| NEVER | 트랜잭션 존재 시 예외 발생 |
✅ 실무 팁
- 이메일 전송, 로그 기록 등은 REQUIRES_NEW로 분리하면 실패해도 원 트랜잭션에 영향 없음
- 동일 클래스 내부 호출은 AOP 적용되지 않아 전파 속성 무시됨 → 분리된 Bean으로 구성 필요
🧨 3. 트랜잭션 롤백 규칙
기본적으로는 Unchecked Exception(RuntimeException, Error) 발생 시 롤백됩니다.
@Transactional
public void save() {
throw new RuntimeException("예외 발생"); // 롤백됨
}
⚠️ Checked Exception 처리
@Transactional(rollbackFor = SQLException.class)
public void save() throws SQLException {
throw new SQLException(); // rollbackFor 없으면 커밋됨
}
- rollbackFor, noRollbackFor로 롤백 정책 명시
- 예외 타입에 따라 롤백 여부가 결정된다는 점을 항상 고려해야 합니다.
🧠 4. 실무 트랜잭션 설계 전략
🔷 트랜잭션은 "서비스 계층"에서만 선언
- Repository 계층에는 선언하지 않음 → 단순 DB 호출 역할만 수행
- Service는 “업무 단위”를 정의 → 트랜잭션도 이 단위에 묶이는 것이 자연스러움
🔷 외부 호출 전후는 트랜잭션 분리
- 외부 API 호출, 메일 전송, 파일 업로드 등은 실패 가능성이 높음
- 메인 트랜잭션과 분리 → REQUIRES_NEW 또는 트랜잭션 없이 실행
🔷 복합 트랜잭션은 메서드 분리 & 명확한 책임 분산
public void registerUser() {
saveUser(); // DB 저장 트랜잭션
sendWelcomeEmail(); // 별도 트랜잭션 or 비동기 처리
}
🧪 5. @Transactional 테스트 전략
✅ 테스트용 트랜잭션 자동 롤백
@SpringBootTest
@Transactional
class UserServiceTest {
// 테스트 종료 시 자동 롤백
}
✅ 트랜잭션 테스트 주의사항
- 동일 트랜잭션 내에서 쿼리 실행 시 영속성 컨텍스트에 의해 반영됨
- DB에 실제 반영되는지 확인하려면 flush() 또는 @Rollback(false) 활용
✅ 마무리 요약
항목 핵심 포인트
| 선언 위치 | Service 계층 권장 |
| 전파 속성 | REQUIRED, REQUIRES_NEW 필수 이해 |
| 롤백 조건 | 기본 RuntimeException, Checked 예외는 명시 필요 |
| 내부 호출 | AOP 적용되지 않음 → 분리된 빈에서 호출 |
| 테스트 전략 | 자동 롤백, @Rollback 옵션 설정 가능 |
📌 다음 편 예고
Spring Boot 고급 시리즈 2편: 계층 분리와 서비스 아키텍처 – 유지보수 가능한 구조 만들기
728x90