CAP 정리: 통신이 끊긴 두 편에 어떤 응답을 줄 수 있을까
CAP 정리는 네트워크 분할이 발생할 수 있는 분산 읽기·쓰기 저장소에서 선형 일관성과 모든 요청에 대한 가용성을 동시에 보장할 수 없다는 불가능성 결과다. 일관성, 가용성, 분할 허용이라는 세 글자로 유명하지만 단순히 “원하는 두 개를 고른다”는 구호보다 정확한 정의가 중요하다.
CAP는 통신 장애가 있는 실행에서 강한 일관성과 모든 요청의 가용성을 함께 보장할 수 없음을 말한다.
C와 A는 일반적인 홍보 용어가 아니다
여기서 C는 연산들이 실시간 순서를 보존한 하나의 원자적 레지스터처럼 보이는 강한 일관성이다. DB 제약을 만족한다는 ACID의 일관성과 같은 뜻이 아니다. A는 고장 나지 않은 노드가 받은 모든 요청이 결국 유효한 응답을 받는다는 성질이다. 단순한 HTTP 오류 응답이나 대기 화면을 반환하는 것만으로 충족되지 않는다.
P는 노드 그룹 사이 메시지가 전달되지 않는 실행도 고려한다는 조건이다. 분할이 언제 끝날지 모르는 상황에서 양쪽은 상대편의 갱신을 확인할 수 없다. 통신 장애를 현실에서 제거할 수 있다고 가정하지 않는다면 이 상황에 대한 정책이 필요하다.
값 하나로 드러나는 모순
초기 x=0인 사본 A,B의 통신이 끊겼다고 하자. A가 x=1 쓰기에 성공 응답한 뒤 B에서 읽기를 시작한다. 선형 일관성을 지키려면 B는 1을 반환해야 하지만 B는 그 쓰기가 있었는지조차 알 수 없다. A가 2를 쓴 실행과도 구별할 수 없다.
A side: write(x, 1) -> success
X network messages blocked X
B side: read(x) begins after the successful write
Reply from local old state -> may violate consistency.
Wait for remote information indefinitely -> violates availability.
B가 항상 답하도록 하면 어떤 실행에서는 잘못된 값을 반환한다. 정확한 정보를 기다리도록 하면 분할이 지속되는 실행에서 요청이 끝나지 않는다. 이 구별 불가능성이 정리의 핵심이며, CPU나 디스크를 더 빠르게 해도 사라지지 않는다.
설계는 작업별 장애 정책으로 나타난다
강한 일관성을 우선하는 시스템은 충분한 노드와 통신할 수 없는 요청을 거부하거나 기다릴 수 있다. 응답을 우선하는 시스템은 오래된 읽기나 나중의 충돌 병합을 허용할 수 있다. 실제 시스템은 읽기 종류, 키, 지역, 장애 상황에 따라 다른 정책을 선택하기도 한다.
분할이 없는 평상시에도 통신 지연, 복제 거리, 처리량의 절충은 남는다. CAP가 모든 성능 선택을 설명하거나 데이터베이스 제품을 두 글자로 완벽하게 분류하는 것은 아니다. 또한 P를 버린다는 말은 네트워크 분할이 생겨도 마술처럼 통신한다는 뜻이 아니라 그 실행을 보장 범위 밖에 두는 가정이다.
정리를 실무에 적용하려면 무엇이 성공한 쓰기인지, 어떤 읽기가 최신이어야 하는지, 어느 요청이 장애 중 응답해야 하는지를 정한다. 그런 구체적 계약에서 기다림, 거부, 오래된 값, 병합이라는 선택의 효과를 평가할 수 있다.