스프링에서이  @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





LIST

+ Recent posts