티스토리 뷰
목차
✅ 1.트랜잭션이란?
하나의 작업 단위를 원자성 있게 처리하기 위한 논리적 작업 묶음
모두 성공하거나, 하나라도 실패하면 전체를 롤백해야 함
📌 ACID 원칙
| 항목 | 설명 |
| Atomicity(원자성) | 전부 선공 or 전부 실패 (불완전 상태 금지) |
| Consistency(일관성) | 작업 후 데이터 정합성 보장 |
| Isolation(격리성) | 동시에 실행되는 트랜잭션 간 간섭 없음 |
| Durability(지속성) | 커밋된 트랜잭션은 영구 반영됨 |
💉 2. Spring의 @Transational이란?
Spring AOP 기반으로 구현된 선언적 트랜잭션 처리 방식
특정 메서드나 클래스에서 트랜잭션 범위와 롤백/커밋 조건을 선언적으로 지정할 수 있음
@Transactional
public void order() {
saveOrder();
savePayment();
}
-> order() 메서드 실행 중 예외 발생 시, 전체 작업을 자동으로 롤백
3. @Transactional 내부 동작 구조
✅ AOP 기반 프록시 매커니즘
Client → [Proxy] → @Transactional Advice → 실제 비즈니스 메서드
- 실제 메서드 호출 전 -> 트랜잭션 시작
- 메서드 정상 종료 -> 커밋
- 런타임 예외 발생 -> 롤백
- 체크 예외 발생 -> 기본적으로 롤백 X (설정 필요)
✅PlatformTransactionManager가 핵심 인터페이스
- DataSourceTransactionManager (JDBC 기반)
- JapTransactionManager (JPA 기반)
4. 실습 예제 (JPA 기준)
@Service
public class MemberService {
@Transactional
public void join(Member member) {
memberRepository.save(member);
// 예외 발생 시 전체 롤백
}
}
✅ 클래스 수준에 선언 시 -> 모든 메서드에 적용
@Transactional
public class OrderService {
public void createOrder() { ... }
public void cancelOrder() { ... }
}
5. 전파(Propagation) 옵션
| 옵션 | 설명 |
| REQUIRED(기본) | 기존 트랜잭션 있으면 참여, 없으면 새로 생성 |
| REQUIRES_NEW | 무조건새로운 트랜잭션 생성 (기존은 일시 중단) |
| NESTED | 트랜잭션 안에 또 다른 트랜잭션 (Savepoint 사용) |
| SUPPORTS | 트랜잭션 있으면 참여, 없으면 그냥 실행 |
| NOT_SUPPORTED | 트랜잭션 있으면 일시 중단하고 비트랜잭션 수행 |
| NEVER | 트랜잭션 있으면 예외 발생 |
| MANDATORY | 반드시 트랜잭션 있어야 함 (없으면 예외) |
✅ 실무 예시 : 로깅은 REQUIRES_NEW
@Transactional(propagation = REQUIRES_NEW)
public void logError(String msg) { ... }
6. 고립 수준
| 수준 | 설명 | 현상 방지 |
| DEFAULT | DB 기본 수준 (대부분 READ_COMMITED) | - |
| READ_UNCONMMITED | 커밋 전 데이터 읽기 가능 | Dirty Read 가능 |
| READ_COMMITED | 커밋된 데이터만 읽음 | Dirty Read 방지 |
| REPEATABLE_READ | 같은 트랜잭션 내동일 쿼리 결과 유지 | Non-repeatable Read 방지 |
| SERIALIZABLE | 가장 엄격, 완전한 격리 | Phantom Read 방지 |
@Transactional(isolation = Isolation.REPEATABLE_READ)
7. 롤백 조건
- 기본 : RuntimeException 또는 Error 발생 시만 롤백
- CheckedException은 롤백하지 않음 -> 명시 필요
@Transactional(rollbackFor = Exception.class)
8. 실무에서 주의할 점
✅ 1. 자기 자신 호출 (self-invocation) -> AOP 미적용
@Transactional
public void methodA() {
methodB(); // 같은 클래스 내 호출 = 프록시 우회 → 트랜잭션 적용 안됨
}
-> 해결책 : 별도 Bean 분리 또는 AOP-aware 방식 사용
✅ 2. 비공개 메서드(private)는 트랜잭션 적용 안됨
- Spring AOP는 public 메서드에만 적용
✅ 3. 메서드 내부에서예외 삼키면 롤백되지 않음
@Transactional
public void save() {
try {
repository.save(); // 예외 발생했지만 catch로 삼킴
} catch (Exception e) {
// 롤백 안 됨
}
}
-> TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 호출로 수동 롤백 가능
✅ 마무리 요약
| 항목 | 핵심 포인트 |
| 트랜잭션 개념 | 원자성 보장, ACID 만족 |
| @Transactional 동작 | AOP 기반 프록시 -> PlatformTransactionalManager 제어 |
| 주요 옵션 | propagation, isolation, rollbackFor |
| 실무 이슈 | 자기 호출, private 메서드, 예외 삼킴 등 주의 |
'IT > Spring' 카테고리의 다른 글
| 🔐 Spring Security & JWT 인증 흐름 완전 정복 - 로그인 인증부터 토큰 발급, 필터 구조 (0) | 2025.06.24 |
|---|---|
| ⚠️Spring 예외 처리 완전 정복 - @ControllerAdvice, @ExceptionHandler, 그리고 실무 예외 전략 (0) | 2025.06.18 |
| Spring AOP 완전 정복 - 핵심 로직과 횡단 관심사의 완전 분리 (0) | 2025.06.05 |
| Spring의 DI 방식 완전 정복 - 생성자 / 필드 / 세터 주입, 그리고 언제 어떻게 써야 하는가? (0) | 2025.05.13 |
| Spring Bean과 생명주기 - Bean의 생성부터 소멸까지, 내부에서는 어떤 일이 벌어질까? (0) | 2025.05.12 |