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 | 롤백 제외 | 저장됨 |
'Dev > Computer Science' 카테고리의 다른 글
| [CS] JAVA React DB 면접질문 답 리스트 (0) | 2026.04.16 |
|---|---|
| [CS] 프로그래밍 기본 개념 시험문제 요약 (0) | 2026.04.16 |
| [CS] 낙관적 락, 비관적 락 - 동시성 제어 주요기법 (0) | 2025.08.20 |
| [CS] RestfulAPI 설계와 적용방법 알아보기 (2) | 2025.08.05 |
| [CS] 회선(서킷) 교환 방식 VS 패킷 교환 방식 (0) | 2025.07.27 |