분산 데이터 저장소를 고를 때마다 "이건 CA 시스템", "저건 AP 시스템" 같은 말을 듣는다. 처음엔 CAP의 세 글자 중 둘을 고르면 된다는 식으로 외웠는데, 막상 실무에서 "그래서 평소에 지연이 더 중요하면 뭘 봐야 하나"라는 질문에는 CAP만으로 답이 안 나왔다. 네트워크가 멀쩡한 99%의 시간 동안의 트레이드오프는 CAP가 아예 말해주지 않기 때문이다.
이 글에서 정리하려는 것은 두 가지다. 첫째, CAP가 실제로 주장하는 바가 흔히 외우는 "셋 중 둘"과 어떻게 다른가. 둘째, 그 빈틈을 메우는 PACELC가 무엇을 추가로 말해주는가. 출처는 주로 Designing Data-Intensive Applications(이하 DDIA) 9장과 Daniel Abadi의 PACELC 논문(2012)이다.
CAP는 Eric Brewer가 2000년 발표하고 이후 정식화된 정리로, 세 글자는 각각 이렇게 정의된다.
DDIA 9장은 "Consistency, Availability, Partition tolerance: 셋 중 둘을 고르라"는 흔한 요약이 오해를 부른다고 분명히 지적한다. 이유는 P가 선택지가 아니기 때문이다. 네트워크 분할은 우리가 "선택"해서 피할 수 있는 게 아니라 언젠가 반드시 발생하는 현실이다. 분할이 일어나지 않는다면 C와 A를 동시에 누리면 되므로, 애초에 트레이드오프가 발생하지 않는다.
그래서 CAP를 정확히 다시 읽으면 이렇게 된다.
네트워크 분할(P)이 발생한 그 순간, 시스템은 일관성(C)과 가용성(A) 중 하나를 포기해야 한다.
분할이 생기면 양쪽으로 갈라진 노드들은 서로의 쓰기를 볼 수 없다. 이때 선택지는 둘뿐이다. (a) 갈라진 쪽의 요청을 거부하거나 에러를 내서 일관성을 지키거나(C 선택, A 포기), (b) 일단 받아주되 사본 간 값이 달라질 위험을 감수하거나(A 선택, C 포기). DDIA는 그래서 CAP가 실용적으로는 "분할 시 C냐 A냐" 한 가지 선택만 말해준다고 정리한다.
흔히 말하는 "CA 시스템"(분할 내성을 포기한 시스템)이라는 분류가 애매한 것도 이 때문이다. 네트워크 분할이 일어나는 환경에서 P를 포기한다는 건 사실상 "분할이 나면 그냥 깨진다"는 뜻에 가깝다.
CAP의 가장 큰 빈틈은 분할이 없는 평상시를 다루지 않는다는 점이다. 실제 운영에서 네트워크 분할은 드물고, 시스템은 대부분의 시간을 정상 상태로 보낸다. 그 평상시에도 분산 복제 시스템은 또 다른 트레이드오프를 안고 있다 — 지연(latency) 대 일관성(consistency)이다.
Daniel Abadi가 2010년 제안하고 2012년 논문으로 정리한 PACELC가 이 부분을 채운다. 이름 자체가 조건문이다.
if (P) then A or C, else (E) then L or C
읽으면 이렇다. 분할(P)이 있으면 가용성(A)과 일관성(C) 사이에서 고르고(이건 CAP와 같다), 그렇지 않으면(Else) 지연(L)과 일관성(C) 사이에서 고른다.
평상시 L 대 C 트레이드오프가 왜 생기는지는 복제 구조를 떠올리면 명확하다. 강한 일관성을 보장하려면 쓰기를 여러 복제본에 동기적으로 반영하고 확인을 받아야 한다. 그만큼 응답이 느려진다(L 포기, C 유지). 반대로 일부 복제본에만 쓰고 바로 응답하면 빠르지만, 다른 복제본은 아직 옛 값을 들고 있을 수 있다(C 포기, L 유지). 분할이 전혀 없어도 이 선택은 사라지지 않는다.
PACELC를 외울 때 핵심은, CAP의 "C"와 ELC의 "C"가 가리키는 일관성의 결이 조금 다르다는 점이다. 앞쪽(PAC)의 C는 CAP에서처럼 강한 일관성을, 뒤쪽(ELC)의 C는 "지연을 더 쓰더라도 복제본을 얼마나 맞출 것인가"라는 정도의 문제로 이해하면 헷갈리지 않는다.
Abadi의 논문은 실제 시스템들을 PACELC 조합으로 분류한다. 표로 정리하면 평상시·분할 시 성향이 한눈에 들어온다. (아래 분류는 논문과 DDIA에서 언급된 일반적 성향이며, 시스템 설정에 따라 달라질 수 있다.)
| 분류 | 분할 시(PA/PC) | 평상시(EL/EC) | 대표 예시(알려진 바로는) |
|---|---|---|---|
| PA/EL | 가용성 우선 | 지연 우선 | Dynamo 계열, Cassandra, Riak |
| PC/EC | 일관성 우선 | 일관성 우선 | VoltDB/H-Store, 전통적 ACID RDB |
| PA/EC | 가용성 우선 | 일관성 우선 | (드묾) |
| PC/EL | 일관성 우선 | 지연 우선 | Yahoo PNUTS, 일부 설정의 MongoDB |
가장 흔한 두 극단은 PA/EL과 PC/EC다.
흥미로운 건 PC/EL이다. 분할이 나면 일관성을 지키지만(PC), 평상시에는 지연을 줄이기 위해 일관성을 살짝 양보한다(EL). Yahoo의 PNUTS가 이 조합으로 자주 인용된다고 알려져 있다. "평소엔 빠르게, 위기엔 보수적으로"라는 운영 철학이 읽힌다.
핵심을 한 줄로 줄이면 이렇다.
CAP는 분할이 났을 때 C와 A 중 하나를 고르라고만 말한다. PACELC는 거기에 분할이 없는 평상시 L과 C의 트레이드오프를 더해, 시스템의 성향을 두 축으로 본다.
실무에서 데이터 저장소를 고를 때 "이건 AP다"에서 멈추지 말고, "그래서 평상시엔 지연을 줄이려 일관성을 양보하나(EL), 아니면 끝까지 일관성을 지키나(EC)"까지 물어보면 선택의 해상도가 올라간다. CAP의 "셋 중 둘"이라는 요약은 편하지만, DDIA의 표현을 빌리면 그건 시스템을 분류하는 도구로 쓰기엔 너무 거칠다.
다음에 더 파고들 만한 주제는 두 가지다. 첫째, ELC의 C를 더 세분화하는 일관성 모델 스펙트럼(선형화 → 인과적 일관성 → 결과적 일관성). 둘째, Cassandra의 tunable consistency가 실제 quorum 설정(R + W > N)으로 어떻게 PACELC 위치를 바꾸는지.