1. Scalability
- 분산시스템에서 확장성이란 사용자 수나 데이터 양이 증가해도 시스템이 처리할 수 있는 능력을 말합니다.
- 한 명의 사용자를 지원하는 시스템에서 시작해서 몇백만 사용자를 지원하는 시스템을 설계하는 방법을 알아보며 확장성에 대해 알아봅니다.
1.1 시스템 규모 확장 핵심 전략
- 시스템의 확장성을 확보하기 위한 핵심 전략은 다음과 같습니다.
- 웹 계층은 무상태 계층으로 설계
- 모든 계층에 다중화 도입
- 가능한 많은 데이터를 캐시
- 여러 데이터 센터 지원
- 정적 콘텐츠는 CDN을 통해 서비스
- 데이터 계층은 샤딩을 통해 규모 확장
- 각 계층은 독립적 서비스로 분할
- 시스템을 지속적 으로 모니터링하고 자동화 도구 활용
대규모 서비스에서는 단일 서버로 모든 트래픽을 처리할 수 없습니다. 시스템의 확장성을 고려한 설계가 필수적입니다.
2. 규모 확장 방식
2.1 Scale Up (수직적 확장)
- 기존 서버나 장비의 성능을 높여 처리 능력을 향상시키는 방법입니다.
- CPU, 메모리, 인스턴스 유형 업그레이드 등을 통해 처리 능력을 향상시킵니다.
- 수직 확장은 단일 노드 성능을 개선하여 작업량이나 요구 사항이 증가하더라도 정상적으로 이를 처리하는 데 중점을 둡니다.
장점
- 단순성
- 기존 시스템 아키텍처나 소프트웨어에 최소한의 변경만 필요합니다.
- 서버로 유입되는 트래픽의 양이 적을 때 좋은 선택입니다.
- 적은 작업량의 경우 여러 노드 대신 단일 노드에서 충분히 처리가 가능하며 비용 면에서 더 효율적일 수 있습니다.
단점
- 수직적 규모 확장에는 한계가 존재합니다.
- 한 대의 서버에 CPU와 메모리를 무한대로 증설할 방법은 없습니다.
- 자동복구 방안이나 다중화 방안을 제시하지 않습니다.
- 서버에 장애가 발생하면 모든 서비스가 완전히 중단 (SPOF 위험성)
- 고성능 서버로 갈수록 가격이 기하급수적으로 상승합니다.
대규모 서비스에서는 Scale Up의 단점으로 인해 주요 확장 전략으로 사용하지 않습니다. 하드웨어의 물리적 한계와 SPOF 위험성이 큽니다.
2.2 Scale Out (수평적 확장)
- 서버나 장비를 여러 대 추가하여 시스 템의 처리 능력을 향상시키는 방법입니다.
- 인스턴스 수를 증가시켜 수평적 확장을 가능하게 합니다.
- 수평 확장은 여러 노드에 작업을 분산시켜 처리 능력을 향상시키는데 중점을 둡니다.
장점
- 여러 개의 서버를 두어 한 서버에 장애가 발생해도 전체 서비스가 중단되지 않습니다.
- SPOF 위험성이 낮습니다.
- 트래픽 증가에 따라 유연하게 서버 추가 가능합니다.
단점
- 분산 조정
- 여러 노드에 작업을 분산하려면 각 노드가 적절하게 협력하고 동기화할 수 있는 메커니즘이 필요합니다.
- 예를 들어 하나의 노드가 재고 수량을 더하거나 빼는 작업을 할 때 다른 노드도 동시에 이 정보를 공유해야 재고 수량이 일관되게 유지됩니다.
- 데이터 일관성
- 데이터가 여러 노드에 걸쳐 분산되므로 일관성을 유지하는 것이 더 어려워집니다.
- 이를 해결하려면 분산 트랜잭션이나 최종 일관성 같은 기법을 사용해야 합니다.
- Scale Up보다 구현하기 복잡합니다.
- 세션 관리 등 추가 고려사항이 존재합니다.
2.3 함께 사용하기
- Scale Up과 Scale Out 중 반드시 하나만 사용해야 하는 것은 아닙니다.
- 때에 따라서는 두 가지 방법을 함께 사용하여 시스템의 확장성을 확보할 수 있습니다.
3. 웹 계층 확장
3.1 로드밸런서
웹 계층의 수평적 규모 확장을 위해 로드밸런서를 사용합니다.
역할
- 부하 분산 집합에 속한 웹 서버들에게 트래픽을 고르게 분산
- 클라이언트는 로드밸런서를 통해 간접적으로 웹 서버에 접속
- 서버 간 통신에는 사설 IP 주소를 사용하여 보안 강화
가용성 향상
- 부하 분산 집합에 웹 서버를 추가하면 가용성 향상
- 서버 하나가 다운되면 모든 트래픽은 다른 서버로 전송되어 전체 서비스 중단 방지
부하 분산
- 트래픽 증가에 따라 새로운 서버를 부하 분산 집합에 추가 가능
- 로드밸런서가 자동으로 트래픽을 분산하여 각 서버의 부하 균등화
로드밸런서를 도입하면 가용성과 확장성을 동시에 확보할 수 있습니다. 서버 장애 시 자동으로 트래픽을 다른 서버로 전환하고, 필요에 따라 서버를 추가하여 처리 용량을 늘릴 수 있습니다.
3.2 Stateless vs Stateful 아키텍처
- 웹 계층을 수평적으로 확장하기 위해서는 상태 관리 전략이 중요합니다.
Stateless 웹 계층 (무상태)
- 상태 정보(사용자 세션 데이터 등)를 웹 계층에서 제거하고, 관계형 데이터베이스나 NoSQL 같은 지속성 저장소에 보관하는 방식입니다.
- 장점
- 사용자 요청을 어떤 웹 서버로도 전달 가능
- 필요시 공유 저장소에서 상태 정보를 조회
- 서버 추가/제거가 자유로움
- 로드밸런싱이 단순하고 효율적
Stateful 웹 계층 (상태 유지)
- 서버가 클라이언트의 정보(상태)를 유지하여 요청들 사이에 공유하는 방식입니다.
- 단점
- 같 은 클라이언트의 요청은 항상 같은 서버로 전송되어야 함
- 고정 세션(Sticky Session)이 필요하여 로드밸런서에 부담
- 서버 추가/제거가 복잡
- 서버 장애 시 해당 서버의 세션 정보 손실
Stateful 아키텍처는 확장성에 제약이 있습니다. 대규모 서비스에서는 Stateless 아키텍처를 채택하여 수평적 확장을 용이하게 하는 것이 바람직합니다.
4. 데이터 계층 확장
4.1 데이터베이스 다중화
- 웹 계층의 다중화는 로드밸런서를 통해 구현할 수 있습니다.
- 데이터베이스 다중화는 Master-Slave 구조를 통해 구현합니다.
- Master-Slave 구조
- 많은 DBMS는 다중화를 지원하며, 서버 사이에 Master와 Slave 관계를 설정합니다.
- Master (주 데이터베이 스): 데이터 원본을 저장하며 쓰기 연산을 담당
- Slave (부 데이터베이스): Master로부터 사본을 전달받아 읽기 연산을 담당
- 대부분의 애플리케이션은 읽기 연산의 비중이 쓰기 연산보다 훨씬 높기 때문에, Slave 데이터베이스의 수가 Master보다 많습니다.
역할 분담
- Master:
- 쓰기 연산(INSERT, UPDATE, DELETE)을 처리
- 데이터 변경 사항을 Slave에 복제
- Slave:
- 읽기 연산(SELECT)을 처리
- Master로부터 데이터 사본을 전달받아 동기화
장점
- 성능 향상: 읽기와 쓰기 연산이 분리되어 병렬 처리 가능
- 데이터 보존: 자연 재해 등으로 일부 서버가 파괴되어도 데이터 보존
- 가용성 확보: 하나의 서버에 장애가 발생해도 다른 서버에서 서비스 지속
- 장애 대응
- Slave 한 대만 있는데 다운된 경우: 읽기 연산을 한시적으로 Master로 전달
- 여러 Slave 중 하나가 다운된 경우: 다른 Slave로 읽기 연산 분산
- Master가 다운된 경우: 한 대의 Slave를 새로운 Master로 승격하고, 추가 Slave 구성
대부분의 웹 애플리케이션에서 읽기 연산은 쓰기 연산보다 훨씬 많습니다. 이러한 특성을 고려하여 Slave를 여러 대 구성하면 읽기 성능을 크게 향상시킬 수 있습니다.
4.2 데이터베이스 샤딩
- 데이터베이스의 수평적 확장은 샤딩(Sharding)을 통해 구현합니다.
- 샤딩이란?
- 대규모 데이터베이스를 샤드(Shard)라는 작은 단위로 분할하는 기술
- 모든 샤드는 같은 스키마를 사용하지만, 샤드에 보관된 데이터 사이에는 중복이 없음
- 각 샤드는 독립적인 데이터베이스로 동작
- 예시
- 사용자 ID를 기준으로 샤딩하는 경우:
- 샤드 1: 사용자 ID 0-999
- 샤드 2: 사용자 ID 1000-1999
- 샤드 3: 사용자 ID 2000-2999
- 장점
- 데이터를 여러 서버에 분산하여 저장 용량 증가
- 쿼리 부하를 여러 서버에 분산하여 성능 향상
- 데이터베이스 서버 추가로 수평적 확장 가능
- 자세한 내용은 데이터베이스 샤딩 문서를 참고하시기 바랍니다.
실제 운영 환경에서는 샤딩과 Master-Slave 복제를 함께 사용합니다. 각 샤드마다 Master-Slave 구조를 구성하여 가용성과 확장성을 동시에 확보할 수 있습니다.
5. 성능 최적화
5.1 캐시
- 웹 계층과 데이터 계층의 다중화를 통해 가용성과 확장성을 확보했습니다.
- 이제 응답 시간을 개선해야 합니다.
- 캐시의 역할
- 자주 조회되는 데이터를 메모리에 저장
- 데이터베이스 부하 감소
- 응답 시간 대폭 단축
- 캐시 전략과 구현 방법에 대한 자세한 내용은 별도 문서를 참고하시기 바랍니다.
- 자세한 내용은 캐시 문서를 참고하시기 바랍니다.
5.2 CDN (Content Delivery Network)
- 정적 콘텐츠(이미지, CSS, JavaScript 등)를 CDN으로 옮기면 응답 시간을 크게 개선할 수 있습니다.
- CDN의 장점
- 지리적으로 분산된 서버에서 콘텐츠 제공
- 사용자와 가까운 서버에서 콘텐츠 전송
- 원본 서버의 부하 감소
6. 시스템 안정성
6.1 메시지 큐
- 메시지 큐는 메시지의 무손실을 보장하는 비동기 통신을 지원하는 컴포넌트입니다.
- 구성 요소
- 생산자(Producer): 메시지를 만들어 메시지 큐에 발행
- 메시지 큐: 메시지의 버퍼 역할, 비동기적으로 전송
- 소비자(Consumer): 메시지를 받아 해당하는 동작 수행
- 장점
- 서비스 간 결합도가 낮아져 규모 확장성 향상
- 생산자와 소비자가 독립적으로 동작
- 한쪽이 다운되어도 다른 쪽은 정상 동작 가능
- 자세한 내용은 메시지 큐 문서를 참고하시기 바랍니다.
6.2 로그, 메트릭, 자동화
- 소규모 프로젝트에서는 선택사항이지만, 규모가 커지면 필수적입니다.
로그
- 에러 로그 모니터링이 중요합니다.
- 로그 수집 도구를 활용하여 중앙 집중식 관리합니다.
- 편리한 검색과 조회 가능합니다.
메트릭
- 메트릭을 잘 수집하면 시스템 상태를 파악하고 개선점을 찾을 수 있습니다.
- 호스트 단위 메트릭: CPU, 메모리, 디스크 I/O
- 종합 메트릭: 데이터베이스 성능, 캐시 성능
- 핵심 비즈니스 메트릭: 일별 능동 사용자, 수익, 재방문 등
자동화
- 지속적 통합(CI) 도구로 코드 검증 자동화합니다.
- 빌드, 테스트, 배포 자동화합니다.
- 개발 생산성 크게 향상합니다.
대규모 시스템에서는 문제가 발생하기 전에 징후를 파악하는 것이 중요합니다. 체계적인 로그와 메트릭 수집을 통해 사전에 문제를 발견하고 대응할 수 있습니다.
7. 정리
- 대규모 시스템의 확장성을 확보하기 위한 핵심 전략을 정리하면 다음과 같습니다.
계층별 확장 전략
- 웹 계층
- 로드밸런서를 통한 부하 분산
- Stateless 아키텍처로 설계
- 데이터 계층
- Master-Slave 복제를 통한 읽기/쓰기 분산
- 샤딩을 통한 수평적 확장
- 성능 최적화
- 캐시를 통한 응답 시간 단축
- CDN을 통한 정적 콘텐츠 제공
- 안정성 확보
- 메시지 큐를 통한 비동기 처리
- 로그/메트릭 수집 및 자동화
아마존 AWS에는 24TB RAM을 가진 서버도 제공되며, Stack Overflow는 한때 천만 명의 사용자를 단 한 대의 Master 데이터베이스로 처리했습니다. 하지만 대부분의 경우 Scale Out을 통한 수평적 확장이 더 유연하고 비용 효율적입니다.