440. 트랜잭션 (Transaction)과 ACID 특성
⚠️ 이 문서는 "내 통장에서 돈은 빠져나갔는데 친구 통장에 돈이 안 들어오는" 금융 대참사를 막기 위해, 데이터베이스가 여러 개의 명령어를 묶어서 **'반드시 지켜야만 하는 4가지 절대 법칙(ACID)'**을 다룹니다.
핵심 인사이트 (3줄 요약)
- 본질: 트랜잭션은 데이터베이스의 상태를 변화시키는 '논리적인 작업의 최소 단위'다. 하나 이상의 SQL 쿼리로 이루어진다.
- ACID: 트랜잭션이 안전하게 처리되기 위해 DB가 완벽하게 보장해야 하는 4대 특성인 원자성(A), 일관성(C), 고립성(I), 영속성(D)의 약자다. (시험 출제율 100%)
- 제어어 (TCL): 이 트랜잭션의 운명을 결정하는 마법의 스위치가 바로
COMMIT(완벽히 저장)과ROLLBACK(처음으로 취소)이다. (418번 문서 참조)
Ⅰ. 개요: 묶거나, 쪼개거나 (Context & Necessity)
우리가 흔히 말하는 '계좌 이체'라는 업무는 사실 2개의 명령어로 이루어진다.
UPDATE 계좌 SET 잔액 = 잔액 - 10000 WHERE 이름 = '나';UPDATE 계좌 SET 잔액 = 잔액 + 10000 WHERE 이름 = '친구';
만약 1번 명령어를 실행하고 2번을 실행하기 직전에 서버가 벼락을 맞아 꺼진다면? 내 돈 1만 원은 우주 속으로 증발해 버린다.
이런 끔찍한 사태를 막기 위해, 데이터베이스는 1번과 2번 명령어를 하나의 '트랜잭션(Transaction)'이라는 밧줄로 꽁꽁 묶어버린다. 그리고 밧줄 안에 있는 명령어들이 ACID라는 4가지 철칙을 모두 지켰을 때만 현실 세계에 반영(COMMIT)해 준다.
📢 섹션 요약 비유: 트랜잭션은 **'결혼식'**과 같습니다. 신랑이 "네"라고 대답하고 신부도 "네"라고 대답해야만(둘 다 성공) 결혼이 성립됩니다. 한 명이라도 "아니오"라고 하거나 대답 전에 기절해 버리면, 그 결혼식은 아예 없던 일(무효)이 되어버립니다.
Ⅱ. 트랜잭션의 4대 특성 (ACID) ★
정보처리기사뿐만 아니라 모든 백엔드 개발자 면접에서 가장 사랑받는 단골 질문이다. 각 특성이 무너지면 어떤 일이 벌어지는지, 그리고 DB가 그걸 어떻게 막는지(보장 기법) 짝지어서 외워야 한다.
1. Atomicity (원자성) - "모 아니면 도 (All or Nothing)"
- 의미: 트랜잭션 안에 묶인 쿼리들은 모두 다 성공하거나, 아니면 모두 다 실패해야 한다. 절대로 '절반만 성공'하는 일은 없어야 한다.
- 보장 기법: 회복(Recovery) 시스템. 에러가 나면
Undo Log를 보고 쿼리 실행 전으로 완벽하게 되돌려(Rollback) 놓는다. (상세 내용은 441번 문서 참조)
2. Consistency (일관성) - "규칙은 영원하다"
- 의미: 트랜잭션이 성공적으로 끝나면, 데이터베이스는 여전히 내가 정해둔 규칙(무결성 제약 조건)을 100% 만족하는 상태여야 한다.
- 보장 기법: 무결성 제약조건 (Integrity Constraints). 잔고는 0보다 커야 한다는 규칙이 있다면, 이체 후 잔고가 마이너스가 되는 트랜잭션은 강제로 거부된다. (상세 내용은 442번 문서 참조)
3. Isolation (고립성/격리성) - "남의 일에 신경 꺼"
- 의미: 수천 명이 동시에 은행 앱을 켜서 이체를 할 때, A의 트랜잭션과 B의 트랜잭션은 서로가 존재하는지조차 모를 정도로 완벽하게 격리되어야 한다.
- 보장 기법: 병행 제어 (Concurrency Control). 남이 쓰고 있는 데이터에 자물쇠(
Lock)를 걸어서 못 건드리게 한다. (상세 내용은 443번 문서 참조)
4. Durability (영속성/지속성) - "한 번 뱉은 말은 무조건 지킨다"
- 의미: 트랜잭션이 성공(
COMMIT)했다면, 그 직후에 데이터센터에 미사일이 떨어져서 서버가 박살 나더라도 그 결과는 영원히 기록되어야 한다. - 보장 기법: 로깅 (Logging). 디스크의 실제 데이터 파일에 쓰기 전에, 무조건 안전한 로그 파일(
Redo Log)에 먼저 기록(WAL)해 둔다. (상세 내용은 444번 문서 참조)
Ⅲ. 실무 팁: 트랜잭션을 작게 썰어라
초보 개발자들은 "트랜잭션은 안전하니까 많이 묶을수록 좋겠네!"라고 생각하며 코드를 이렇게 짠다.
@Transactional // ❌ 나쁜 예시 (트랜잭션이 너무 긺)
public void buyItem() {
updateInventory(); // 재고 빼기 (0.1초)
processPayment(); // 카드사 결제 (3초)
sendEmail(); // 이메일 발송 (2초)
}
대참사 발생: 카드사 결제를 기다리는 3초 동안, 다른 사용자들은 '재고 테이블'에 접근하지 못하고 무한 대기(Lock)에 빠진다. 쇼핑몰 전체가 마비된다. 정답: 트랜잭션(ACID)은 디스크(DB)를 건드리는 핵심 로직(재고 차감, 주문 기록)에만 짧고 굵게 걸고, 외부 API 호출(결제, 메일)은 트랜잭션 밖으로 빼내야 한다.
Ⅳ. 결론
"ACID는 관계형 데이터베이스(RDB)가 NoSQL을 이길 수 있는 최후의 보루다." 데이터베이스를 평가할 때 "얼마나 빠른가?"보다 1만 배 더 중요한 질문은 "데이터가 꼬이지 않는가?"이다. 이 4가지 원칙(ACID)을 지키기 위해 오라클과 MySQL 같은 엔진들은 내부에 상상을 초월할 정도로 복잡한 잠금(Lock)과 복구(Recovery) 메커니즘을 품고 있다. 속도를 올리기 위해 NoSQL이 일부 포기했던 이 ACID 특성은, 돈과 생명이 오가는 시스템(금융, 의료)에서 결국 RDB로 다시 돌아오게 만드는 대체 불가능한 중력과도 같다.
📌 관련 개념 맵
- 관련 명령어: TCL (COMMIT, ROLLBACK - 418번 문서)
- 대척점 이론: BASE (NoSQL의 특성 - Basically Available, Soft state, Eventual consistency)
- 발전된 아키텍처: 분산 트랜잭션 (Saga Pattern - 550번 문서)
- 보장 기법 핵심 요약: 원자성(회복), 일관성(무결성), 고립성(병행제어), 영속성(로그)
👶 어린이를 위한 3줄 비유 설명
- 트랜잭션은 편의점에서 '과자 집기 $\rightarrow$ 계산하기 $\rightarrow$ 거스름돈 받기'를 하나의 세트로 묶은 거예요.
- 중간에 지진이 나서 정전이 됐다면? 과자를 샀던 건 아예 **없던 일(원자성)**이 되고, 내 용돈의 총합은 **그대로(일관성)**여야 하죠.
- 내가 계산하는 동안 뒤에 줄 선 사람은 조용히 기다려야 하고(고립성), 한 번 영수증을 받았으면 편의점이 망해도 내가 과자를 샀다는 사실은 영원히 변하지 않아요(영속성)!