🔥 On-Demand과 Provisioned: 가격 모델

1653자
18분

On-Demand과 Provisioned 두 모드의 청구 형태 비교 표지 이미지. 같은 트래픽 곡선이 위쪽엔 Provisioned 예약량 라인 + 실제 사용량 음영, 아래쪽엔 On-Demand request unit 누적으로 두 가지 청구 형태로 보인다.

처음 사이드 프로젝트에 DynamoDB 표를 만들 때, AWS 콘솔의 첫 화면이 capacity mode를 고르라고 했다. 그때는 두 옵션이 어떻게 다른지 잘 몰랐다. "사용한 만큼만 내라"는 문구가 먼저 들어와서 On-Demand를 골랐다. 첫 달 청구서가 예상보다 두 배쯤 컸다. 트래픽이 정착한 뒤에 들어온 백만 단위 단가가 그렇게 됐다. 그제야 capacity mode 결정이 표에 어떤 청구 모델을 붙이는 결정인지를 천천히 살폈다.

DynamoDB의 처리량 단위 자체는 DynamoDB란 무엇인가: 키-값 스토어의 관점에서 정리했다. Provisioned 모드의 read/write capacity unit과 On-Demand 모드의 read/write request unit이 같은 처리량을 두 다른 청구 단위로 표현한다는 사실까지가 그쪽 글의 범위다. 이 글에서는 같은 단위를 AWS가 어떻게 청구서에 찍는지, 그리고 두 모드 중 어느 쪽이 어떤 워크로드에 어울리는지를 다룬다.

Provisioned은 RCU/WCU를 시간당으로 예약한다

Provisioned 모드는 사용자가 RCU와 WCU를 미리 정해 두는 모드다. 표를 만들 때 "이 표는 평균적으로 RCU 100, WCU 50을 쓴다"고 선언하면 DynamoDB가 그만큼의 capacity를 할당한다. 청구액은 이 예약량 × 시간이 결정한다. 실제 트래픽이 0이어도 AWS가 예약량만큼 매시간 청구한다.

AWS 공식 pricing 페이지(https://aws.amazon.com/dynamodb/pricing/)는 us-east-1 기준 RCU 한 시간을 $0.00013, WCU 한 시간을 $0.00065로 적어 둔다. 서울 리전(ap-northeast-2)은 region별 단가가 따로 적혀 있으므로 발행 시점 페이지를 직접 확인한다. 한 달이 약 730시간이니 RCU 100을 한 달 내내 예약하면 100 × 730 × $0.00013 ≈ $9.49, WCU 50이라면 50 × 730 × $0.00065 ≈ $23.73. 두 항목을 합치면 그 표는 한 달에 약 $33을 처리량 항목으로만 낸다. storage·backup·DTO는 별개다.

예약량을 트래픽에 맞춰 자동으로 조정하려면 Application Auto Scaling을 켠다. AWS Developer Guide "Considerations when switching capacity modes in DynamoDB"는 콘솔에서 Provisioned로 전환할 때 다음 default를 권한다. target utilization 70%, 최소 5 unit, 최대는 region maximum. CloudWatch 알람이 ConsumedReadCapacityUnits / ProvisionedReadCapacityUnits 비율을 utilization으로 계산한다. 70%를 넘으면 알람이 trigger되고 Auto Scaling이 RCU/WCU를 늘리도록 update를 호출한다.

이 update가 즉시 끝나지 않는다는 점이 Provisioned 모드의 단서다. capacity 조정은 분 단위로 끝난다. 트래픽이 갑자기 두 배로 튄 순간, 새 capacity가 들어올 때까지 기존 예약량 + 약간의 burst capacity로 버텨야 한다. burst가 모자라면 throttle된다. 즉, Provisioned는 예측 가능한 트래픽에 강하고 예측이 빗나간 트래픽에 약하다.

Provisioned 청구 구조 다이어그램. 한 달 시간 축 위에 평평한 'Reserved RCU/WCU' 라인이 그려져 있고, 그 아래로 흔들리는 'Actual usage' 라인이 있다. 두 라인 사이의 간격은 'unused capacity (still billed)' 로 음영 처리. 우측 상단에 'Auto Scaling target 70% — adjusts in minutes, not seconds' 메모. 하단에 'reservation × hours = bill' 청구 공식.

On-Demand는 read/write request unit으로 청구한다

On-Demand 모드는 사전 예약 자체가 없다. 매 read·write 요청 한 번이 read/write request unit으로 환산되고, AWS가 한 달치 unit 합계에 단가를 곱해 청구한다. AWS Developer Guide "DynamoDB on-demand capacity mode"가 단위 정의를 단정적으로 적는다. "One read request unit represents one strongly consistent read operation per second, or two eventually consistent read operations per second, for an item up to 4 KB in size." (read request unit 하나는 4 KB 이하 항목에 대한 strongly consistent read 1회 또는 eventually consistent read 2회를 가리킨다.) 그리고 "One write request unit represents one write operation per second, for an item up to 1 KB in size." (write request unit 하나는 1 KB 이하 항목 write 1회를 가리킨다.)

us-east-1 단가는 RRU 백만 개당 $0.125, WRU 백만 개당 $0.625다(2024-11 인하 후). 같은 트래픽 수준을 가정하면 Provisioned 환산값과 비교할 수 있다. 한 시간에 쓰기 50회/초가 일정하게 발생한다면 한 달치 WRU 합은 50 × 3600 × 730 = 약 1.31억 개. 이 트래픽을 On-Demand로 처리하면 1.31억 / 100만 × $0.625 ≈ $82. 같은 워크로드를 Provisioned WCU 50으로 받으면 위에서 본 $23.73이다. 일정한 트래픽을 100% 활용한다면 Provisioned가 분명히 싸다.

문제는 그 "100% 활용"이 현실에서 거의 불가능하다는 점이다. Auto Scaling을 70% 타깃으로 켜 두면 평균 활용률은 70% 근처에서 머문다. burst를 대비해 여유 용량을 남기면 더 줄어든다. 활용률이 30%로 떨어지는 워크로드라면, Provisioned는 70%의 시간 동안 쓰지 않는 capacity에도 돈을 내는 모드가 된다.

On-Demand는 방향이 반대다. 사전 예약이 없으므로 활용률 개념이 없고, AWS가 실제로 발생한 요청 수만큼만 청구한다. 트래픽이 0인 시간엔 처리량 청구도 0이다. 대신 단가는 비싸다. AWS Developer Guide는 단가를 "pay-per-request"로 설명하면서, throttle 없이 직전 peak의 두 배까지 즉시 받아 준다고 적는다. peak를 넘는 폭증이 30분 안에 두 번 일어나면 throttle 가능. peak가 누적되면 다음 peak도 그만큼 더 받는다.

partition 단위의 한도는 두 모드 모두 같다는 점은 Partition Key와 Sort Key: 데이터 분산의 원리에서 확인했다. On-Demand가 사전 예약을 없앤다고 해서 partition 한도(1,000 WCU/sec, 3,000 RCU/sec)가 사라지지는 않는다. PK 분포 설계는 두 모드 모두 같은 자세로 다룬다.

On-Demand 청구 모델 다이어그램. 위쪽엔 시간 축을 따라 흔들리는 트래픽 곡선이 있고, 아래쪽엔 같은 시간 구간 동안 누적되는 read/write request unit 막대 그래프. 트래픽이 0인 구간엔 막대도 0으로 내려간다. 'Idle hour = zero throughput charge'와 'Peak x 2 instant; over 2x within 30 min may throttle' 두 inset 메모.

2024-11 인하가 새 손익분기를 만든다

2024-11-01에 AWS가 On-Demand 단가를 50% 인하했다. 같은 날 발표된 AWS Database Blog "New – Amazon DynamoDB lowers pricing for on-demand throughput and global tables"는 인하 폭과 적용 시점을 단정적으로 적는다. "Effective November 1, 2024, DynamoDB has reduced prices for on-demand throughput by 50%." (2024년 11월 1일부로 DynamoDB는 On-Demand 처리량 가격을 50% 인하했다.) 이 인하는 모든 region에 자동 적용됐고 사용자가 따로 신청할 일이 없었다.

같은 글은 그 인하의 의미를 분명하게 적는다. "Most provisioned capacity workloads on DynamoDB today will achieve a lower price with on-demand mode." (오늘날 DynamoDB의 provisioned 워크로드 대부분은 on-demand 모드에서 더 낮은 가격을 얻는다.) AWS가 자기 서비스의 두 모드 중 하나를 default로 권장하는 일은 흔하지 않다. AWS Developer Guide "DynamoDB on-demand capacity mode"의 첫 문단도 같은 결론을 한 줄로 단정한다. on-demand 모드가 default이자 권장 처리량 옵션이고, 작게 시작해 초당 수백만 요청까지 자라는 현대적 serverless 애플리케이션을 단순하게 만들어 주기 때문이라는 한 문장이다.

정확한 손익분기 활용률은 AWS가 공식적으로 발표한 수치가 아니라 워크로드별로 다르다. 인하 전 일반적인 운영 룰은 활용률 70% 근처를 기준으로 잡는 경우가 많았고, 인하 후에는 그 기준이 더 낮은 활용률 쪽으로 이동했다는 추정이 가능한 정도다. 정확한 수치는 region·item size·consistency 모드에 따라 달라지므로, 실제 표 하나를 옮기기 전에 CloudWatch의 ConsumedReadCapacityUnits·ConsumedWriteCapacityUnits 메트릭을 한 달치 받아 두 모드의 청구 시뮬레이션을 직접 한다. AWS의 default 권장이 옳더라도, 자기 표의 활용률 패턴을 본 뒤에 결정한다.

2024-11 인하 전후 손익분기 그래프 비교. 왼쪽 패널 'Before Nov 2024'은 X축 utilization 0-100%, Y축 monthly cost. Provisioned 평탄선과 우상향 On-Demand 선이 약 70% 활용률 근처에서 교차. 오른쪽 패널 'After Nov 2024'은 같은 축에서 On-Demand 선이 50% 낮아져 더 낮은 활용률 (35% 근처) 에서 Provisioned 선과 교차. 같은 워크로드의 결정이 인하 후 달라졌음을 보여 준다.

모드 전환에는 비대칭 한도가 있다

한 번 고른 모드가 영구하지는 않다. AWS Developer Guide "Considerations when switching capacity modes in DynamoDB"는 모드 전환 한도를 단정적으로 적어 둔다. "You can switch tables from provisioned capacity mode to on-demand mode up to four times in a 24-hour rolling window. You can switch tables from on-demand mode to provisioned capacity mode at any time." (Provisioned에서 On-Demand로는 24시간 rolling window에서 최대 4회 전환할 수 있다. On-Demand에서 Provisioned로는 언제든 전환할 수 있다.) 비대칭이라는 점이 첫 단서다. AWS는 사용자가 On-Demand 쪽으로 옮기는 결정을 더 쉽게 두었다.

전환 자체는 즉시 끝나지 않는다. AWS Developer Guide는 "이 처리에는 몇 분이 걸릴 수 있고, 그 사이에는 직전 Provisioned 설정에 맞는 처리량을 그대로 받는다"고 적는다. Provisioned에서 On-Demand로 옮기는 경우, AWS가 과거 peak에 맞춰 On-Demand 측 초기 처리량을 보장한다. 같은 글의 예시 한 줄을 빌리면, 4,000 WCU 미만으로만 운영해 온 표는 On-Demand로 전환한 직후 4,000 writes/sec와 12,000 reads/sec를 바로 쓸 수 있다. 그 표가 과거에 한 번이라도 더 높은 peak에 닿았다면 그 peak가 새 default가 된다.

반대 방향 — Provisioned에서 On-Demand로 옮기는 경우는 콘솔과 CLI/SDK의 동작이 다르다. 콘솔이 기존 Auto Scaling 설정을 모두 삭제한다. CLI/SDK로 전환하면 그 설정들을 그대로 보존하고, 나중에 다시 Provisioned로 돌아올 때 그 보존본을 다시 쓴다. On-Demand에서 Provisioned로 돌아올 때는 콘솔이 Auto Scaling 새 default(target 70%·min 5·max region maximum)를 권하고, CLI/SDK는 이전에 보존한 설정을 그대로 다시 적용한다. 운영 자동화 스크립트가 콘솔 흐름을 흉내 내고 있다면 이 차이를 같이 다룬다.

모드 전환의 비대칭 한도 다이어그램. 왼쪽 'Provisioned' 박스에서 오른쪽 'On-Demand' 박스로 향하는 두꺼운 주황 화살표에 'up to 4 times per 24-hour rolling window' 라벨. 반대 방향으로 향하는 파란 화살표에는 'no limit, anytime' 라벨. 하단에 'Switching takes minutes; previous peak preserved on first transition (4,000 WCU floor)' 작은 메모.

신규 표를 만들 때는 도구마다 default가 다르다는 점을 알아 둔다. AWS 콘솔의 create-table 화면은 On-Demand를 기본 선택값으로 보여 준다. CloudFormation의 AWS::DynamoDB::TableBillingMode를 생략하면 default를 PROVISIONED로 처리한다(공식 CloudFormation 문서 기준). On-Demand로 만들고 싶으면 BillingMode: PAY_PER_REQUEST를 명시적으로 적어야 한다. Terraform의 aws_dynamodb_table 리소스도 같은 규칙으로 billing_mode 인자를 명시하지 않으면 PROVISIONED로 만든다. 과거 IaC 템플릿이 BillingMode: PROVISIONED로 들어 있다면, AWS 권장이 On-Demand로 바뀌었다고 해서 그 줄을 그냥 들어내면 안 된다. 들어내도 여전히 PROVISIONED 모드로 동작한다. PAY_PER_REQUEST로 바꾸려면 그 값을 명시한다.

두 모드는 맞바꿈이 아니라 예측 비용을 누가 떠안는가의 차이다

두 모드를 처음 봤을 때 나는 비용과 편의의 맞바꿈이라고 정리했다. Provisioned는 더 싸지만 손이 많이 가는 옵션, On-Demand는 더 비싸지만 손이 덜 가는 옵션 정도로 봤다. 2024-11 인하 이후 그 정리는 부정확하다. 단가 차이가 좁혀진 지금, 두 모드의 차이는 주로 트래픽 예측 비용을 누가 떠안는가에 있다.

Provisioned는 사용자가 예측 비용을 떠안는다. RCU·WCU를 미리 정하려면 트래픽 패턴을 알아야 하고, Auto Scaling 정책을 짜려면 utilization 곡선을 봐야 한다. burst를 위한 여유를 얼마나 둘지, capacity가 늘어나는 데 걸리는 분 단위 지연을 어떻게 흡수할지는 모두 사용자가 결정한다. 그 노력의 보상이 단가 차이다.

On-Demand는 AWS가 예측 비용을 떠안는다. peak 추적, 자동 capacity 조정, partition split for heat까지 AWS 내부가 알아서 처리한다. 사용자는 access pattern과 PK 설계만 다룬다. 단가는 그 떠안기에 대한 대가다. 이렇게 보면, 두 모드 중 어느 쪽을 고를지가 곧 내가 트래픽을 어디까지 예측할 수 있는가에 대한 질문이 된다.

두 모드의 예측 비용 분담 비교 패널. 왼쪽 'Provisioned: user carries it' 패널에 'Predict traffic patterns / Plan Auto Scaling policy / Design burst headroom / Absorb scale-out delay' 항목 + 'Reward: cheaper unit price at high utilization' 메모. 오른쪽 'On-Demand: AWS carries it' 패널에 'Track previous peak / Auto-scale capacity / Split-for-heat partitions' 항목 + 'Cost: higher unit price' 메모.

다음에 새 DynamoDB 표를 만들 때 나는 default인 On-Demand로 시작한다. 한 달 트래픽이 쌓이면 CloudWatch 메트릭으로 활용률 곡선을 본다. 곡선이 평탄하고 활용률이 60%를 안정적으로 유지하면 그제야 Provisioned로 옮길지 검토한다. 그 검토를 안 거치면, 처음 사이드 프로젝트에서 그랬던 것처럼 청구서를 받고 나서야 모드 결정을 늦게 다시 한다.

YouTube 영상

채널 보기
투영과 예측, 그리고 선형 결합 | 선형대수학
직교성과 벡터 투영 | 선형대수학
AI는 데이터를 어떻게 분류할까? 벡터의 거리와 KNN 알고리즘 | 선형대수학
내적의 기하학적 의미와 코사인 유사도 원리 | 선형대수학
숫자 하나가 AI 모델의 운명을 바꾼다? | 선형대수학
우리가 매일 쓰는 맞춤법 검사기와 라우터 속에 숨겨진 알고리즘은? | Trie 자료구조 이야기
행렬의 가장 중요한 연산 - 행렬 곱셈 | 선형대수학
AI를 위한 선형대수학 - 소개 | 선형대수학