DynamoDB 항목 크기 한도 (400 KB)
단일 DynamoDB 항목은 최대 400 KB의 데이터를 담을 수 있습니다. MongoDB(16 MB
문서)나 실질적 상한이 없는 관계형 행에서 온 사람이라면 그 상한이 낮게 느껴집니다 —
그리고 보통은 어렵게 발견하게 됩니다. 몇 달 동안 잘 동작하던 쓰기가 어느 날 갑자기
항목 하나가 마침내 너무 커졌다는 이유로 ValidationException과 함께 실패할 때 말이죠.
이 한도는 임의로 정해진 것도, 상향 조정할 수 있는 할당량도 아닙니다. 이것은 모델링 제약이며, 여기에 부딪히는 항목은 대개 데이터가 잘못 모델링되었다는 신호입니다.
DynamoDB의 최대 항목 크기는 얼마인가요?
DynamoDB는 단일 항목을 400 KB로 제한하며, 이는 상향 조정할 수 없는 하드 한도입니다. 크기는 속성 이름과 값을 함께 계산하며, 중첩된 모든 리스트·맵·세트 요소를 포함합니다. 항목은 보통 끝없이 커지는 임베디드 리스트처럼 무한한 성장을 통해 이 한도에 도달합니다. 해결책은 압축이 아니라 모델링, 즉 컬렉션을 별도의 항목으로 쪼개는 것입니다.
- 항목당 400 KB, 하드 상한. 조정할 수 없으며 소프트 할당량도 아닙니다.
- 크기 = 속성 이름 + 값을 합한 것. 긴 속성 이름은 모든 항목에서 크기에 포함됩니다.
- 중첩과 세트도 포함됩니다. 리스트, 맵, 그리고 그 안의 중첩된 값이 모두 합산됩니다.
- 흔한 원인은 무한한 성장 — 부모 항목에 한계 없이 커지는 리스트를 임베드하는 것입니다.
- 해결책은 압축이 아니라 모델링입니다. 커지는 컬렉션을 공유 파티션 키 아래 자체 항목으로 분리하세요.
문제: 영원히 커지는 항목
차량 플릿을 추적한다고 해봅시다. 각 차량의 텔레메트리 측정값을 차량 항목의 리스트로 저장하기로 했습니다:
PK: VEHICLE#A1 readings: [ {ts, lat, lng, fuel}, {ts, lat, lng, fuel}, ... ]하루 이틀은 괜찮습니다. 하지만 측정값은 몇 초마다 도착하고 결코 멈추지 않으므로
리스트는 한없이 커집니다. 결국 측정값 하나만 더 추가해도 항목이 400 KB를 넘게 되고,
DynamoDB는
ValidationException: Item size has exceeded the maximum allowed size로 쓰기를 거부합니다 — 업데이트할 때마다
항목 전체를 다시 쓰기 때문에, 그 차량의 텔레메트리는 더 이상 전혀 기록할 수 없습니다.
버그는 크기 한도가 아닙니다. 무한한 일대다 관계를 임베디드 리스트로 모델링한 것이 버그입니다. 그 방식은 "다" 쪽이 유한하고 작을 때만 통합니다.
실제로 400 KB에 포함되는 것
DynamoDB는 항목의 총 크기를 다음의 합으로 측정합니다:
- 모든 속성 이름, UTF-8 인코딩 기준. 수백만 개의 항목에 반복되는 20자짜리 이름은 크기이자 비용을 지불하는 스토리지입니다 — 경험 많은 모델러가 속성 이름을 짧게 유지하는 이유입니다.
- 모든 속성 값. 문자열과 바이너리는 바이트 길이로, 숫자는 압축된 인코딩으로, 불리언과 null은 아주 작은 고정 비용으로 계산됩니다.
- 중첩 구조. 리스트나 맵은 자체 오버헤드에 더해 그 안의 모든 요소와 키의 크기를 끝까지 내려가며 계산합니다.
속성별로 따로 계획해야 할 상한은 없습니다 — 항목 전체가 400 KB 선과 겨룹니다. AWS 항목 크기 문서 가 정확한 바이트 계산 방식을 설명합니다.
이 한도가 존재하는 이유
큰 항목은 옮기는 데 비용이 많이 듭니다. DynamoDB 읽기는 4 KB 단위로 과금되므로 400 KB 항목을 강력한 일관성으로 읽으면 100 RCU가 듭니다 — 그리고 항목이 커질수록 읽기, 쓰기, 복제가 모두 느려지고 비싸집니다. 이 상한은 관계형 습관에서 비롯되어 NoSQL 초보자가 흔히 손을 뻗는 "거대한 blob 하나를 가져오기" 안티패턴에서 멀어지고 작고 목적이 분명한 항목으로 향하도록 유도합니다.
이를 우회하는 모델링
플릿 예제라면 임베딩을 그만두세요. 각 측정값에 차량과 같은 파티션 안에서 자체 항목을 주고, 정렬 키에 타임스탬프로 순서를 매기세요:
PK: VEHICLE#A1 SK: READING#2026-06-27T10:00:05Z lat, lng, fuel
PK: VEHICLE#A1 SK: READING#2026-06-27T10:00:10Z lat, lng, fuel이제 어떤 항목도 커지지 않고, 쓰기가 상한을 넘을 일도 없으며, VEHICLE#A1에 대한
단일 Query는 여전히 차량의 측정값을 정렬된 하나의
항목 컬렉션으로 가져옵니다. 유한한 하위 리스트
(태그 몇 개, 고정된 설정 블록)는 임베드해도 괜찮습니다. 무한한 것은 항목이 됩니다.
DynoTable에서 항목 크기 확인하기
어떤 형태로 갈지 확정하기 전에 대표 항목의 무게를 재보세요. DynoTable에서 항목 하나를 Quick View로 열면 속성과 함께 항목의 바이트 크기를 보여 줍니다 — 실제 데이터를 둘러보는 동안, 쓰기가 실패한 뒤가 아니라 설계 시점에 너무 무거운 형태를 잡아낼 수 있습니다.
브라우저에서 처리하고 싶으신가요? DynamoDB 항목 크기 계산기가 붙여 넣은 샘플로 같은 일을 해주며, 정확한 KB와 각 읽기·쓰기에 드는 RCU/WCU를 알려 줍니다.

DynamoDB로 검증했습니다
크기 계산 규칙은 말하기는 쉬워도 미묘하게 틀리기 쉽습니다. 그래서 유일하게 의미 있는 권위, 즉 DynamoDB가 실제로 청구하는 값과 대조해 확인했습니다.
핵심은 ConsumedCapacity가 바이트가 아니라 단위를 보고하며, N바이트 쓰기에 ceil(N / 1024) WCU가 든다는 점입니다. 일반적으로는 거칠지만 경계에서는 정확합니다. 정확히 1024바이트에 떨어지도록 만든 항목은 반드시 1 WCU여야 하고, 1025바이트로 만든 항목은 반드시 2 WCU여야 하므로, 계산에서 1바이트만 틀려도 관측되는 숫자가 뒤집힙니다.
| 항목 | 우리 계산 바이트 | 예측 WCU | 실제 WCU |
|---|---|---|---|
| 정확히 1 KB | 1,024 | 1 | 1 |
| 1 KB + 1바이트 | 1,025 | 2 | 2 |
| 정확히 2 KB | 2,048 | 2 | 2 |
| 2 KB + 1바이트 | 2,049 | 3 | 3 |
| 정확히 4 KB | 4,096 | 4 | 4 |
| 혼합 타입 | 32 | 1 | 1 |
여섯 개 중 여섯 개가 일치하며, 증명을 담고 있는 것은 경계 쌍입니다. 1,024바이트와 1,025바이트 항목은 패딩 문자 하나 차이인데 DynamoDB는 둘에 다르게 과금하며, 그 지점은 정확히 우리 계산이 단차가 있다고 말하는 곳입니다.
실질적인 결과는 돈이 드는 쪽입니다. 1킬로바이트를 1바이트 넘긴 항목은 WCU 하나를 통째로 더 씁니다. 그리고 4 KB에서는 읽기 쪽에 같은 절벽이 나타납니다 — 항목을 1,025바이트에서 1,024바이트로 줄이면 쓰기 비용이 절반이 되고, 1,024에서 1,025로 늘리면 두 배가 됩니다. 속성 이름도 총합에 포함되므로, 트래픽이 많은 테이블에서 키 이름을 줄이는 것은 미세 최적화가 아닙니다.
함정과 다음 단계
- 트래픽과 함께 커지는 임베디드 리스트를 주시하세요 — 전형적인 400 KB 시한폭탄입니다. 한계를 두거나 분리하세요.
- 카디널리티가 높은 항목에서는 속성 이름을 줄이세요 — 크기와 스토리지를 공짜로 돌려받습니다.
- 큰 값은 S3에 두세요. 큰 blob(이미지, 문서)은 S3에 저장하고 항목에는 키만 남기세요.
- 관련 내용: 비정규화와 일대다 관계에서 임베드할지 분리할지 다룹니다.
테이블 전체의 실제 항목 크기를 한눈에 보고 싶으신가요? DynoTable을 다운로드해 데이터를 직접 살펴보세요.
용량 수치는 2026-07-26에 us-east-1의 실제 DynamoDB 서비스로 검증했습니다(pnpm content:verify-item-size).


