트랜잭션을 사용하는 이유 : 데이터의 일관성과 무결성을 보장하기 위해서
- 원자성(Atomicity) → 모두 성공하거나 모두 실패해야 한다.
- 일관성(Consistency) → 트랜잭션 전후 데이터가 항상 규칙을 지킨다.
- 격리성(Isolation) → 동시에 실행돼도 서로 간섭하지 않는다.
- 지속성(Durability) → 커밋된 결과는 영구적으로 보존된다.
@Transactional 주요 옵션 총정리
1) propagation (전파 속성)
트랜잭션이 이미 존재할 때, 현재 메서드를 어떻게 실행할지 결정
| 옵션 | 설명 |
| REQUIRED (기본값) | 현재 트랜잭션이 있으면 참여, 없으면 새로 생성 |
| REQUIRES_NEW | 항상 새 트랜잭션 생성, 기존 트랜잭션은 잠시 보류 |
| NESTED | 중첩 트랜잭션 생성, 부모 트랜잭션 안에 별도 저장점(Savepoint) 생성 |
| SUPPORTS | 트랜잭션 있으면 참여, 없으면 트랜잭션 없이 실행 |
| NOT_SUPPORTED | 트랜잭션 없이 실행, 기존 트랜잭션 있으면 잠시 중단 |
| MANDATORY | 반드시 트랜잭션 내에서 실행, 없으면 예외 발생 |
| NEVER | 트랜잭션 있으면 예외 발생, 트랜잭션 없이만 실행 가능 |
2) isolation (격리 수준)
동시성 문제 제어 — 잘못된 읽기 방지
| 옵션 | 설명 |
| DEFAULT | DB 기본 설정 따름 |
| READ_UNCOMMITTED | 다른 트랜잭션의 미완료 데이터도 읽기 가능 (가장 약함) |
| READ_COMMITTED | 커밋된 데이터만 읽기 가능 (기본값인 경우 많음) |
| REPEATABLE_READ | 트랜잭션 내 같은 데이터 반복 조회 시 값 고정 |
| SERIALIZABLE | 가장 엄격, 완전한 순차 처리 보장, 성능 저하 가능 |
cf. 트랜잭션 격리 수준 별 이상 현상 발생 여부
1) 트랜잭션 이상 현상(Anomaly) 용어
용어 뜻 문제 상황 더티 리드 커밋되지 않은 타인의 수정 데이터를 읽음 (롤백 가능성 있음) 값 변경 중에 읽었는데 롤백 노 리피트블 리드 한 트랜잭션 내에서 같은 데이터를 두 번 읽는데 값이 다름 값을 읽는 사이에 값 변경 팬텀 리드 한 트랜잭션 내에서 같은 조건 조회인데 행(ROW) 개수가 바뀜 값을 읽는 사이에 열 추가 or 삭제
2) 트랜잭션 격리 수준 요약
격리 수준 더티 리드 노 리피트블 리드 리드 팬텀 리드 실무 사용도 특징 READ_UNCOMMITTED 발생함 발생함 발생함 거의 안 씀 가장 약함, 신뢰도 낮음 READ_COMMITTED 차단 발생함 발생함 기본값인 경우 많음 커밋된 데이터만 읽기 REPEATABLE_READ 차단 차단 발생함 중요 트랜잭션에 사용 같은 데이터 재조회 값 고정 SERIALIZABLE 완전 차단 완전 차단 완전 차단 성능 이슈로 제한적 가장 엄격, 완벽한 고립 보장
3) rollbackFor / noRollbackFor
특정 예외 발생 시 롤백 여부 설정
@Transactional(rollbackFor = Exception.class)
- Exception 발생 시 롤백하도록 설정
cf.
❓ 예외가 발생하면 롤백하는게 기본 설정 아닌가?
@Transactional의 기본 롤백 기준
→ RuntimeException 또는 그 하위 예외 발생 시 롤백됨
자바 예외 (Throwable) 계층 구조
Throwable ├── Error → 시스템 치명적 오류 (OutOfMemoryError 등) └── Exception ├── RuntimeException → 실행 시 발생, 예외처리 선택 (Unchecked Exception) └── (그 외) → 컴파일 강제 예외처리 필요 (Checked Exception)@Transaction의 기본 롤백 기준이 RuntimeException이다.
❓ 이때 든 의문점
RuntimeException(Unchecked Exception)이 아닌 예외는 Checked Exception이며,
Checked Exception은 컴파일 시점에서 걸리게 된다고 생각했다.
그렇다면 정상 실행된 서버에서 Checked Exception이 발생되는 경우가 있나?
✔️ 결론
정상적으로 실행되는 서버에서 checked exception이 발생할 수 있는 상황은 충분히 있다.
주로 외부 환경 요인 에서 비롯된다:
이러한 예외들은 대부분 Checked Exception 이기 때문에 기본 설정인 @Transactional로는 자동 롤백되지 않는다.
- 파일 입출력 중 (IOException)
- 네트워크 요청 중 (TimeoutException) (Checked 타입일 경우)
- DB 연결 중 (SQLException) 등
❓ 예외가 발생했는데 롤백을 하지 않는 상황도 있을까?
대표적으로 사용자 입력 오류 같은 경우에는 예외가 발생해도 롤백하지 않고 데이터를 유지하는 게 더 나은 선택일 수 있다.
사용자 입력 오류 등에서 롤백하지 않는 이유
- 트랜잭션 내 일부 작업이 사용자 실수로 실패했더라도,
그 전까지 정상 처리된 데이터는 저장되어야 할 가치가 있음- 전체 트랜잭션을 롤백하면
정상적인 데이터까지 사라지고, 사용자 경험이 나빠질 수 있음- 예외 상황(오류)은 별도로 처리하고,
성공한 작업은 그대로 커밋하는 것이 더 효과적임
e.g. 사용자가 주문을 진행 중: 물건을 담고 → 할인 쿠폰 입력 시 오류 발생
- 이 경우 할인 쿠폰 적용만 실패했을 뿐 주문 자체는 유효하므로 롤백할 이유가 없음
- 트랜잭션 전체를 롤백하면 물건 담은 정보도 사라짐
→ 사용자 입장에서 처음부터 다시 주문해야 하는 불편함 발생
4) timeout
트랜잭션 최대 수행 시간 (초 단위)
@Transactional(timeout = 5)
- 5초 넘으면 트랜잭션 강제 종료
5) readOnly
조회 전용 트랜잭션 (쓰기 금지)
@Transactional(readOnly = true)
- 성능 최적화에 도움, 쓰기 시도하면 예외 발생할 수도 있음
'Spring' 카테고리의 다른 글
| [Spring] Specification vs QueryDSL (0) | 2025.06.26 |
|---|---|
| [Spring] JPA 엔티티 설정 & 관계 매핑 심화 (0) | 2025.06.25 |
| [Spring] Filter vs Interceptor vs AOP (0) | 2025.06.24 |
| [Spring] Service와 Controller 통합 테스트 (0) | 2025.06.12 |
| [Spring] H2 In-Memory DB를 활용한 Repository 테스트 (2) | 2025.06.04 |