샤딩 (Sharding)
핵심 개념
하나의 대규모 테이블을 여러 DB 서버에 수평 분할하는 것.
[단일 DB]
orders 테이블: 1억 건 → 느림!
[샤딩 후]
Shard 1: user_id 1~1000만 (2500만 건)
Shard 2: user_id 1001~2000만 (2500만 건)
Shard 3: user_id 2001~3000만 (2500만 건)
Shard 4: user_id 3001만~ (2500만 건)
→ 각 서버가 25%만 담당!
샤딩 키 전략
| 전략 | 방법 | 장점 | 단점 |
|---|
| 범위 기반 | user_id 1~N | 구현 간단 | 핫스팟 가능 |
| 해시 기반 | hash(user_id) % N | 균등 분산 | 범위 쿼리 어려움 |
| 디렉토리 기반 | 매핑 테이블 조회 | 유연함 | 매핑 테이블 병목 |
해시 기반 샤딩 예시
user_id = 12345
shard = hash(12345) % 4 = 1
→ Shard 1에 저장/조회
[라우팅]
App → Shard Router
→ hash(key) % N
→ 해당 Shard로 전달
주의할 점
Cross-Shard JOIN 불가
→ user_id=1과 user_id=2000만의
주문을 JOIN하려면?
→ 애플리케이션 레벨에서 처리
Shard 추가 시 재분배 필요
→ Consistent Hashing으로 완화
→ 전체 데이터 이동 최소화
트랜잭션 범위 제한
→ 단일 Shard 내에서만 ACID 보장
→ 분산 트랜잭션은 복잡하고 느림
샤딩 vs 다른 전략
데이터 1000만 건 이하
→ 인덱스 최적화 + 읽기 복제본
1000만~1억 건
→ 파티셔닝 (단일 DB 내 분할)
1억 건 이상 or 쓰기 병목
→ 샤딩 (여러 DB 서버)
Q.샤딩이 필요한 시점은 언제인가요?
한 대로는 감당이 안 되고 다른 수단을 다 써본 뒤입니다. 샤딩은 운영 복잡도가 크게 오릅니다.
| 순서 | 수단 |
|---|
| 1 | 인덱스와 쿼리 개선 |
| 2 | 캐시 도입 |
| 3 | 읽기 복제본 추가 |
| 4 | 서버 사양 상향 |
| 5 | 테이블 파티셔닝 |
| 6 | 샤딩 |
3번까지로 읽기는 대부분 해결됩니다. 샤딩이 필요한 것은 쓰기가 한 대의 한계를 넘을 때입니다. 복제본을 늘려도 쓰기는 리더 한 곳으로 모이기 때문입니다.
그 밖의 신호로는 단일 테이블이 수억 행을 넘어 인덱스가 메모리에 안 들어가는 경우, 백업과 복구 시간이 감당 안 되는 경우가 있습니다.
흔한 실수: 데이터가 많아지면 바로 샤딩을 떠올리는 것. 조인과 트랜잭션이 샤드를 넘으면 어려워지므로, 미룰 수 있으면 미루는 것이 좋습니다.
Q.샤딩 키를 잘못 선택하면 어떤 문제가 생기나요?
| 문제 | 원인 | 증상 |
|---|
| 편중 | 값이 고르지 않다 | 한 샤드만 포화되고 나머지는 논다 |
| 핫스팟 | 특정 값에 트래픽이 몰린다 | 인기 사용자나 인기 상품이 한 샤드로 |
| 재분배 비용 | 나머지 연산 기반 | 샤드 수를 바꾸면 대부분의 키가 이동한다 |
| 교차 샤드 조회 | 조회 조건이 샤드 키가 아니다 | 모든 샤드에 물어봐야 한다 |
user_id % 100 지역 코드가 앞에 오는 id 면 특정 샤드에 몰린다
hash(user_id) % 100 고르게 흩어진다
키 선택의 기준은 조회 조건에 그 키가 들어가는가입니다. 메시지를 room_id 로 샤딩하면 방 단위 조회가 한 샤드에서 끝납니다. user_id 로 샤딩하면 같은 방의 메시지가 흩어집니다.
흔한 실수: 고르게 나누는 것만 보는 것. 분포가 고르더라도 조회가 매번 전 샤드를 훑으면 샤딩의 이점이 사라집니다.
Q.Cross-Shard JOIN이 필요한 상황은 어떻게 해결하나요?
샤드를 넘는 조인은 DB 가 대신 해주지 않으므로 설계로 피하거나 애플리케이션에서 조합합니다.
| 방법 | 내용 | 대가 |
|---|
| 같은 샤드에 모은다 | 함께 조회되는 데이터를 같은 키로 샤딩 | 키 설계가 어려워진다 |
| 애플리케이션 조합 | 각 샤드에서 가져와 코드에서 합친다 | 왕복이 늘고 페이징이 어렵다 |
| 참조 데이터 복제 | 작고 잘 안 바뀌는 표를 모든 샤드에 둔다 | 갱신을 전 샤드에 전파해야 한다 |
| 조회 전용 저장소 | 검색 엔진이나 분석 DB 에 합쳐 둔다 | 동기화 지연이 생긴다 |
첫 번째가 가장 근본적입니다. 주문과 주문 항목을 같은 user_id 로 샤딩하면 그 조인은 한 샤드 안에서 끝납니다.
정렬과 페이징이 특히 어렵습니다. 전 샤드에서 상위 N개를 각각 받아 합치고 다시 정렬해야 하며, 깊은 페이지일수록 비용이 커집니다.
흔한 실수: 샤딩 후에도 기존 조인 쿼리를 그대로 쓰려는 것. 샤딩을 도입하는 순간 데이터 접근 방식을 함께 바꿔야 합니다.
먼저 스스로 답해보고 아래 답변과 견줘보세요. 막히는 부분은 문제로 확인할 수 있어요.
읽었으면 문제로 확인해보세요
데이터베이스 문제를 풀면 틀린 문제가 자동으로 노트에 쌓입니다. 가입 없이 5문제를 먼저 풀어볼 수도 있어요.