DynamoDB 용량 모드 선택 가이드: On-Demand vs Provisioned — 트래픽 패턴을 모를 때 어떻게 결정할까

DynamoDB 테이블을 처음 생성할 때 가장 먼저 마주치는 질문이 바로 용량 모드 선택이다. 트래픽 패턴이 불분명한 초기 단계에서 Provisioned를 잘못 설정하면 스로틀링으로 요청이 거부되고, On-Demand를 무심코 유지하다 보면 예상치 못한 청구서를 받게 된다. 이 글은 DynamoDB 용량 모드의 내부 동작 원리부터 실전 전환 판단 기준까지, 운영 경험을 바탕으로 정리한다.

TL;DR — 한눈에 보는 선택 기준

상황권장 모드핵심 이유
트래픽 패턴 미확인, 초기 서비스On-Demand스로틀링 없이 자동 스케일, 용량 예측 불필요
트래픽이 예측 가능하고 일정함Provisioned + Auto Scaling단위 비용이 낮고 비용 상한 제어 가능
급격한 스파이크 + 평시 트래픽 낮음On-Demand피크 대비 Provisioned 과잉 프로비저닝 방지
높은 베이스라인 + 예측 가능한 피크Provisioned + Auto ScalingReserved Capacity와 조합 시 비용 최적화

DynamoDB 용량 모드의 내부 동작 원리

두 모드를 단순히 '자동 vs 수동'으로 이해하면 운영 중 반드시 실수가 생긴다. 각 모드가 내부적으로 어떻게 처리량을 관리하는지 먼저 파악해야 한다.

Provisioned 모드

Provisioned 모드에서는 RCU(Read Capacity Unit)와 WCU(Write Capacity Unit)를 명시적으로 설정한다. DynamoDB는 설정된 용량을 파티션 단위로 분배하며, 특정 파티션에 요청이 집중되면 해당 파티션의 할당량이 소진되어 ProvisionedThroughputExceededException이 발생한다. Auto Scaling을 활성화하면 CloudWatch 지표를 기반으로 목표 사용률에 맞게 RCU/WCU를 자동 조정하지만, 스케일 아웃에는 수 분의 지연이 존재한다. 갑작스러운 트래픽 급증이 이 지연 구간에 발생하면 스로틀링을 피할 수 없다.

On-Demand 모드

On-Demand 모드는 사전 용량 설정 없이 요청량에 따라 자동으로 처리량을 조정한다. 내부적으로 DynamoDB는 테이블의 이전 피크 트래픽을 기준으로 즉각적인 처리 능력을 유지한다. 단, 완전히 새로운 테이블이거나 트래픽이 장기간 낮았던 경우, 갑작스러운 대규모 스파이크는 내부 조정 시간이 필요할 수 있다. 비용은 실제 소비한 rRCU(replicated read request unit)와 WRU(write request unit) 단위로 청구된다.

graph TD Client["클라이언트 요청"] --> Router["DynamoDB 요청 라우터"] Router --> ModeCheck{"용량 모드?"} ModeCheck -->|"Provisioned"| CapCheck["파티션 할당 용량 확인"] ModeCheck -->|"On-Demand"| DirectProcess["즉시 처리
요청 단위 과금"] CapCheck --> ThrottleCheck{"용량 초과?"} ThrottleCheck -->|"Yes"| Throttle["ProvisionedThroughputExceededException 반환"] ThrottleCheck -->|"No"| ProvProcess["요청 처리
프로비저닝 용량 과금"] Throttle --> ASCheck{"Auto Scaling
활성화?"} ASCheck -->|"Yes"| ASScale["CloudWatch 알람 트리거
용량 조정 (수 분 지연)"] ASCheck -->|"No"| AppRetry["애플리케이션 재시도 필요"] DirectProcess --> Success["응답 반환"] ProvProcess --> Success
  1. 클라이언트 요청이 DynamoDB 엔드포인트에 도달한다.
  2. Provisioned 경로: 파티션별 할당 용량을 확인하고, 초과 시 즉시 스로틀링 오류를 반환한다. Auto Scaling이 활성화된 경우 CloudWatch 알람을 통해 용량 조정이 트리거되지만 반영까지 지연이 있다.
  3. On-Demand 경로: 용량 확인 없이 요청을 처리하고, 실제 소비량을 기준으로 과금한다. 내부적으로 용량을 동적으로 관리한다.
  4. 두 모드 모두 파티션 키 설계가 핫 파티션을 방지하는 핵심 변수다. 모드 선택만으로 불균등한 키 분산 문제를 해결할 수 없다.

On-Demand vs Provisioned: 상세 비교

항목On-DemandProvisioned (+ Auto Scaling)
용량 설정불필요RCU/WCU 명시 필요
스로틀링 위험매우 낮음스파이크 시 발생 가능
비용 구조요청 단위 과금프로비저닝 용량 기준 과금
비용 예측성낮음 (트래픽 비례)높음 (상한 제어 가능)
적합한 워크로드불규칙, 스파이크, 초기 서비스안정적, 예측 가능한 트래픽
Reserved Capacity 적용불가가능 (비용 절감 효과 큼)
모드 전환 제한마지막 모드 변경 후 24시간 경과 후 전환 가능 (양방향 동일)

On-Demand를 '무제한 무료'로 오해하는 경우가 많다. 실제로는 요청 단위 단가가 Provisioned보다 높기 때문에, 트래픽이 안정화되면 Provisioned로 전환하는 것이 비용 효율적이다. 전기 요금으로 비유하면, On-Demand는 편의점 배달 요금, Provisioned는 월정액 구독 요금에 가깝다.

모드 전환 제한 — 운영에서 자주 놓치는 부분

On-Demand와 Provisioned 간 전환은 양방향 모두 마지막 모드 변경 후 24시간이 경과해야 다음 전환이 가능하다. 즉, On-Demand → Provisioned로 전환했다면, 다시 Provisioned → On-Demand로 되돌리려면 24시간을 기다려야 한다. 이 제한은 AWS 공식 문서에 명시된 동작이다.

실제 운영에서 이 제한이 문제가 되는 시나리오가 있다. 예상치 못한 트래픽 급증으로 On-Demand로 긴급 전환했는데, 몇 시간 후 비용 급증을 확인하고 다시 Provisioned로 되돌리려 해도 24시간 내에는 불가능하다. 전환 전에 반드시 비용과 트래픽 패턴을 충분히 검토해야 하는 이유다.

현재 테이블의 용량 모드와 마지막 변경 시각을 확인하는 방법:

aws dynamodb describe-table \
  --table-name your-table-name \
  --query 'Table.{BillingMode:BillingModeSummary.BillingMode,LastChangeToOnDemandTime:BillingModeSummary.LastUpdateToPayPerRequestDateTime,TableStatus:TableStatus}' \
  --output table

출력의 LastUpdateToPayPerRequestDateTime 값을 기준으로 24시간 경과 여부를 확인한다. BillingModePAY_PER_REQUEST이면 On-Demand, PROVISIONED이면 Provisioned 모드다.

DynamoDB 용량 모드 전환 — 단계별 실행 가이드

Step 1: 현재 소비 지표 확인

모드 전환 전에 실제 소비 패턴을 파악하는 것이 선행되어야 한다. ConsumedReadCapacityUnits와 ConsumedWriteCapacityUnits 지표를 최소 2주 이상 관찰해야 피크와 평균의 차이를 정확히 알 수 있다. 이 데이터 없이 Provisioned 값을 설정하면 과잉 또는 과소 프로비저닝이 불가피하다.

aws cloudwatch get-metric-statistics \
  --namespace AWS/DynamoDB \
  --metric-name ConsumedWriteCapacityUnits \
  --dimensions Name=TableName,Value=your-table-name \
  --start-time 2024-01-01T00:00:00Z \
  --end-time 2024-01-15T00:00:00Z \
  --period 3600 \
  --statistics Sum Maximum \
  --output table

시간당 Sum과 Maximum을 함께 확인한다. Maximum이 Sum의 평균 대비 크게 높다면 스파이크성 트래픽이 존재한다는 신호다.

Step 2: 스로틀링 이력 확인

현재 Provisioned 모드라면 스로틀링 발생 여부를 반드시 확인한다. 스로틀링이 발생하고 있다면 용량 증설이나 모드 전환이 필요하다. 지표를 보지 않고 '아마 괜찮겠지'라고 넘어가는 것이 가장 흔한 실수다.

aws cloudwatch get-metric-statistics \
  --namespace AWS/DynamoDB \
  --metric-name WriteThrottleEvents \
  --dimensions Name=TableName,Value=your-table-name \
  --start-time 2024-01-01T00:00:00Z \
  --end-time 2024-01-15T00:00:00Z \
  --period 3600 \
  --statistics Sum \
  --output table

ReadThrottleEvents도 동일한 방식으로 확인한다. Sum이 0이 아닌 구간이 존재한다면 해당 시간대의 트래픽 패턴과 함께 분석한다.

Step 3: On-Demand로 전환

트래픽 패턴이 불규칙하거나 초기 서비스라면 On-Demand로 전환한다. 전환 자체는 즉시 적용되며 테이블 가용성에 영향을 주지 않는다.

aws dynamodb update-table \
  --table-name your-table-name \
  --billing-mode PAY_PER_REQUEST

전환 후 테이블 상태가 ACTIVE로 돌아올 때까지 수 분이 소요될 수 있다. 전환 중에도 읽기/쓰기는 정상 처리된다.

Step 4: Provisioned + Auto Scaling으로 전환

트래픽 패턴이 안정화되고 On-Demand 비용이 예측 가능한 Provisioned 비용보다 높아지는 시점이 전환 타이밍이다. 먼저 테이블을 Provisioned로 전환하고, 이어서 Auto Scaling 정책을 설정한다.

aws dynamodb update-table \
  --table-name your-table-name \
  --billing-mode PROVISIONED \
  --provisioned-throughput ReadCapacityUnits=100,WriteCapacityUnits=50

초기 RCU/WCU 값은 Step 1에서 확인한 평균 소비량의 70% 수준으로 설정하고, Auto Scaling이 나머지를 처리하도록 구성하는 것이 일반적인 접근이다.

🔽 Auto Scaling 정책 등록 CLI (클릭하여 펼치기)
# 쓰기 용량 Auto Scaling 대상 등록
aws application-autoscaling register-scalable-target \
  --service-namespace dynamodb \
  --resource-id table/your-table-name \
  --scalable-dimension dynamodb:table:WriteCapacityUnits \
  --min-capacity 10 \
  --max-capacity 500

# 쓰기 용량 스케일링 정책 설정
aws application-autoscaling put-scaling-policy \
  --service-namespace dynamodb \
  --resource-id table/your-table-name \
  --scalable-dimension dynamodb:table:WriteCapacityUnits \
  --policy-name WriteAutoScalingPolicy \
  --policy-type TargetTrackingScaling \
  --target-tracking-scaling-policy-configuration '{
    "TargetValue": 70.0,
    "PredefinedMetricSpecification": {
      "PredefinedMetricType": "DynamoDBWriteCapacityUtilization"
    },
    "ScaleInCooldown": 60,
    "ScaleOutCooldown": 60
  }'

Step 5: Auto Scaling 정책 확인

Auto Scaling 정책이 정상 등록되었는지 확인한다. 정책이 없는 Provisioned 테이블은 트래픽 변화에 전혀 대응하지 못한다. 콘솔에서 설정한 것처럼 보여도 실제 정책이 누락된 경우가 있으니 CLI로 직접 확인하는 것이 안전하다.

aws application-autoscaling describe-scaling-policies \
  --service-namespace dynamodb \
  --resource-id table/your-table-name \
  --query 'ScalingPolicies[*].{PolicyName:PolicyName,Dimension:ScalableDimension,TargetValue:TargetTrackingScalingPolicyConfiguration.TargetValue}' \
  --output table
graph LR Start(["서비스 시작"]) --> OnDemand["On-Demand 모드로 시작"] OnDemand --> Collect["2주+ 지표 수집
ConsumedCapacity / ThrottleEvents"] Collect --> Analyze{"트래픽 패턴 분석"} Analyze -->|"불규칙 / 스파이크"| KeepOD["On-Demand 유지"] Analyze -->|"안정적 / 예측 가능"| CostCompare{"On-Demand 비용 >
Provisioned 예상 비용?"} CostCompare -->|"No"| KeepOD CostCompare -->|"Yes"| WaitCheck{"마지막 모드 변경 후
24시간 경과?"} WaitCheck -->|"No"| Wait["24시간 대기"] Wait --> WaitCheck WaitCheck -->|"Yes"| Switch["Provisioned + Auto Scaling 전환"] Switch --> Monitor["72시간 스로틀링 모니터링"] Monitor --> ThrottleOccur{"스로틀링 발생?"} ThrottleOccur -->|"Yes"| AdjustCap["RCU/WCU 또는 Auto Scaling 설정 조정"] ThrottleOccur -->|"No"| Stable(["안정 운영"]) AdjustCap --> Monitor
  1. 서비스 초기: 트래픽 패턴 미확인 상태에서 On-Demand로 시작한다.
  2. 지표 수집 단계: 2주 이상 ConsumedCapacity와 ThrottleEvents를 관찰한다.
  3. 패턴 분석: 트래픽이 안정적이고 예측 가능하면 Provisioned 전환을 검토한다. 불규칙하면 On-Demand를 유지한다.
  4. 전환 실행: 마지막 모드 변경 후 24시간 경과를 확인하고 전환한다.
  5. 전환 후 모니터링: 스로틀링 지표를 72시간 이상 관찰하여 설정값을 검증한다.

실전 경험: 잘못된 진단이 만든 비용 폭탄

On-Demand 테이블에서 갑자기 DynamoDB 비용이 3배로 뛰었다는 알림을 받은 적이 있다. 처음에는 애플리케이션 버그로 요청이 폭주하는 것으로 의심했다. CloudWatch에서 ConsumedWriteCapacityUnits를 확인했더니 수치는 정상이었다.

실제 원인은 전혀 다른 곳에 있었다. 배치 작업 하나가 TransactWriteItems를 사용하도록 변경되었는데, 트랜잭션 쓰기는 동일한 데이터를 쓰더라도 일반 PutItem보다 2배의 WRU를 소비한다. 코드 변경 전후 비용 차이를 트랜잭션 오버헤드로 설명할 수 있었다. 모드 문제가 아니라 API 선택의 문제였다.

비용 이상 징후가 보일 때 모드 전환을 먼저 고려하는 것은 잘못된 접근이다. 먼저 어떤 작업이 얼마나 소비하는지를 파악해야 한다.

aws cloudwatch get-metric-statistics \
  --namespace AWS/DynamoDB \
  --metric-name ConsumedWriteCapacityUnits \
  --dimensions Name=TableName,Value=your-table-name \
  --start-time 2024-01-14T00:00:00Z \
  --end-time 2024-01-15T00:00:00Z \
  --period 300 \
  --statistics Sum \
  --output table

5분 단위로 Sum을 확인하면 비용 급증이 시작된 정확한 시각을 특정할 수 있고, 그 시각의 배포 이력이나 배치 실행 로그와 교차 분석하면 원인을 빠르게 좁힐 수 있다.

IAM 권한 — 용량 모드 변경에 필요한 최소 권한

용량 모드 전환과 Auto Scaling 정책 설정에는 여러 서비스에 걸친 권한이 필요하다. 최소 권한 원칙에 따라 필요한 권한만 부여한다.

🔽 최소 권한 IAM 정책 예시 (클릭하여 펼치기)
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DynamoDBTableUpdate",
      "Effect": "Allow",
      "Action": [
        "dynamodb:UpdateTable",
        "dynamodb:DescribeTable"
      ],
      "Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/your-table-name"
    },
    {
      "Sid": "AutoScalingManagement",
      "Effect": "Allow",
      "Action": [
        "application-autoscaling:RegisterScalableTarget",
        "application-autoscaling:PutScalingPolicy",
        "application-autoscaling:DescribeScalingPolicies",
        "application-autoscaling:DeleteScalingPolicy",
        "application-autoscaling:DeregisterScalableTarget"
      ],
      "Resource": "*"
    },
    {
      "Sid": "CloudWatchReadMetrics",
      "Effect": "Allow",
      "Action": [
        "cloudwatch:GetMetricStatistics",
        "cloudwatch:DescribeAlarms"
      ],
      "Resource": "*"
    },
    {
      "Sid": "IAMPassRoleForAutoScaling",
      "Effect": "Allow",
      "Action": "iam:PassRole",
      "Resource": "arn:aws:iam::123456789012:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable"
    }
  ]
}

application-autoscaling 관련 액션은 리소스 수준 제한을 지원하지 않아 "Resource": "*"가 필요하다. IAM Service Authorization Reference에서 각 액션의 리소스 수준 지원 여부를 확인하고 적용한다.

DynamoDB 용량 모드 선택 — 마무리 및 다음 단계

트래픽 패턴을 모르는 초기 단계에서는 On-Demand로 시작하는 것이 안전한 기본값이다. 스로틀링 없이 서비스를 운영하면서 실제 소비 지표를 2주 이상 수집하고, 패턴이 안정화되면 Provisioned + Auto Scaling으로 전환하여 비용을 최적화하는 것이 검증된 접근법이다.

모드 전환은 양방향 모두 마지막 변경 후 24시간 제한이 있으므로, 전환 결정은 충분한 데이터를 바탕으로 신중하게 내려야 한다. 비용 이상 징후가 보일 때는 모드보다 먼저 API 사용 패턴과 파티션 키 분산을 점검하라.

핵심 용어 정리

용어설명
RCU (Read Capacity Unit)최대 4KB 항목에 대한 강력한 일관성 읽기 1회, 또는 최종 일관성 읽기 2회에 해당하는 단위
WCU (Write Capacity Unit)최대 1KB 항목에 대한 쓰기 1회에 해당하는 단위
PAY_PER_REQUESTOn-Demand 모드를 나타내는 AWS API 파라미터 값
ProvisionedThroughputExceededExceptionProvisioned 모드에서 설정된 용량을 초과할 때 반환되는 오류
핫 파티션 (Hot Partition)특정 파티션에 요청이 집중되어 해당 파티션의 처리량 한도를 초과하는 현상

댓글

이 블로그의 인기 게시물

EC2 SSH 연결 시간 초과: 확인해야 할 보안 그룹(Security Group) 규칙

EC2 SSH 연결 타임아웃 완전 해결 가이드: Security Group 인바운드 규칙부터 라우팅까지

IAM User vs IAM Role 차이점 완전 정리 — EC2에서 S3 접근 시 무엇을 써야 하는가