스프링에서이 @Transactional이 안 먹히는(동작하지 않는) 주요 원인들을 정리해드릴게요. 이건 실무에서도 자주 마주치는 중요한 이슈입니다.
---
✅ 1. 자기 자신을 호출할 때 (내부 호출 문제)
❌ 예시:
@Service
public class MyService {
@Transactional
public void outerMethod() {
innerMethod(); // 트랜잭션 적용 안 됨
}
@Transactional
public void innerMethod() {
// 트랜잭션 적용 기대 → ❌ 안 됨
}
}
🔥 원인:
스프링의 트랜잭션은 프록시 기반 AOP인데, 자기 자신(this)으로 호출하면 프록시를 거치지 않아서 적용 안 됨.
✅ 해결:
innerMethod()를 다른 빈에 분리하거나
AopContext.currentProxy()로 강제로 프록시 호출 (비추천)
---
✅ 2. @Transactional이 public이 아닌 메서드에 붙은 경우
❌ 예시:
@Transactional
private void doSomething() { ... } // 적용 안 됨
🔥 원인:
프록시 기반 AOP는 public 메서드만 지원
✅ 해결:
@Transactional은 꼭 public 메서드에 붙여야 함
---
✅ 3. 프록시 적용 시점보다 먼저 호출된 경우
예를 들어, @PostConstruct나 생성자 안에서 @Transactional 메서드 호출 시
❌ 예시:
@PostConstruct
public void init() {
transactionalMethod(); // 아직 프록시 적용 전 → ❌ 안 먹힘
}
✅ 해결:
트랜잭션은 빈 초기화 이후, 즉 요청 처리 시점에 적용되도록 설계해야 함
---
✅ 4. 스프링 설정에 @EnableTransactionManagement 누락
❌ 예시:
XML 기반에서 <tx:annotation-driven/> 없거나
Java Config에서 @EnableTransactionManagement 안 붙은 경우
✅ 해결:
@Configuration
@EnableTransactionManagement
public class AppConfig {
...
}
---
✅ 5. 예외가 캐치되어 rollback이 안 되는 경우
❌ 예시:
@Transactional
public void doSomething() {
try {
// 에러 발생
} catch (Exception e) {
// 예외 잡아버림 → rollback 안 됨
}
}
🔥 원인:
기본적으로 RuntimeException 이상만 rollback됨
예외가 잡히면 스프링은 트랜잭션 실패로 인식하지 않음
✅ 해결:
예외를 던지거나, @Transactional(rollbackFor = Exception.class) 설정
---
✅ 6. 데이터소스가 트랜잭션을 지원하지 않을 때
예: JDBC 연결이 잘못되었거나, 트랜잭션 매니저 설정이 이상할 때
---
🔍 결론 요약
원인 설명
내부 메서드 호출 this로 호출해서 프록시 안 거침
public 아님 AOP는 public만 대상
초기화 시 호출 @PostConstruct, 생성자 등에서 호출 시 프록시 적용 안 됨
설정 누락 @EnableTransactionManagement 빠짐
예외 캐치 예외가 롤백 트리거 안 됨
트랜잭션 매니저 문제 잘못된 설정, 사용 불가능한 DB
'Spring & Backend' 카테고리의 다른 글
| 브라우저가 폰트를 적용하는 과정을 설명해주세요 (4) | 2025.07.24 |
|---|---|
| 인덱스 변경 시 DB에 락 (2) | 2025.07.24 |
| never와 unknown 타입에 대해서 설명해주세요 (2) | 2025.07.23 |
| 낙관적 락과 비관적 락에 대해 설명해 주세요. (2) | 2025.07.23 |
| 계층형 아키텍처 (0) | 2025.07.22 |
