당장은 노드마다 값이 다를 수 있지만, 갱신이 멈추면 결국 모두 같아진다는 보장 (eventual consistency).
무엇을 보장하고 무엇을 보장하지 않나
보장하는 것 : 새 쓰기가 없으면 언젠가 모든 복제본이 같아진다 보장 안 하는 것 : "언젠가"가 언제인지. 그 사이에 무엇을 읽을지
이 느슨함이 성능과 가용성을 준다.
강한 일관성과의 대비
강한 일관성 (strong) 쓰기 완료 → 이후 모든 읽기가 새 값을 본다
- 복제본 확인을 기다려야 하므로 느리다
최종 일관성 (eventual) 쓰기 완료 → 일부 노드는 아직 옛 값
- 기다리지 않으므로 빠르다
실제로 겪는 문제들
글 작성 → 목록에 안 보임 (내가 쓴 걸 내가 못 봄) 좋아요 → 숫자가 안 변함 → 새로고침하니 변함
- 주문 완료 → 주문 목록에 없음 — → 잠시 후 나타남
사용자는 이것을 "버그"로 인식한다. 기술적으로는 정상 동작이지만 사용자 경험으로는 실패다. 그래서 완화 장치가 필요하다.
중간 단계의 보장들 — 실무의 핵심
"강한 일관성 아니면 최종 일관성"의 이분법이 아니다.
| 보장 | 내용 | 구현 |
|---|---|---|
| read-your-writes | 내가 쓴 것은 내가 반드시 본다 | 쓴 직후 N초는 리더에서 읽기 |
| monotonic reads | 한 번 본 값이 되돌아가지 않는다 | 같은 사용자를 같은 복제본에 고정 |
| consistent prefix | 인과 순서가 뒤집히지 않는다 | 순서 보존 복제 |
| bounded staleness | 최대 N초까지만 뒤처진다 | 지연 모니터링 + 라우팅 |
read-your-writes만 해결해도 체감 문제의 대부분이 사라진다. 사용자는 남의 데이터가 조금 늦는 것은 잘 눈치채지 못하지만, 자기 행동의 결과가 안 보이면 즉시 알아챈다.
monotonic reads가 없으면 — 시간이 거꾸로 간다
새로고침 1 → 복제본 A(최신) → 댓글 10개
- 새로고침 2 → 복제본 B(뒤처짐) → 댓글 8개 — ← 댓글이 사라졌다! 새로고침 3 → 복제본 A → 다시 10개
값이 왔다 갔다 하는 것은 단순히 늦는 것보다 훨씬 나쁘게 느껴진다. 같은 사용자를 같은 복제본으로 고정하면 해결된다.
충돌 해결
여러 곳에서 동시에 다른 값을 쓰면 합칠 때 충돌한다.
| 방법 | 내용 | 문제 |
|---|---|---|
| LWW (Last Write Wins) | 타임스탬프가 늦은 쪽 채택 | 한쪽 쓰기가 조용히 사라진다. 시계 동기화에도 의존 |
| 벡터 시계 | 인과 관계를 추적해 진짜 충돌만 골라냄 | 메타데이터가 커짐 |
| CRDT | 자료구조 자체가 합치기 가능하게 설계됨 | 표현 가능한 타입이 제한적 |
| 애플리케이션 병합 | 도메인 지식으로 결정 | 구현 부담 |
CRDT의 예 — 카운터를 "노드별 증가량의 합"으로 표현하면 어느 순서로 합쳐도 결과가 같다. 공동 편집 문서가 이 원리로 동작한다.
UI 차원의 대응 — 종종 최선의 해법
- 낙관적 UI — : 서버 응답 전에 화면을 먼저 갱신
- (좋아요를 누르면 즉시 하트가 채워진다)
- 상태 표시 — : "처리 중입니다" 로 최종 일관성을 드러낸다
- 폴링·푸시 — : 완료되면 알려 준다
기술로 못 없애면 UX로 감싼다. 이 판단을 말할 수 있으면 좋은 답변이다.