CAP 정리는 왜 다들 잘못 인용하는가
"CAP 정리 때문에 이렇게 설계했습니다"는 대부분 틀린 말이다
CAP 정리는 시스템 디자인 인터뷰에서 가장 많이 언급되면서 가장 많이 잘못 언급되는 개념입니다. 흔히 "일관성, 가용성, 파티션 허용성 중 두 개만 고를 수 있다"로 요약되는데, 이 요약이 오해를 만듭니다. 파티션(네트워크 분단)은 고르는 게 아닙니다. 분산 시스템이라면 네트워크 파티션은 언젠가 반드시 일어나는 사건이고, CAP 정리는 정확히는 "파티션이 발생했을 때, 일관성과 가용성 중 하나를 포기해야 한다"는 이야기입니다. 평상시에는 셋 다 가질 수 있는 것처럼 보입니다 — 파티션이 없을 때는 이 정리가 아무것도 강제하지 않기 때문입니다.
그래서 "우리는 AP 시스템을 선택했습니다"라는 말은, 정확히는 "네트워크 파티션이 발생한 그 순간에는, 응답을 포기하기보다는 오래된 값이라도 응답을 주는 쪽을 택했습니다"라는 뜻이어야 합니다. 평소 설계 전반을 관통하는 선언이 아니라, 아주 구체적이고 드문 장애 상황에서의 선택입니다. 이걸 모르고 "우리 시스템은 CP입니다"를 시스템 전체의 성격처럼 말하면, 면접관은 파티션이 없는 상황에서의 정합성 얘기와 헷갈리고 있다는 걸 눈치챕니다.
일관성이라는 단어가 최소 세 가지 다른 뜻으로 쓰인다
더 헷갈리는 지점은 "일관성(consistency)"이라는 단어가 CAP 정리, ACID, 그리고 일상적인 "데이터가 다 똑같다"는 의미에서 서로 다르게 쓰인다는 겁니다. ACID의 C는 트랜잭션이 정의된 제약조건(외래키, 유니크 제약 등)을 지킨다는 뜻이고, CAP의 C는 모든 노드가 같은 시점에 같은 데이터를 본다는 뜻입니다. 인터뷰에서 이 둘을 섞어 쓰면 답이 새기 시작합니다. 이 챕터에서 다루는 건 CAP과 분산 시스템 맥락의 일관성입니다.
강한 일관성과 최종 일관성, 실제 체감 차이
# 강한 일관성(linearizable)을 흉내낸 시뮬레이션
# 쓰기가 완료된 이후의 모든 읽기는 반드시 그 값을 본다
class StrongConsistencyStore:
def __init__(self):
self.value = None
self.lock = threading.Lock()
def write(self, v):
with self.lock:
self.value = v # 모든 복제본에 동기 반영 완료 후 리턴한다고 가정
def read(self):
with self.lock:
return self.value # 항상 최신값
# 최종 일관성(eventual consistency)을 흉내낸 시뮬레이션
# 쓰기 직후 일정 시간 동안은 오래된 값이 보일 수 있다
class EventualConsistencyStore:
def __init__(self):
self.primary_value = None
self.replica_value = None # 비동기로 뒤늦게 갱신됨
def write(self, v):
self.primary_value = v
schedule_async(lambda: setattr(self, "replica_value", v), delay_ms=200)
def read_from_replica(self):
return self.replica_value # 최대 200ms 동안 오래된 값 반환 가능강한 일관성을 보장하려면 쓰기가 모든(또는 과반의) 복제본에 반영될 때까지 기다려야 합니다. 그만큼 쓰기 지연시간이 늘어납니다. 최종 일관성은 쓰기를 먼저 확정하고 복제는 뒤따라가게 두므로 빠르지만, 그 사이의 짧은 시간 동안 서로 다른 노드가 다른 값을 보여줄 수 있습니다. 은행 잔고라면 이 틈이 치명적이지만, 게시글의 좋아요 숫자라면 1초 정도 오래된 값이 보여도 아무도 알아채지 못합니다. 어떤 데이터에 어떤 모델을 쓸지는 도메인이 결정하는 것이지, 기술적으로 더 우월한 쪽이 정해져 있는 게 아닙니다.
인터뷰에서 실제로 통하는 답변의 형태
이 개념을 인터뷰에서 잘 써먹는 방법은 정의를 줄줄 외워 말하는 게 아니라, 설계 중인 시스템의 구체적인 데이터에 적용해서 말하는 겁니다. 예를 들어 채팅 시스템을 설계하다가 이렇게 말할 수 있습니다. "메시지 자체는 순서와 전달이 중요하니 강한 일관성에 가깝게 가고 싶습니다. 하지만 읽음 확인 표시는 1~2초 늦게 갱신돼도 사용자 경험에 문제가 없으니, 이 부분은 최종 일관성으로 풀어 쓰기 지연을 줄이겠습니다." 이렇게 시스템 안에서도 데이터마다 다른 일관성 모델을 섞어 쓸 수 있다는 걸 보여주는 답변이, "우리는 CP입니다" 한 문장보다 훨씬 깊이가 있어 보입니다. CAP 정리는 인용하기 위한 이름이 아니라, 데이터마다 다시 던져야 하는 질문이라고 생각하면 이 개념을 오용하지 않게 됩니다.