
DynamoDB 완전 정복: Amazon이 논문 한 편으로 시작한 NoSQL 혁명
2007년 Amazon 내부 논문에서 시작해, 전 세계 10조 건 이상의 요청을 하루에 처리하는 서비스가 되기까지. Dynamo 논문의 핵심 아이디어, Single Table Design의 철학, 그리고 실전 사례와 주의점을 풀어본다.

2007년 Amazon 내부 논문에서 시작해, 전 세계 10조 건 이상의 요청을 하루에 처리하는 서비스가 되기까지. Dynamo 논문의 핵심 아이디어, Single Table Design의 철학, 그리고 실전 사례와 주의점을 풀어본다.
2004년 크리스마스 시즌, Amazon.com에서 최악의 시나리오가 벌어졌다. 주문이 폭주하면서 관계형 데이터베이스가 한계에 도달했다. 일부 사용자의 장바구니 데이터가 유실됐고, 주문 처리가 지연됐다. 연중 가장 중요한 매출 시즌에.
문제의 핵심: Amazon의 핵심 서비스들(장바구니, 세션 관리, 추천) — 은 단순한 키-값 조회가 대부분이었다. "이 사용자의 장바구니를 가져와라." 이 작업에 관계형 DB의 복잡한 조인(JOIN), 트랜잭션, 스키마가 필요한가? 오히려 이 복잡성이 확장을 가로막는 병목이 되고 있었다.
Amazon의 엔지니어들은 근본적인 질문을 던졌다:
"모든 데이터가 정말 관계형 모델이 필요한가? 아니면 더 단순하고 더 확장 가능한 모델이 있는가?"
이 질문에서 시작된 프로젝트가 Dynamo이고, 그 아이디어를 서비스로 만든 것이 DynamoDB다.
2007년 10월, Amazon의 엔지니어 Giuseppe DeCandia 등 7명이 ACM SOSP(운영체제 원리 심포지엄)에서 논문을 발표했다:
"Dynamo: Amazon's Highly Available Key-value Store"
이 논문은 컴퓨터 과학 역사에서 가장 영향력 있는 시스템 논문 중 하나가 됐다. 인용 횟수 5,000회 이상. 이 한 편의 논문이 NoSQL 운동 전체의 도화선이 됐다.
Dynamo는 전통적 데이터베이스의 상식을 뒤집었다:
CAP 정리와의 관계:
UC Berkeley의 Eric Brewer가 2000년에 제안한 CAP 정리(CAP Theorem): 분산 시스템은 일관성(Consistency), 가용성(Availability), 파티션 허용성(Partition Tolerance) 중 세 가지를 동시에 만족할 수 없다.
네트워크 파티션은 분산 시스템에서 피할 수 없으므로, 결국 C(일관성)와 A(가용성) 중 하나를 선택해야 한다. 전통적 RDBMS는 C를 선택했고, Dynamo는 A를 선택했다.
논문에서 소개된 기술들은 이후 모든 분산 데이터베이스의 교과서가 됐다:
1. 일관된 해싱(Consistent Hashing): 데이터를 여러 노드에 균등하게 분배하는 방법. 노드가 추가되거나 제거되어도 최소한의 데이터만 이동한다.
2. 벡터 클럭(Vector Clocks): 여러 노드에서 동시에 데이터가 수정됐을 때 충돌을 감지하고 해결하는 방법.
3. 쿼럼 기반 복제: N개 노드에 복제하고, W개 노드에 쓰기 성공하면 쓰기 완료, R개 노드에서 읽으면 읽기 완료. W+R > N이면 일관성을 보장하지만, Amazon은 W+R ≤ N으로 설정하여 가용성을 우선시했다.
4. 가십 프로토콜(Gossip Protocol): 노드들이 서로의 상태 정보를 "소문"처럼 퍼뜨려 장애를 감지하는 분산 프로토콜.
Dynamo 논문의 영향으로 탄생한 프로젝트들:
| 프로젝트 | 시기 | Dynamo에서 가져온 것 |
|---|---|---|
| Apache Cassandra | 2008 (Facebook) | 일관된 해싱, 가십 프로토콜 |
| Apache HBase | 2008 | 분산 스토리지 모델 |
| Riak | 2009 | Dynamo 아키텍처 거의 그대로 |
| Voldemort | 2009 (LinkedIn) | 키-값 모델, 일관된 해싱 |
| DynamoDB | 2012 (AWS) | Dynamo + SimpleDB의 결합 |
혼동하기 쉽지만, Dynamo(2007 내부 시스템)와 DynamoDB(2012 AWS 서비스)는 다르다. DynamoDB는 Dynamo의 아이디어에 SimpleDB(AWS의 초기 NoSQL 서비스)의 교훈을 결합하여 새로 만든 것이다.
2012년 1월 출시 시 Werner Vogels(Amazon CTO)는 이렇게 말했다:
"DynamoDB가 목표로 하는 것은 분명하다. 개발자가 규모에 대해 걱정하지 않는 것."
DynamoDB는 RDS와 근본적으로 다른 서비스다:
| 특성 | RDS (관계형) | DynamoDB (NoSQL) |
|---|---|---|
| 데이터 모델 | 테이블, 행, 열, 관계 | 키-값 + 문서 |
| 스키마 | 고정 (ALTER TABLE) | 유연 (항목마다 다를 수 있음) |
| 쿼리 | SQL (JOIN, GROUP BY 등) | 키 기반 조회, Scan, Query |
| 스케일링 | 수직 (인스턴스 크기) | 수평 (자동 파티셔닝) |
| 지연 시간 | 수~수십 ms | 일정하게 < 10ms |
| 관리 | 인스턴스 선택 필요 | 완전 서버리스 가능 |
| 트랜잭션 | 완전한 ACID | 제한적 트랜잭션 (2018~) |
| 적합한 경우 | 복잡한 관계, 분석 쿼리 | 대규모 읽기/쓰기, 예측 가능한 접근 패턴 |
{
"PK": "USER#u123",
"SK": "PROFILE",
"name": "김개발",
"email": "kim@example.com",
"plan": "pro",
"created_at": "2026-01-15"
}
DynamoDB에서 가장 중요한 설계 결정은 키 구조다.
파티션 키(Partition Key, PK): 데이터가 물리적으로 어떤 파티션에 저장될지 결정한다. 해시 함수를 통해 데이터를 여러 파티션에 분배한다.
정렬 키(Sort Key, SK): 같은 파티션 내에서 데이터를 정렬한다. 범위 쿼리(BETWEEN, begins_with)가 가능해진다.
date로 설정하면, 오늘 날짜의 파티션에 모든 쓰기가 몰린다. 카디널리티가 높은 키(사용자 ID, 주문 ID 등)를 파티션 키로 선택하라.관계형 DB에서는 엔티티별로 테이블을 만든다: users, orders, products, reviews. DynamoDB에서는 하나의 테이블에 모든 엔티티를 저장하는 패턴이 권장된다. 이것이 Single Table Design(단일 테이블 설계)이다.
AWS의 DynamoDB 수석 에반젤리스트 Rick Houlihan이 2018~2019년 re:Invent에서 이 개념을 집중적으로 소개하며 커뮤니티에 퍼졌다. 그의 세션은 DynamoDB 역사상 가장 많이 시청된 강연 중 하나다.
관계형 DB의 접근: 데이터를 정규화하여 여러 테이블에 분리하고, 쿼리 시 JOIN으로 합친다.
-- RDS: 사용자와 주문을 JOIN으로 조회
SELECT u.name, o.order_id, o.total
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE u.id = 'u123';
DynamoDB의 접근: JOIN이 없다. 대신, 관련 데이터를 같은 파티션에 미리 모아놓는다.
PK SK 속성들
─────────────── ─────────────────── ──────────────
USER#u123 PROFILE name: "김개발", email: ...
USER#u123 ORDER#2026-03-01 total: 45000, items: [...]
USER#u123 ORDER#2026-03-15 total: 12000, items: [...]
USER#u123 ORDER#2026-03-18 total: 89000, items: [...]
이제 PK = USER#u123으로 Query하면, 프로필과 모든 주문이 한 번의 조회로, 한 자릿수 ms로 반환된다. JOIN이 없으므로 테이블 크기가 커져도 성능이 일정하다.
S3 버킷 공개 사고만큼 대중적이지는 않지만, DynamoDB 관련 보안 사고도 발생했다:
2019년 — Capital One 사고의 DynamoDB 연결고리: 이전 RDS 글에서 다룬 Capital One 사고에서, 공격자는 탈취한 IAM 자격증명으로 S3뿐 아니라 DynamoDB 테이블에도 접근했다. 문제는 DynamoDB 테이블에 과도한 IAM 권한이 부여되어 있었던 것.
2020~2022년 — IAM 키 유출을 통한 데이터 탈취: GitHub에 실수로 커밋된 AWS IAM 키를 통해 DynamoDB 테이블의 데이터가 유출되는 사례가 다수 보고됐다. DynamoDB는 네트워크 격리(VPC 엔드포인트)와 IAM 정책이 유일한 방어선이므로, IAM 키 관리가 핵심이다.
dynamodb:GetItem만 필요하면 dynamodb:*를 주지 마라| 온디맨드 (On-Demand) | 프로비저닝 (Provisioned) | |
|---|---|---|
| 과금 | 요청 건당 | 초당 읽기/쓰기 용량(RCU/WCU)에 따라 |
| 스케일링 | 자동 (즉시) | 수동 또는 Auto Scaling |
| 트래픽이 없을 때 | 비용 0원 (저장 비용만) | 프로비저닝된 용량에 과금 |
| 비용 수준 | 요청당 비용 높음 | 단가 낮지만 유휴 비용 발생 |
| 적합한 경우 | 트래픽 예측 어려움, 초기 서비스 | 트래픽 예측 가능, 대규모 |
DynamoDB와 Lambda는 AWS 서버리스 아키텍처의 황금 조합이다. 둘 다 서버 관리 불필요, 자동 스케일링, 사용량 과금.
이 전체 스택에서 관리해야 할 서버: 0대. 트래픽이 없으면 비용: 거의 0원. 트래픽이 폭증하면: 자동 확장.
DynamoDB Streams는 테이블의 모든 변경(추가/수정/삭제)을 실시간 이벤트 스트림으로 제공한다. Lambda를 트리거로 연결하면:
Amazon.com 자체가 DynamoDB의 가장 큰 사용자다. 프라임데이(Prime Day)에 초당 수천만 건의 요청을 DynamoDB가 처리한다. 2023년 프라임데이에 DynamoDB는 피크 초당 1억 2,600만 건의 요청을 처리했다고 AWS가 발표했다.
수백만 대의 차량 위치를 실시간으로 추적하는 Lyft는 DynamoDB를 사용한다. 차량 위치 업데이트는 초당 수백만 건이며, 각 업데이트에 한 자릿수 ms 응답이 필요하다 — DynamoDB의 완벽한 유스케이스다.
이전 글들에서 반복 등장한 Samsung SmartThings. 수억 대의 IoT 기기 상태 데이터를 DynamoDB에 저장한다. 기기 상태 조회가 대부분이고, 한 자릿수 ms 응답이 필수.
4억 명 이상의 사용자의 학습 진행 상태, 스트릭(streak), 리더보드 데이터를 DynamoDB에 저장한다.
DynamoDB는 만능이 아니다. 이런 경우에는 RDS/Aurora가 더 적합하다:
| 상황 | 이유 | 대안 |
|---|---|---|
| 복잡한 JOIN이 필요 | DynamoDB에 JOIN 없음 | RDS, Aurora |
| 접근 패턴이 불확실 | Single Table Design은 패턴이 확정돼야 함 | PostgreSQL |
| 분석/리포팅 쿼리 | ad-hoc 쿼리에 부적합 | Athena, Redshift |
| 강력한 트랜잭션 | 제한적 트랜잭션만 지원 | Aurora, PostgreSQL |
| 관계형 데이터 모델 | 정규화된 관계를 표현하기 어려움 | RDS |
| 비용 예측이 어려움 | 잘못된 키 설계 시 비용 폭증 가능 | RDS (인스턴스 고정비) |
Dynamo 논문에서 시작된 혁명의 핵심 메시지는 이것이다:
"데이터의 특성에 맞는 데이터베이스를 선택하라."
2000년대까지는 "데이터베이스 = 관계형 DB"였다. 모든 데이터를 MySQL이나 Oracle에 넣었다. 하지만 모든 데이터가 복잡한 관계를 가지는 것은 아니다. 장바구니는 키-값이고, 로그는 시계열이고, 소셜 그래프는 그래프 DB가 적합하다.
이것을 다중 모델 아키텍처(Polyglot Persistence) 라고 부른다. Martin Fowler가 2011년에 정리한 이 개념은 2026년 현재 대부분의 기업이 실천하고 있다:
코어닷투데이의 AI 서비스에서도 이 패턴은 동일하다. AI 모델 메타데이터는 DynamoDB에 빠르게 조회하고, 학습 데이터는 S3에 저장하고, 사용자 관계 데이터는 Aurora에 보관한다. 각 데이터의 특성에 맞는 최적의 저장소를 선택하는 것 — 그것이 Dynamo 논문이 18년 전에 던진 질문의 현재 답이다.