데이터베이스 엔지니어링 마스터 노트 시리즈 4편. 단일 DB 한계와 샤딩의 등장, 파티셔닝 vs 샤딩의 결정적 차이, Range·Hash·Geographic 샤딩 3전략, Consistent Hashing이 노드 추가에서 빛나는 이유, Cross-Shard JOIN 함정, Resharding의 어려움, 언제 샤딩해야 하는가까지.
이 글은 데이터베이스 엔지니어링 마스터 노트 시리즈의 네 번째 편입니다. 3편(파티셔닝)이 단일 DB 안 분할이었다면, 이번엔 여러 서버로 분산 — 샤딩.
수억·수십억 사용자 = 단일 DB 한계 도달. 샤딩 = 마지막 수평 확장 카드. 다만 샤딩은 비싼 결정 — 잘못 선택하면 운영 지옥. 언제·어떻게가 핵심.
샤딩이란?
데이터를 여러 DB 인스턴스(샤드)에 분산.
거대한 users 테이블 (10억 행, 단일 DB)
↓ 샤딩
shard1 (1~10억): users (1~3억)
shard2 (2~10억): users (3억~6억)
shard3 (3~10억): users (6억~10억)
각 샤드 = 별도 DB 서버
각 샤드는 자체 PostgreSQL·MySQL 같은 완전한 DB. 애플리케이션이 어느 샤드에 갈지 결정.
전통 DB의 한계
단일 노드 한계
CPU = 32~96 코어 한계
RAM = 1~6TB 한계
Storage = 수십 TB 한계
연결 = 수만 동시 연결 한계
처리량 = 수만 QPS 한계
이 한계 도달 = 수직 확장(더 큰 서버) 비용 폭발.
샤딩의 등장
샤드 1 → 32 코어 / 256GB RAM
샤드 2 → 32 코어 / 256GB RAM
샤드 3 → 32 코어 / 256GB RAM
샤드 4 → 32 코어 / 256GB RAM
= 합계 128 코어 / 1TB RAM
수평 확장 = 이론상 무제한.
파티셔닝 vs 샤딩 — 결정적 차이
| 구분 | Partitioning | Sharding |
|---|---|---|
| 범위 | 단일 DB 안 | 여러 DB 서버 |
| 투명성 | DBMS 자동 처리 | 애플리케이션 라우팅 |
| 관리 | 단일 DB 관리 | 분산 관리 |
| Join | 모든 파티션 가능 | Cross-Shard JOIN 어려움 |
| 트랜잭션 | 보통 ACID | 분산 트랜잭션 복잡 |
| 적합 | 단일 노드 한계 내 | 단일 노드 초과 |
여기서 정말 중요한 시험 함정 — 샤딩은 ACID 보장 어려움. Cross-Shard 트랜잭션은 2PC(Two-Phase Commit) 필요. 성능 큰 비용. 8편(고급)에서 자세히.
샤딩 전략 3가지
1. Range Sharding
shard1: user_id 1~1000만
shard2: user_id 1000만~2000만
shard3: user_id 2000만~3000만
장점 — 범위 쿼리 한 샤드만.
단점 — Hot Spot 위험. 신규 사용자가 shard3에 몰림.
2. Hash Sharding
shard_id = hash(user_id) % N
장점 — 균등 분산, hot spot 회피.
단점 — 범위 쿼리 모든 샤드 스캔 필요.
여기서 정말 중요한 시험 함정 — 단순 modulo 해시는 Resharding 지옥. 노드 1개 추가 시 거의 모든 데이터 재배치 필요. 해결 = Consistent Hashing.
3. Geographic / Directory Sharding
shard_kr: 한국 사용자
shard_us: 미국 사용자
shard_eu: 유럽 사용자
또는 Directory Service 사용 — 별도 매핑 테이블에 "user_id → shard_id" 저장.
장점 — 유연. 단점 — Directory가 SPOF·병목.
Consistent Hashing — 노드 변경에 강건
단순 해시의 문제
N=4 샤드
key=100 → 100 % 4 = shard 0
N=5 샤드 추가
key=100 → 100 % 5 = shard 0
N=6
key=100 → 100 % 6 = shard 4 (위치 변경!)
거의 모든 키가 새 위치 → 대량 데이터 이동.
Consistent Hashing 동작
Hash 공간 (0 ~ 2^32) — 원형(ring)으로 배치
Ring:
shard1 ─→ shard2 ─→ shard3 ─→ shard4 ─→ (다시 shard1)
키:
hash(key) → ring의 한 위치 → 시계방향 가장 가까운 shard에 저장
노드 추가/제거 시 인접 영역만 영향 — 1/N 데이터만 이동.
shard5 추가:
shard1과 shard2 사이에 위치
→ shard2의 일부 데이터만 shard5로 이동
→ shard1·shard3·shard4의 데이터는 그대로
여기서 정말 중요한 시험 함정 — Consistent Hashing은 Cassandra·DynamoDB·MongoDB·Redis Cluster 등 거의 모든 분산 DB의 표준입니다.
Virtual Nodes (vnodes)
각 물리 샤드에 가상 노드 여러 개 매핑 → ring에 더 균등 분산.
shard1 → vnode1, vnode10, vnode30 (가상 위치 3개)
shard2 → vnode5, vnode20, vnode40
분산 균등성 ↑.
샤딩의 단점
1. Cross-Shard JOIN
-- 단일 DB
SELECT u.name, o.amount
FROM users u JOIN orders o ON u.id = o.user_id;
-- 샤딩 환경
-- users는 shard1, orders는 shard5에 있다면?
-- 애플리케이션이 두 샤드 조회 후 코드로 JOIN
해결법:
- 데이터 재구조화 — 같은 샤드에 관련 데이터 (user_id로 모든 관련 데이터 샤딩)
- 애플리케이션 레벨 JOIN — 두 쿼리 후 코드 결합
- 데이터 중복 (denormalization)
2. 분산 트랜잭션
shard1: account A 출금
shard2: account B 입금
ACID 보장 = 2PC (Two-Phase Commit)
Phase 1: 모든 샤드 PREPARE
Phase 2: 모든 PREPARE 성공 → COMMIT, 하나라도 실패 → ROLLBACK
여기서 시험 함정이 하나 있어요. 2PC는 느리고 장애에 약함 (coordinator 다운 = 정지). 가능하면 분산 트랜잭션 회피 — Saga 패턴 등 대안.
3. Resharding
샤드 수 변경 = 데이터 재분배. 운영 중 매우 어려움.
4 → 8 샤드 확장
- 데이터 이동 시간 (수일~수주)
- 운영 중 일관성 유지
- 다운타임 최소화
도구 — Vitess (MySQL), Citus (PostgreSQL), MongoDB Sharding.
4. 운영 복잡도
- 모니터링 N배
- 백업 N개 동기화
- 보안 패치 N대
- 모든 샤드의 일관된 스키마 변경
언제 샤딩해야 하는가?
샤딩 전 시도할 것:
1. 인덱스 최적화 (2편)
2. Read Replica (5편)
3. 캐시 (Redis·Memcached)
4. 파티셔닝 (3편)
5. Vertical Scaling (큰 서버)
↓
↓ 모두 부족하면
↓
6. 샤딩 (마지막 수단)
여기서 정말 중요한 시험 함정 — 샤딩은 마지막 수단. 단일 큰 서버(64코어·1TB RAM)로 수년 동안 충분한 경우 많음. 너무 일찍 샤딩 = 비용 큼.
신호:
- 단일 서버 RAM/Disk 한계
- 단일 서버 처리량 한계 (수만 QPS+)
- 지리적 분산 필요 (글로벌 서비스)
- 강제 샤딩 정책 (compliance·격리)
샤딩 키 선정
핵심 결정 — 어떤 컬럼으로 샤딩할 것인가.
좋은 샤딩 키:
- 카디널리티 높음 — 균등 분산
- 자주 WHERE에 등장 — 단일 샤드 조회
- 변경 안 됨 — 샤드 이동 비용 큼
- JOIN 효율 — 관련 데이터 같은 샤드
예시:
- 멀티 테넌트 SaaS —
tenant_id - 소셜 —
user_id - 게임 —
account_id또는region
여기서 시험 함정이 하나 있어요. 잘못된 샤딩 키는 거의 되돌릴 수 없음. 신중히 선정. 가능하면 데이터 모델링 단계에서 결정.
샤딩 도구
Vitess (YouTube에서 시작)
MySQL 위 샤딩 레이어. 애플리케이션 투명 (vt-gate 라우팅).
Citus (PostgreSQL)
PostgreSQL 확장. 분산 테이블 SQL로 관리.
MongoDB Sharding
MongoDB 자체 지원. mongos 라우터 + config 서버.
직접 구현
소규모 — 애플리케이션 코드에서 샤드 라우팅. 간단하지만 운영 부담.
def get_shard(user_id):
return user_id % NUM_SHARDS
shard_id = get_shard(123)
db = get_db_connection(shard_id)
db.execute("SELECT * FROM users WHERE id = ?", (123,))
샤딩 vs 복제
5편(복제)와 보완 관계.
샤딩 = 데이터 분할 (쓰기 확장)
복제 = 데이터 복사 (읽기 확장 + HA)
운영 환경 = 샤딩 + 복제 조합
shard1 (Primary + Replica × 2)
shard2 (Primary + Replica × 2)
shard3 (Primary + Replica × 2)
시험 직전 한 번 더 — 자주 헷갈리는 함정 모음
여기까지가 4편의 핵심입니다. 시험 직전 또는 실무에서 헷갈릴 때 다시 펼쳐 볼 수 있게 압축 노트로 마무리할게요.
- 샤딩 = 여러 DB 서버에 분산
- 단일 노드 한계 — CPU·RAM·Disk·연결·처리량
- Partitioning (단일 DB) vs Sharding (여러 서버)
- 샤딩 = 애플리케이션 라우팅 (DBMS 자동 X)
- ACID 보장 어려움 — 2PC 필요
- 3 전략 — Range / Hash / Geographic
- Range = 범위 쿼리 빠름, Hot Spot 위험
- Hash = 균등 분산, 범위 쿼리 X
- Geographic = 지역별 / Directory = 매핑 테이블
- 단순 modulo 해시 = Resharding 지옥
- Consistent Hashing = 노드 추가/제거 시 1/N만 이동
- Cassandra·DynamoDB·MongoDB·Redis Cluster 표준
- Virtual Nodes (vnodes) = 분산 균등성 ↑
- 단점 4가지 — Cross-Shard JOIN / 분산 트랜잭션 / Resharding / 운영 복잡도
- Cross-Shard JOIN = 데이터 재구조화·앱 레벨·denormalization
- 2PC = Phase 1 PREPARE / Phase 2 COMMIT, 느리고 장애에 약함
- 대안 = Saga 패턴
- Resharding 어려움 — 도구 (Vitess·Citus·MongoDB)
- 샤딩은 마지막 수단 — 인덱스·Read Replica·캐시·파티셔닝 먼저
- 샤딩 키 선정 = 가장 중요, 거의 되돌릴 수 없음
- 좋은 키 — 카디널리티 높음·자주 WHERE·불변·JOIN 효율
- SaaS =
tenant_id/ 소셜 =user_id - 도구 — Vitess (MySQL) / Citus (PostgreSQL) / MongoDB
- 샤딩 = 쓰기 확장 / 복제 = 읽기 확장 + HA (보완 관계)
시리즈 다른 편
- 1편 — ACID·트랜잭션
- 2편 — 인덱싱
- 3편 — 파티셔닝
- 4편 — 샤딩 (현재 글)
- 5편 — 복제
- 6편 — 동시성 제어
- 7편 — 내부 구조
- 8편 — 고급 주제
공식 문서: Vitess Architecture / Citus Documentation 에서 더 깊이.
다음 글(5편)에서는 복제 — Master-Slave / Multi-Master / 동기 vs 비동기 / Read Replica 설계까지 풀어 갑니다.