DynamoDB 파티션 키 설계: 핫 파티션 방지와 성능 최적화
DynamoDB 파티션 키를 올바르게 설계하여 핫 파티션을 방지하고 최대 성능을 이끌어내는 방법을 알아봅니다.
관련 시험 도메인
- Domain 3: Design High-Performing Architectures
핵심 요약 (BLUF)
파티션 키는 카디널리티가 높고 접근 패턴이 균등한 속성을 선택하세요. 핫 파티션이 발생하면 프로비저닝된 용량을 낭비하고 쓰로틀링이 발생합니다. 샤딩 기법으로 부하를 분산시킬 수 있습니다.
시험 팁
시험 핵심: "핫 파티션 → 쓰로틀링 → 해결책: 높은 카디널리티 키 또는 쓰기 샤딩"
파티션 키가 왜 중요한가?
DynamoDB는 파티션 키의 해시값을 기반으로 데이터를 물리적 파티션에 분산합니다.
┌─────────────────────────────────────────┐
│ DynamoDB 테이블 │
└─────────────────────────────────────────┘
│
┌─────────────────┼─────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 파티션 A │ │ 파티션 B │ │ 파티션 C │
│ (Hash 0-33) │ │ (Hash 34-66)│ │ (Hash 67-99)│
│ │ │ │ │ │
│ user_001 │ │ user_002 │ │ user_003 │
│ user_004 │ │ user_005 │ │ user_006 │
└──────────────┘ └──────────────┘ └──────────────┘
파티션별 처리 한도
| 항목 | 한도 |
|---|---|
| 읽기 용량 | 3,000 RCU/초 |
| 쓰기 용량 | 1,000 WCU/초 |
| 저장 용량 | 10GB |
시험 팁
암기: 파티션당 3,000 RCU, 1,000 WCU, 10GB
핫 파티션(Hot Partition)이란?
특정 파티션에 요청이 집중되어 해당 파티션의 처리 한도를 초과하는 현상입니다.
핫 파티션 발생 예시
잘못된 설계: 파티션 키 = "date" (YYYY-MM-DD)
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 2026-01-24 │ │ 2026-01-25 │ │ 2026-01-26 │
│ │ │ │ │ 🔥 HOT! │
│ 접근: 1% │ │ 접근: 5% │ │ 접근: 94% │
│ │ │ │ │ │
│ 한도 여유 │ │ 한도 여유 │ │ 쓰로틀링! │
└──────────────┘ └──────────────┘ └──────────────┘
결과: 오늘 날짜 파티션에 모든 요청이 집중되어 쓰로틀링 발생
핫 파티션의 영향
- 쓰로틀링:
ProvisionedThroughputExceededException발생 - 비용 낭비: 다른 파티션의 용량은 사용되지 않음
- 성능 저하: 요청 지연 또는 실패
좋은 파티션 키의 조건
1. 높은 카디널리티 (Cardinality)
파티션 키의 고유값 개수가 많을수록 좋습니다.
| 파티션 키 | 카디널리티 | 평가 |
|---|---|---|
user_id | 수백만 | ✅ 매우 좋음 |
order_id | 수백만 | ✅ 매우 좋음 |
genre | 10-20 | ❌ 낮음 |
status | 3-5 | ❌ 매우 낮음 |
date | 365 | ⚠️ 낮음 (접근 패턴 문제) |
2. 균등한 접근 패턴
키 값들에 대한 요청이 고르게 분산되어야 합니다.
좋은 예: user_id
- user_001: 100 요청/초
- user_002: 95 요청/초
- user_003: 105 요청/초
→ 균등 분산 ✅
나쁜 예: celebrity_id
- celebrity_001 (인기 연예인): 10,000 요청/초 🔥
- celebrity_002: 10 요청/초
- celebrity_003: 5 요청/초
→ 집중 현상 ❌
3. 복합 키 활용
파티션 키 + 정렬 키로 더 세밀한 설계가 가능합니다.
| 설계 패턴 | 파티션 키 | 정렬 키 | 용도 |
|---|---|---|---|
| 사용자별 주문 | user_id | order_timestamp | 사용자의 주문 이력 조회 |
| 게시판 | board_id | post_timestamp | 게시판의 글 목록 |
| IoT 센서 | device_id | timestamp | 센서 데이터 시계열 |
핫 파티션 해결 전략
전략 1: 쓰기 샤딩 (Write Sharding)
파티션 키에 무작위 접미사를 추가하여 부하를 분산합니다.
원본 키: "popular_item_001"
↓
샤딩된 키: "popular_item_001#shard_0"
"popular_item_001#shard_1"
"popular_item_001#shard_2"
...
"popular_item_001#shard_9"
구현 예시:
import random
def get_sharded_key(item_id, shard_count=10):
shard = random.randint(0, shard_count - 1)
return f"{item_id}#shard_{shard}"
# 쓰기
dynamodb.put_item(
TableName='Products',
Item={
'pk': {'S': get_sharded_key('popular_item_001')},
'view_count': {'N': '1'}
}
)
# 읽기 (모든 샤드 집계)
for i in range(10):
response = dynamodb.query(
TableName='Products',
KeyConditionExpression='pk = :pk',
ExpressionAttributeValues={
':pk': {'S': f'popular_item_001#shard_{i}'}
}
)
시험 팁
쓰기 샤딩 단점: 읽기 시 모든 샤드를 조회해야 하므로 읽기 복잡도가 증가합니다. 쓰기 집중 워크로드에 적합합니다.
전략 2: 시간 기반 파티셔닝
날짜 대신 더 세분화된 시간 단위를 사용합니다.
나쁜 예: pk = "2026-01-26" (하루에 하나의 핫 파티션)
좋은 예: pk = "2026-01-26#hour_14" (시간별 분산)
더 좋은 예: pk = "2026-01-26#14:30" (30분 단위 분산)
전략 3: 복합 속성 결합
여러 속성을 결합하여 카디널리티를 높입니다.
나쁜 예: pk = "status" (PENDING, COMPLETED, FAILED)
→ 3개 파티션만 사용
좋은 예: pk = "status#customer_id"
→ PENDING#cust_001, COMPLETED#cust_002, ...
→ 수천 개 파티션으로 분산
Adaptive Capacity
DynamoDB는 핫 파티션 문제를 자동으로 완화하는 기능을 제공합니다.
작동 방식
- 핫 파티션 감지
- 다른 파티션의 여유 용량을 핫 파티션에 재분배
- 필요 시 파티션 자동 분할
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 파티션 A │ │ 파티션 B │ │ 파티션 C │
│ 사용: 200 │ │ 사용: 2800 │ │ 사용: 100 │
│ 한도: 1000 │ │ 한도: 1000 │ │ 한도: 1000 │
└──────────────┘ └──────────────┘ └──────────────┘
│ │ │
└───────────────►│◄────────────────┘
Adaptive Capacity
B에 추가 용량 할당
한계
- 즉각적이지 않음: 감지 및 조정에 시간 소요
- 무한 확장 아님: 프로비저닝된 총 용량 내에서만 작동
- 근본적 해결 아님: 설계 개선이 여전히 필요
시험 팁
시험에서 "Adaptive Capacity가 있으니 파티션 키 설계는 중요하지 않다"는 틀린 답변입니다.
실전 설계 패턴
패턴 1: 전자상거래 주문
테이블: Orders
파티션 키: customer_id (높은 카디널리티)
정렬 키: order_timestamp#order_id
조회 패턴:
- 특정 고객의 최근 주문: Query(pk=customer_id, sk begins_with "2026-01")
- 특정 주문 조회: GetItem(pk=customer_id, sk=timestamp#order_id)
패턴 2: 실시간 리더보드
문제: 전체 순위 조회 시 모든 파티션 스캔 필요
해결: GSI 활용
- 기본 테이블: pk=user_id, sk=game_id
- GSI: pk="GAME#game_id", sk=score (내림차순)
- 상위 100명 조회: Query(GSI, pk="GAME#001", Limit=100)
패턴 3: IoT 센서 데이터
문제: 수천 개 센서에서 초당 수만 건 데이터 유입
설계:
파티션 키: device_id#YYYY-MM-DD-HH (시간별 분산)
정렬 키: timestamp_ms
결과:
- 24시간 × 1000 센서 = 24,000 파티션으로 분산
- 개별 센서의 시간대별 조회 가능
SAA-C03 시험 출제 포인트
- ✅ 핫 파티션 원인: "낮은 카디널리티 또는 불균등한 접근 패턴"
- ✅ 쓰로틀링 해결: "파티션 키 재설계 또는 쓰기 샤딩"
- ✅ Adaptive Capacity: "자동 용량 재분배, 하지만 설계 대체 불가"
- ✅ 파티션 한도: "3,000 RCU, 1,000 WCU, 10GB/파티션"
- ✅ 복합 키 활용: "pk + sk로 세밀한 접근 패턴 지원"
시험 팁
시험 문제 예시: "DynamoDB 테이블에서 특정 날짜의 데이터 접근 시 쓰로틀링이 발생합니다. 파티션 키는 날짜(YYYY-MM-DD)입니다. 가장 적절한 해결책은?" → 정답: 파티션 키에 무작위 접미사를 추가하여 쓰기 샤딩 구현
자주 묻는 질문 (FAQ)
Q: 파티션 키를 나중에 변경할 수 있나요?
아니요. 파티션 키는 테이블 생성 후 변경할 수 없습니다. 새 테이블을 만들고 데이터를 마이그레이션해야 합니다.
Q: 정렬 키 없이도 테이블을 만들 수 있나요?
네. 파티션 키만 사용하는 단순 기본 키도 가능합니다. 하지만 복잡한 쿼리 패턴에는 정렬 키가 유용합니다.
Q: 샤딩 개수는 몇 개가 적당한가요?
예상 최대 쓰기 부하를 파티션당 1,000 WCU로 나눈 값 이상이어야 합니다. 예: 5,000 WCU 필요 → 최소 5개 샤드
Q: On-Demand 모드에서도 핫 파티션이 문제가 되나요?
네. On-Demand도 파티션당 한도가 있습니다. Adaptive Capacity가 작동하지만, 갑작스러운 부하 급증에는 대응이 늦을 수 있습니다.
Q: GSI도 핫 파티션 문제가 있나요?
네. GSI도 별도의 파티션 구조를 가지므로, GSI의 파티션 키 설계도 동일한 원칙을 따라야 합니다.