"사용자가 1억 명이 넘었습니다. DB 서버 한 대로는 용량도 부족하고, 쓰기 트래픽을 감당할 수 없습니다."
이때 해결책은 데이터를 여러 DB(Shard)에 나누어 담는 것입니다. 이를 **수평 분할(Horizontal Partitioning)**이라고 합니다. 핵심은 **"어떤 규칙으로 데이터를 나눌 것인가(Sharding Key)"**입니다. 이 규칙을 잘못 정하면 샤딩을 안 하느니만 못한 결과가 나옵니다.
1. 방식 1: 레인지 샤딩 (Range Sharding) - "순서대로 차곡차곡"
데이터를 특정 범위(Range)를 기준으로 나누는 방식입니다. 예를 들어 날짜별로 나누거나, ID(Primary Key) 순서대로 나눕니다.
특징
- 규칙: if (id < 100만) DB_1 else if (id < 200만) DB_2
- 확장성: 데이터가 늘어나면 그냥 새로운 DB(DB_3)를 추가하고 200만 < id < 300만 규칙만 추가하면 됩니다.
구조 예시
- Shard A: 사용자 ID 1 ~ 1,000,000
- Shard B: 사용자 ID 1,000,001 ~ 2,000,000
장단점
- 장점:
- 구현이 쉽고 관리가 편합니다.
- 범위 조회(Range Query)가 가능합니다. "최근 1주일 가입자"를 찾을 때 특정 샤드만 뒤지면 됩니다.
- 단점:
- 데이터 쏠림(Hotspot): 만약 "최근 가입한 사용자"만 활동이 활발하다면? Shard B는 터져나가는데 Shard A는 텅텅 비는 불균형이 발생합니다. (트래픽 분산 실패)
2. 방식 2: 해시 샤딩 (Hash / Modular Sharding) - "골고루 섞기"
데이터의 키(Key)를 해시 함수에 넣고, 그 결과를 샤드 개수(N)로 나눈 나머지(%)를 기준으로 저장할 곳을 정합니다.
특징
- 규칙: shard_index = hash(user_id) % node_count
- 균등 분포: 데이터가 순서와 상관없이 모든 샤드에 골고루 퍼집니다.
구조 예시 (노드가 2개일 때)
- User ID 1: 1 % 2 = 1 -> Shard B
- User ID 2: 2 % 2 = 0 -> Shard A
- User ID 3: 3 % 2 = 1 -> Shard B
장단점
- 장점:
- 데이터 균등 분산: 특정 샤드에 트래픽이 몰리는 핫스팟 현상을 막을 수 있습니다. 쓰기 성능 확장에 최적입니다.
- 단점:
- 재샤딩(Resharding)의 지옥: 서버를 2대에서 3대로 늘리면? 나누는 수(N)가 바뀌므로(% 2 -> % 3) 기존 데이터의 위치가 전부 엉망이 됩니다. 데이터를 전부 꺼내서 다시 계산하고 이동시켜야 하는 대공사가 필요합니다.
- (참고: 이를 해결하기 위해 '일관성 해싱(Consistent Hashing)' 알고리즘을 사용합니다.)
3. 실무 비교: 언제 무엇을 쓰는가?
| 구분 | Range Sharding (범위 기반) | Hash Sharding (해시 기반) |
| 분할 기준 | PK 범위, 날짜, 지역 등 순차적 기준 | hash(key) % N (무작위성) |
| 데이터 분포 | 불균형 가능성 높음 (최신 데이터 쏠림) | 균등함 (트래픽 분산 우수) |
| 쿼리 효율 | 범위 검색(BETWEEN) 유리 | 단건 조회(=) 유리, 범위 검색 불리 |
| 확장성 | 쉬움 (새 범위용 서버만 추가) | 어려움 (전체 데이터 재배치 필요) |
| 추천 상황 | 로그 데이터, 날짜별 히스토리, 지역별 서비스 | SNS 피드, 대규모 사용자 세션, 글로벌 서비스 |
결론
"최근 일주일 데이터만 주로 조회한다"거나 "지역별로 데이터가 명확히 나뉜다"면 **레인지 샤딩(Range)**이 관리하기 편합니다.
하지만 "모든 사용자가 언제 접속할지 모르고, 트래픽을 아주 공평하게 분산해야 한다"면 **해시 샤딩(Hash)**을 써야 합니다. 단, 해시 샤딩을 쓸 때는 서버 증설 시의 데이터 마이그레이션 비용을 미리 계산해둬야 합니다.
(현대적인 NoSQL DB인 MongoDB나 Cassandra는 내부적으로 이 두 가지 전략 중 하나를 선택하거나 혼합해서 자동으로 관리해 줍니다.)
'프로그래밍 > 디자인패턴' 카테고리의 다른 글
| API 버저닝 패턴(API Versioning Pattern) 완벽 정리 (0) | 2025.12.07 |
|---|---|
| 인증 상태 관리 패턴: 세션(Session) vs 토큰(JWT) 완벽 비교 (0) | 2025.12.07 |
| 리더 선출 패턴(Leader Election Pattern) 완벽 정리 (0) | 2025.12.07 |
| 비동기 요청-응답 패턴(Asynchronous Request-Reply) 완벽 정리 (0) | 2025.12.07 |
| 사이드카 패턴(Sidecar Pattern) 완벽 정리 (0) | 2025.12.07 |