본문 바로가기
Dev/Computer Science

[CS] 트랜잭션 예외 처리 정리 | Checked Exception, Unchecked Exception

by 컴포넌트설계자 2025. 9. 11.

Spring 트랜잭션 예외 처리 정리

1. 기본 동작

  • Checked Exception
    • 발생해도 기본적으로 롤백하지 않음
    • 컴파일 시점에 예외 처리를 강제하는 정상 예외 상황으로 간주
  • Unchecked Exception (RuntimeException, Error)
    • 발생 시 자동 롤백
    • 보통 프로그래머의 실수나 시스템 오류 상황으로 간주
    • Spring은 JDBC, JPA, Hibernate 예외를 DataAccessException (Unchecked) 으로 변환해 일관 처리

2. 설정 확장 (@Transactional 속성)

  • rollbackFor : 특정 Checked Exception도 롤백하도록 지정
  • noRollbackFor : 특정 Unchecked Exception에 대해 롤백 제외 가능

3. Java EE와 비교

  • CMT (컨테이너 관리 트랜잭션)
    • RuntimeException → 자동 롤백
    • CheckedException → 기본 롤백 없음 (@ApplicationException(rollback=true) 필요)
  • 프로그래밍 방식 트랜잭션
    • 개발자가 commit(), rollback() 직접 호출해야 함

entity

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;

@Entity
@Getter @Setter
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
}

 

Repository

import org.springframework.data.jpa.repository.JpaRepository;

public interface MemberRepository extends JpaRepository<Member, Long> {
}

Service

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class MemberService {

    private final MemberRepository memberRepository;

    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

    // 기본: RuntimeException -> 롤백됨
    @Transactional
    public void uncheckedExample() {
        Member m = new Member();
        m.setName("Runtime 예외");
        memberRepository.save(m);

        throw new RuntimeException("RuntimeException 발생 -> 롤백됨");
    }

    // 기본: CheckedException -> 롤백 안 됨
    @Transactional
    public void checkedExample() throws Exception {
        Member m = new Member();
        m.setName("Checked 예외");
        memberRepository.save(m);

        throw new Exception("CheckedException 발생 -> 롤백 안 됨");
    }

    // rollbackFor 설정: CheckedException도 롤백
    @Transactional(rollbackFor = Exception.class)
    public void rollbackForCheckedExample() throws Exception {
        Member m = new Member();
        m.setName("Checked 예외 롤백For");
        memberRepository.save(m);

        throw new Exception("CheckedException 발생 + rollbackFor -> 롤백됨");
    }

    // noRollbackFor 설정: RuntimeException도 롤백 안 함
    @Transactional(noRollbackFor = RuntimeException.class)
    public void noRollbackForRuntimeExample() {
        Member m = new Member();
        m.setName("Runtime 예외 noRollbackFor");
        memberRepository.save(m);

        throw new RuntimeException("RuntimeException 발생 + noRollbackFor -> 롤백 안 됨");
    }
}

Test.java

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class MemberServiceTest {

    @Autowired
    MemberService memberService;

    @Autowired
    MemberRepository memberRepository;

    @Test
    void testUnchecked() {
        try {
            memberService.uncheckedExample();
        } catch (RuntimeException e) {
            System.out.println(">>> member count = " + memberRepository.count()); 
            // 0 (롤백됨)
        }
    }

    @Test
    void testChecked() {
        try {
            memberService.checkedExample();
        } catch (Exception e) {
            System.out.println(">>> member count = " + memberRepository.count()); 
            // 1 (롤백 안 됨)
        }
    }

    @Test
    void testRollbackFor() {
        try {
            memberService.rollbackForCheckedExample();
        } catch (Exception e) {
            System.out.println(">>> member count = " + memberRepository.count()); 
            // 0 (롤백됨)
        }
    }

    @Test
    void testNoRollbackFor() {
        try {
            memberService.noRollbackForRuntimeExample();
        } catch (RuntimeException e) {
            System.out.println(">>> member count = " + memberRepository.count()); 
            // 1 (롤백 안 됨)
        }
    }
}

 

5. 테스트 결과 요약

상황기본 동작DB 반영 여부
RuntimeException 발생 자동 롤백 저장 안 됨
CheckedException 발생 롤백 안 함 저장됨
CheckedException + rollbackFor 롤백 강제 저장 안 됨
RuntimeException + noRollbackFor 롤백 제외 저장됨