2단계 커밋(Two-Phase Commit, 2PC)은 여러 데이터베이스나 서비스에 걸친 하나의 트랜잭션을, "전부 커밋"이나 "전부 롤백" 둘 중 하나로만 끝나게 보장하는 분산 커밋 프로토콜입니다. 이름 그대로 준비(prepare)와 커밋(commit)이라는 두 단계로 나뉘고, 이 과정을 지휘하는 코디네이터(coordinator)가 있습니다.
왜 이런 게 필요하냐면, 단일 DB 안에서는 트랜잭션이 원자성을 알아서 보장하지만 여러 시스템에 걸치면 그 보장이 사라지기 때문입니다. A 은행 계좌에서 빼고 B 은행 계좌에 넣는데, 빼기는 성공하고 넣기가 실패하면? 돈이 증발합니다. 2PC는 이 "부분 성공"을 원천 차단하려는 시도입니다.
두 단계가 어떻게 흘러가나
1단계 — 준비(prepare): 코디네이터가 모든 참가자에게 "커밋할 준비 됐어?"라고 묻습니다. 각 참가자는 변경을 로그에 기록하고 락을 잡은 뒤, 커밋을 확실히 할 수 있으면 "예(vote-commit)"라고 답합니다. 이때 참가자는 이후 코디네이터가 어떤 결정을 내리든 따르겠다고 약속한 상태가 됩니다.
2단계 — 커밋/중단(commit/abort): 모두가 "예"라고 하면 코디네이터는 "전부 커밋"을 결정해 통보합니다. 한 명이라도 "아니오"라거나 응답이 없으면 "전부 중단"을 통보합니다. 참가자는 그 결정대로 실제 커밋 또는 롤백을 수행하고 락을 풉니다.
// 코디네이터 관점 (의사코드)
phase1 = [p.prepare(txn) for p in participants]
if all(v == "VOTE_COMMIT" for v in phase1):
decision = "COMMIT"
else:
decision = "ABORT"
log(decision) // 결정을 먼저 기록(중요)
for p in participants:
retry_forever(lambda: p.finish(txn, decision))
핵심은 코디네이터가 결정을 먼저 자기 로그에 남긴 뒤 통보한다는 점입니다. 통보 중에 죽어도, 재시작하면 로그를 보고 같은 결정을 이어서 밀어붙일 수 있어야 하니까요.
2PC의 치명적 약점 — 블로킹
정확해 보이지만, 2PC에는 교과서에서도 강조하는 근본적 결함이 있습니다. 코디네이터가 결정을 내리기 직전이나 통보 도중에 죽으면, "예"라고 답한 참가자들이 무한정 기다리며 락을 쥔 채 멈춥니다. 참가자는 혼자서 커밋할지 중단할지 정할 수 없습니다. 다른 참가자가 이미 커밋했을 수도 있으니까요. 코디네이터가 살아 돌아올 때까지 그저 대기합니다. 이걸 블로킹 문제라고 부릅니다.
2PC는 정합성(consistency)을 위해 가용성(availability)을 희생합니다. 코디네이터라는 단일 실패 지점이 멈추면, 걸려 있던 자원 전체가 함께 멈춥니다. 이 성질 때문에 마이크로서비스 세계에서는 점점 기피됩니다.
여기에 더해, 준비 단계에서 잡은 락이 두 단계 내내 유지되므로 동시성이 크게 떨어지고, 참가자가 늘수록 지연과 실패 확률이 곱으로 커집니다. 그래서 지연에 민감하거나 서비스가 많은 시스템에는 잘 안 맞습니다.
그래서 요즘은 무엇을 쓰나
대안은 상황에 따라 갈립니다.
| 방식 | 일관성 | 특징 |
|---|---|---|
| 2PC | 강한 일관성 | 블로킹, 락 장기 점유 |
| 사가(Saga) | 최종 일관성 | 보상 트랜잭션으로 되돌림 |
| 아웃박스+이벤트 | 최종 일관성 | 비동기, 멱등 소비 필요 |
| 3PC | 강한 일관성 | 비블로킹이나 복잡·현실성 낮음 |
마이크로서비스에서는 강한 일관성을 포기하고 사가 패턴으로 각 단계를 로컬 트랜잭션으로 처리하되, 실패 시 앞선 작업을 되돌리는 보상 트랜잭션을 실행하는 쪽이 대세입니다. 반대로 XA 트랜잭션을 지원하는 전통적 DB·메시지 브로커 조합에서는 여전히 2PC가 쓰입니다. 도구가 코디네이터 복구까지 잘 처리해 준다면, 강한 일관성이 필요한 좁은 범위에는 유효한 선택입니다.
자주 묻는 질문
2PC는 무조건 나쁜 건가요?
아닙니다. 참가자가 적고, 강한 일관성이 반드시 필요하며, 코디네이터 복구가 잘 갖춰진 환경(예: 검증된 XA 트랜잭션 매니저)에서는 합리적입니다. 다만 서비스가 많고 지연·가용성이 중요한 곳에는 부적합합니다.
3단계 커밋(3PC)이 블로킹을 해결하지 않나요?
이론상 준비와 커밋 사이에 단계를 하나 더 둬 블로킹을 완화합니다. 하지만 네트워크 분단 상황에서 안전하지 않을 수 있고 지연이 더 커서, 현실에서는 거의 쓰이지 않습니다.
사가와 2PC는 언제 갈라 쓰나요?
중간 상태가 잠깐 보여도 괜찮고 최종적으로만 맞으면 되는 비즈니스 흐름(주문·결제·배송 등)은 사가가 적합합니다. 어떤 순간에도 부분 상태가 노출되면 안 되는 좁고 강한 요구에는 2PC를 고려합니다.
코디네이터가 죽으면 정말 방법이 없나요?
코디네이터가 결정 로그를 남기고 재시작 후 이어서 통보하면 복구됩니다. 문제는 그 사이 참가자들이 락을 쥔 채 대기한다는 점입니다. 복구가 느리면 그만큼 시스템이 멈추는 것이 2PC의 본질적 한계입니다.

댓글 0