Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

66장. DynamoDB의 사고방식 — Key-Value · 파티션 키

이 장에서 말하고자 하는 것

지금까지 본 RDS · Aurora는 관계형 DB다.

테이블에 행 · 열 · 관계 · 트랜잭션이 있다

DynamoDB는 다른 세계다.

키로 단순히 값을 꺼낸다
그 대신 무제한에 가까운 확장과 한 자릿수 ms 응답을 보장한다

이 장은 DynamoDB의 사고방식을 잡는다.
구문 이전에 모델이 다르다.


1. DynamoDB는 무엇인가

  • AWS의 완전 관리형 NoSQL DB
  • 키-값 · 문서 모델
  • 서버를 관리할 필요 없음
  • 처리량을 자동으로 확장 가능
  • 단일 자릿수 밀리초 응답 (보통)
  • 멀티 AZ 자동 복제

2. 가장 큰 사고방식 차이

관계형:    "이 조건을 만족하는 행을 다 줘"
DynamoDB: "이 키를 가진 항목을 줘"

DynamoDB는 임의 검색을 잘 못 한다.
그 대신 키 기반 조회를 압도적으로 잘 한다.

DynamoDB 모델링의 70%는 “어떤 키로 무엇을 꺼낼지” 를 미리 정하는 일이다


3. Partition Key — 데이터를 어디에 둘지 결정

DynamoDB는 데이터를 여러 파티션 에 흩어서 저장한다.

파티션 키 "user_id"
   ↓ 해시
어떤 파티션에 저장될지 결정

같은 파티션 키 값을 가진 항목은 같은 파티션에 모인다.

user_id = "u-1"  →  Partition A
user_id = "u-2"  →  Partition B
user_id = "u-3"  →  Partition A   (해시가 같은 곳)

4. Sort Key — 같은 파티션 안에서 정렬

파티션 키 하나만 쓰면 한 파티션에 항목 하나밖에 못 둔다.

대부분의 테이블은 파티션 키 + 정렬 키 의 복합 키를 쓴다.

Primary Key (user_id, created_at)

user_id = "u-1", created_at = "2026-01-01" → 항목 A
user_id = "u-1", created_at = "2026-01-02" → 항목 B
user_id = "u-1", created_at = "2026-01-03" → 항목 C

이렇게 두면

“u-1 의 최근 10개 항목” 같은 쿼리가 가능해진다


5. 두 가지 조회 방식

GetItem — 키 하나로 한 항목

GetItem (user_id="u-1", created_at="2026-01-02") → 항목 B

가장 빠른 조회. O(1).

Query — 같은 파티션 안의 여러 항목

Query (user_id="u-1", created_at BETWEEN "2026-01-01" AND "2026-01-31")
→ user_id=u-1 의 1월 항목들

파티션 키는 반드시 정확히 지정해야 한다.

Scan — 모든 파티션 훑기

Scan (모든 항목 검사)

거의 항상 안 쓴다. 비싸고 느리다.

운영에서 Scan은 “데이터 마이그레이션 같은 일회성” 에만


6. Hot Partition — 가장 흔한 문제

파티션 키 선택이 잘못되면 한 파티션에 부하가 몰린다.

파티션 키 = "country"
  ↓
"KR" 파티션에 모든 한국 트래픽이 몰림 → 처리량 한계

파티션 키는 카디널리티가 높은(고유값이 많은) 필드 가 좋다
user_id · order_id · device_id 같은 것


7. 우리 서비스에서

[ECS Service "catalog"]
   ↓
[DynamoDB Table "products"]
  Primary Key: (product_id)
  
[ECS Service "sessions"]
   ↓
[DynamoDB Table "sessions"]
  Primary Key: (session_id)
  TTL on expires_at
  • 단순 키 조회 · 무제한 확장 · 일정한 응답 → DynamoDB가 자연스럽다

8. 직접 확인해보기 — CLI

테이블 만들기

aws dynamodb create-table \
  --table-name orders \
  --attribute-definitions \
      AttributeName=user_id,AttributeType=S \
      AttributeName=created_at,AttributeType=S \
  --key-schema \
      AttributeName=user_id,KeyType=HASH \
      AttributeName=created_at,KeyType=RANGE \
  --billing-mode PAY_PER_REQUEST

항목 넣기

aws dynamodb put-item \
  --table-name orders \
  --item '{
    "user_id":    {"S": "u-1"},
    "created_at": {"S": "2026-01-01"},
    "total":      {"N": "12000"}
  }'

조회

aws dynamodb query \
  --table-name orders \
  --key-condition-expression "user_id = :uid" \
  --expression-attribute-values '{":uid": {"S": "u-1"}}'

9. 코드로는 이렇게 생겼다 — Terraform

resource "aws_dynamodb_table" "orders" {
  name         = "orders"
  billing_mode = "PAY_PER_REQUEST"
  hash_key     = "user_id"
  range_key    = "created_at"

  attribute {
    name = "user_id"
    type = "S"
  }

  attribute {
    name = "created_at"
    type = "S"
  }

  point_in_time_recovery {
    enabled = true
  }

  server_side_encryption {
    enabled = true
  }
}

PAY_PER_REQUEST 는 사용량 기반 과금. 시작에 좋다.


10. 이렇게 쓰면 망한다 — 안티패턴

안티패턴 1. SQL 식 사고로 모델링한다

“정규화” 하면 조회마다 N번 Get을 부르게 된다.

DynamoDB는 읽는 모양에 맞춰 데이터를 미리 배치 한다
“쓰기에서 일을 해서 읽기를 단순하게”

안티패턴 2. 카디널리티 낮은 필드를 파티션 키로

hot partition 발생. 한 파티션 부하가 한계에 닿는다.

안티패턴 3. Scan을 일상적으로 쓴다

비용 · 지연 다 폭발한다.

Scan은 일회성 마이그레이션이나 분석용으로만

안티패턴 4. Point-in-time recovery를 안 켠다

실수로 데이터를 지웠을 때 복구가 안 된다.

운영 테이블은 무조건 PITR 켜기


11. 한 줄로 정리

DynamoDB는 키로 값을 꺼내는 모델이며,
“어떻게 읽을지” 를 먼저 정하고 그에 맞춰 데이터를 배치하는 사고방식이다


12. 이 장의 핵심 정리

  1. DynamoDB는 키-값/문서 모델의 NoSQL이다.
  2. Partition Key는 데이터를 어디에 둘지, Sort Key는 그 안의 순서를 결정한다.
  3. GetItem · Query 는 빠르고, Scan 은 거의 안 쓴다.
  4. 카디널리티 높은 필드를 파티션 키로 잡아 hot partition을 피한다.
  5. “읽는 모양에 맞춰 데이터를 미리 배치한다” 가 모델링의 핵심이다.
  6. 운영 테이블은 PITR + 암호화가 출발선이다.