//
요즘 개발자를 위한 시스템 설계 수업 · 디렌드라 신하, 테자스 초프라
2장은 호텔 객실 예약 시스템이라는 구체적인 예시로 문을 연다. 예약 데이터를 여러 레플리카에 나누어 저장할 때, 쓰기와 읽기를 어떤 방식으로 처리할 수 있는지 옵션을 늘어놓는 방식이다.
데이터 쓰기 옵션
| 방식 | 설명 |
|---|---|
| 직렬 동기 쓰기 | 레플리카에 순차적으로 쓰고 각 응답을 기다린다 |
| 직렬 비동기 쓰기 | 순차적으로 쓰지만 응답을 기다리지 않는다 |
| 병렬 비동기 쓰기 | 모든 레플리카에 동시에 쓰고 응답을 기다리지 않는다 |
| 메시징 서비스에 쓰기 | 카프카 같은 큐에 먼저 쓰고 소비자가 각 저장소에 반영한다 |
데이터 읽기 옵션
이 두 목록을 나란히 놓고 보면, 분산 시스템 설계가 왜 "정답 고르기"가 아니라 "저울질"인지 바로 드러난다. 직렬 동기 쓰기는 일관성이 가장 강하지만 가장 느리고, 병렬 비동기 쓰기는 가장 빠르지만 일부 레플리카가 뒤처질 수 있다. 읽기 쪽도 같다. 하나의 레플리카만 읽으면 빠르지만 오래된 값을 볼 수 있고, 모든 레플리카를 읽으면 정확하지만 느리다.
읽기 레플리카 수 R, 쓰기 레플리카 수 W, 전체 레플리카 수 N 사이에 R + W > N이 성립하면 읽기가 반드시 최신 쓰기를 본다. 이것이 쿼럼(Quorum) 조건이며, 5장의 키-값 저장소 설계에서 다시 등장한다.
이어서 책은 분산 시스템을 평가하는 축을 하나씩 짚어 나간다.
여러 노드에 데이터가 복제되고 분산되어 있더라도 시스템 내 모든 노드가 항상 동일한 상태나 데이터를 참조하도록 하는 개념이다. 책은 두 단계로 나눈다.
강한 일관성(Strong Consistency) 은 모든 노드가 데이터 업데이트를 동일한 순서로 처리하도록 보장한다. 구현 수단으로 분산 트랜잭션과 분산 잠금이 있고, 더 근본적으로는 팩소스(Paxos)나 래프트(Raft) 같은 합의 알고리즘을 적용한다. 은행처럼 민감한 데이터를 다루는 서비스가 여기에 해당한다.
최종 일관성(Eventual Consistency) 은 일시적인 데이터 불일치를 허용하되, 시간이 지나면 모든 레플리카가 결국 동일한 상태에 도달하도록 보장한다. 불일치를 해소하는 기법으로 충돌 해결(Conflict Resolution), 데이터 복제(Replication), 가십 프로토콜(Gossip Protocol)이 쓰인다.
장애나 오류가 발생하더라도 사용자에게 서비스를 지속적으로 제공할 수 있는 능력이다. 내부에서 무슨 일이 벌어지든 사용자 눈에는 정상으로 보이게 만드는 것이 목표다.
복제 방식의 두 갈래를 구분해 둘 만하다. 액티브-패시브는 한 노드를 주 노드로 쓰고 나머지를 백업으로 두는 구성이고, 액티브-액티브는 여러 노드가 동시에 요청을 처리하는 구성이다. 전자는 단순하지만 백업 노드의 자원이 놀고, 후자는 자원을 다 쓰지만 노드 간 조정이 필요하다.
네트워크 파티션(Network Partition) 은 네트워크 장애로 일부 노드가 시스템의 다른 부분과 연결이 끊겨 서로 접근하거나 데이터를 주고받지 못하는 상태다. 파티션 허용성(Partition Tolerance) 은 그런 상황에서도 시스템이 계속 정상적으로 작동할 수 있는 능력이다.
클라우드 컴퓨팅, 분산 데이터베이스, 대규모 분산 애플리케이션처럼 가용성이 중요한 환경에서는 파티션이 "발생할 수도 있는 일"이 아니라 "언젠가 반드시 발생하는 일"이므로, 파티션 허용성은 선택 사항이 아니다. 이 전제가 다음 장 CAP 정리의 출발점이 된다.
요청이 들어와 응답이 돌아오기까지 걸리는 시간이다. 책은 줄이는 방법을 다섯 가지로 정리한다.
| 기법 | 내용 |
|---|---|
| 네트워크 최적화 | 빠른 연결, 네트워크 홉 수 줄이기, 혼잡도 최소화 |
| 캐싱 | 메모리 캐싱, CDN, 데이터베이스 캐싱 |
| 데이터 지역화 | 데이터 복제, 엣지 컴퓨팅, 콘텐츠 분산 전략 |
| 비동기 통신 | 메시지 큐, 이벤트 기반 아키텍처로 결합도를 낮추고 논블로킹 처리 |
| 성능 튜닝 | 시스템 설정 조정, 쿼리 최적화, 알고리즘 및 코드 실행 방식 개선 |
세 속성은 비슷해 보이지만 관심의 초점이 다르다.
여기서 책이 짚는 중요한 연결점이 있다. 내구성을 높이면 일관성 유지에 시간이 더 걸린다. 데이터를 여러 곳에 복제해야 하므로, 복제가 끝나기 전까지는 레플리카 사이에 불일치가 존재한다. 세 속성은 독립적으로 최대화할 수 있는 값이 아니다.
사용자 수나 데이터양이 증가해도 성능과 신뢰성을 유지하면서 더 많은 작업을 처리할 수 있는 능력이다. 두 방향이 있다.
| 수직 확장(Scale Up) | 수평 확장(Scale Out) | |
|---|---|---|
| 방식 | 장비 한 대의 성능을 높인다 | 장비 수를 늘린다 |
| 장점 | 아키텍처 변경 최소, 소규모에서 비용 효율적 | 용량·성능 증가, 장애 허용성 확보 |
| 단점 | 하드웨어 한계, 단일 장애점 | 노드 간 동기화 필요, 데이터 일관성 유지가 어려움 |
수직 확장의 단점 두 가지는 성격이 다르다. 하드웨어 한계는 돈으로 해결할 수 없는 물리적 상한이고, 단일 장애점(Single Point of Failure)은 그 한 대가 죽으면 서비스가 멈춘다는 구조적 문제다. 반대로 수평 확장의 단점은 둘 다 조정 비용으로 요약된다. 노드가 늘어날수록 노드 사이를 맞추는 일이 어려워진다.
실무에서는 이분법이 아니라 순서 문제로 접근하는 편이 낫다. 초기에는 수직 확장이 압도적으로 저렴하고 빠르다. 수평 확장은 트래픽이 실제로 한 대의 한계에 근접할 때, 혹은 단일 장애점을 없애야 할 때 도입한다. 다만 처음부터 상태를 서버 밖으로 빼두면(무상태 설계) 나중에 수평 확장으로 옮겨 갈 때의 비용이 크게 줄어든다.
2장은 일관성, 가용성, 파티션 허용성, 지연 시간, 내구성, 신뢰성, 장애 허용성, 확장성이라는 축을 하나씩 정의하는 장이다. 개별 정의는 익숙한 내용이지만, 한자리에 모아 놓고 보면 이 속성들이 서로 당기고 밀어내는 관계라는 점이 선명해진다.
내구성을 높이면 일관성 비용이 오르고, 가용성을 높이려 복제를 늘리면 다시 일관성이 흔들린다. 확장성을 위해 수평으로 늘리면 조정 비용이 늘어난다. 결국 설계란 이 축들 사이에서 어느 지점에 서겠다고 명시적으로 결정하는 일이다. 그 결정 구조를 정리해 주는 것이 다음 장의 CAP 정리와 PACELC 정리다.
이 글이 도움이 되셨나요?