어떤 예외가 발생하면 트랜잭션을 롤백하나요?

김상진 ·2025년 2월 24일
0

CS

목록 보기
31/34

어떤 예외가 발생하면 트랜잭션을 롤백하나요?

Spring 기반 백엔드 개발을 하다 보면, 트랜잭션이 예상대로 롤백되지 않아 곤란한 상황을 겪은 적이 한 번쯤은 있을 것입니다.
이번 글에서는 Spring 트랜잭션의 예외 처리와 롤백 기준을 중심으로, 실무에서 반드시 알아야 할 핵심 개념과 동작 방식을 정리해봅니다.


✅ 기본 원칙: 어떤 예외가 롤백을 트리거할까?

Spring에서는 @Transactional 어노테이션을 통해 선언적 트랜잭션을 사용할 수 있습니다.
이때 어떤 예외가 발생하면 트랜잭션이 롤백되고, 어떤 예외는 커밋되는지 기준은 아래와 같습니다.

예외 종류기본 동작롤백 여부
Unchecked Exception (RuntimeException, Error)예외 발생 시 자동 전파롤백 됨
Checked Exception (Exception 상속 중 RuntimeException 제외)기본적으로 커밋롤백 안 됨

즉, 예외가 RuntimeException 이상이면 롤백이 기본이지만, IOException, SQLException, ParseException 같은 체크 예외는 자동 롤백되지 않습니다.


⚠️ 예외를 catch하면 롤백되지 않는다

이건 실무에서 자주 발생하는 실수입니다.
예외가 발생해도 try-catch로 잡아버리고 throw하지 않으면, 트랜잭션은 롤백되지 않습니다.

@Transactional
public void process() {
    try {
        throw new IllegalStateException("에러 발생");
    } catch (Exception e) {
        // 예외를 삼킴 → 롤백되지 않음
        log.warn("예외 발생: {}", e.getMessage());
    }
}

위 코드에서는 IllegalStateException이 발생했지만, catch 블록에서 처리하고 다시 던지지 않기 때문에 트랜잭션은 커밋됩니다.


💡 트랜잭션 롤백을 강제로 유도하려면?

  1. 예외를 다시 던진다
@Transactional
public void process() {
    try {
        ...
    } catch (RuntimeException e) {
        log.error("에러", e);
        throw e; // 다시 던지면 롤백됨
    }
}
  1. setRollbackOnly()를 명시적으로 호출
import org.springframework.transaction.interceptor.TransactionAspectSupport;

@Transactional
public void process() {
    try {
        ...
    } catch (Exception e) {
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    }
}

🛠️ Checked Exception도 롤백하고 싶다면?

@TransactionalrollbackFor 속성을 사용하면 됩니다.

@Transactional(rollbackFor = ParseException.class)
public void process() throws ParseException {
    throw new ParseException("날짜 파싱 실패", 0);
}

🧱 Spring 외 Java EE 환경에서는?

  • 컨테이너 관리 트랜잭션 (CMT)
    RuntimeException은 기본 롤백.
    Checked Exception@ApplicationException(rollback=true)로 지정 필요.

  • 프로그래밍 방식 트랜잭션 제어 (manual)
    begin() ~ commit() 혹은 rollback() 직접 호출
    → 예외 종류와 관계없이 개발자가 직접 처리


✅ 정리: 실전에서 놓치기 쉬운 트랜잭션 롤백 조건

상황롤백 여부대응 방법
RuntimeException 발생 → 전파✅ 롤백됨기본 동작
Checked Exception 발생❌ 커밋됨rollbackFor 명시 필요
try-catch 후 throw 없음❌ 커밋됨throw하거나 setRollbackOnly() 호출
@Transactional 내부에서 private 메서드 호출❌ 롤백 안 됨AOP 대상은 public 메서드
내부 메서드 호출 (this.method())❌ 프록시 미적용트랜잭션 분리 필요 시 별도 컴포넌트로 분리

📚 참고 자료


✍️ 마무리

트랜잭션의 롤백 기준은 단순히 예외의 종류뿐 아니라, 예외 전파 여부, AOP 적용 범위, 명시적 롤백 처리 여부 등 다양한 요소에 따라 달라집니다.
개발 초기엔 놓치기 쉬운 부분이지만, 실무에선 데이터 무결성과 직결되는 만큼 반드시 정확히 이해하고 있어야 합니다.

예외를 처리한다고 해서 트랜잭션도 자동으로 처리되는 건 아닙니다.
"예외가 트랜잭션을 벗어나야, 트랜잭션도 비로소 반응한다."

profile
알고리즘은 백준 허브를 통해 github에 꾸준히 올리고 있습니다.🙂

0개의 댓글