하나의 논리적 작업 단위
→ 여러 쿼리를 한 덩어리로 묶어 처리하는 것
예) "A가 B에게 5만 원 이체"는
A 잔고 감소
B 잔고 증가 → 둘 다 돼야 의미
| 속성 | 설명 |
|---|---|
| 원자성 (A) | All or Nothing! 쿼리 일부만 반영 ❌ |
| 일관성 (C) | 트랜잭션 전후 DB 상태가 유효해야 함 |
| 격리성 (I) | 동시에 여러 트랜잭션 → 서로 간섭 ❌ |
| 지속성 (D) | 성공된 트랜잭션은 시스템 장애에도 유지 |
| 용어 | 설명 |
|---|---|
| 커밋(commit) | 트랜잭션 결과를 DB에 영구 반영 |
| 롤백(rollback) | 트랜잭션 전 상태로 되돌리기 (오류 발생 시 등) |


@Transactional사용 시 예외 발생 → 자동 롤백
| 격리 수준 | 더티 리드 | 반복불가 조회 | 팬텀 리드 | 설명 |
|---|---|---|---|---|
| READ UNCOMMITTED | ✅ 발생 | ✅ 발생 | ✅ 발생 | 커밋 안 된 데이터도 읽음 (가장 약함) |
| READ COMMITTED | ❌ 차단 | ✅ 발생 | ✅ 발생 | 커밋된 데이터만 읽음 (Oralce 기본) |
| REPEATABLE READ | ❌ 차단 | ❌ 차단 | ✅ 발생 | 같은 행의 데이터 반복 조회 시 일관성 보장 (MySQL 기본) |
| SERIALIZABLE | ❌ 차단 | ❌ 차단 | ❌ 차단 | 가장 엄격한 수준, 동시성 낮지만 모든 현상 차단 |
→ 커밋되지 않은 값을 다른 트랜잭션이 읽는 현상
예) A가 100 → 10으로 수정 중인데 B가 그 10을 먼저 읽음
→ 같은 트랜잭션 안에서 같은 행을 두 번 읽었는데 값이 달라짐
예) A가 조회한 값이 B의 업데이트로 달라짐
→ 같은 조건의 SELECT 결과 행 수가 달라지는 현상
예) A가 “나이 > 20”을 두 번 조회했는데 B가 중간에 INSERT 해서 결과 다름
@Transactional이 붙은 메서드 간 호출 시
트랜잭션을 어떻게 이어갈 것인지 설정하는 방식
| 전파 타입 | 설명 |
|---|---|
REQUIRED (기본값) | 기존 트랜잭션 있으면 참여, 없으면 생성 |
REQUIRES_NEW | 무조건 새 트랜잭션 시작 |
NESTED | 내부에 savepoint 잡고 롤백 가능 (savepoint 수준 rollback) |
@Transactional
public void sendMoney(Long fromId, Long toId, int amount) {
Member from = memberRepository.findById(fromId);
from.withdraw(amount); // 출금
// 예외 발생 가능 구간
Member to = memberRepository.findById(toId);
to.deposit(amount); // 입금
}
중간에 예외 발생 → 둘 다 롤백됨 (원자성 보장)
| 무결성 종류 | 설명 |
|---|---|
| 개체 무결성 | 기본키(Primary Key)는 반드시 NULL이 될 수 없고, 중복 불가 |
| 참조 무결성 | 외래키(Foreign Key)는 참조하는 기본키가 실제로 존재해야 함 |
| 고유 무결성 | 특정 컬럼에 대해 중복 없이 고유한 값만 허용 (UNIQUE 제약조건 등) |
| NULL 무결성 | 특정 컬럼에 대해 NULL 허용 여부를 명시 (NOT NULL 등으로 제한 가능) |
참고: 북스터디 - 면접을 위한 CS 전공지식 노트 (Chapter 4-3)