CertNote/ 출퇴근 학습 노트
로드맵
KOEN
CLF-C02 · FoundationalCloud Practitioner - Foundational
DVA-C02 · AssociateDeveloper - Associate
  • Week 1
    • 1.개발자 시점에서 본 AWS: 리전, 인프라, 그리고 책임의 경계
    • 2.IAM의 4대 엔터티: User, Group, Role, Policy
    • 3.STS와 정책 조건: 임시 자격증명의 깊은 세계
    • 4.AWS CLI와 SDK: 자격증명 체이닝부터 SigV4까지
    • 5.Week 1 종합: 인프라와 IAM이 만드는 신뢰의 사슬
  • Week 2
  • Week 3
  • Week 4
  • Week 5
  • Week 6
    • 1.DynamoDB: NoSQL의 철학과 파티션 설계의 수학
    • 2.DynamoDB: 파티션 키 설계의 수학, LSI/GSI 내부 동작, Single-Table Design
    • 3.DynamoDB: RCU/WCU 수학, DAX 아키텍처, Streams 처리
    • 4.DynamoDB: 트랜잭션, 조건부 쓰기, TTL의 내부 동작
    • 5.Week 6 종합 복습: DynamoDB 전체 지형도
  • Week 7
  • Week 8
  • Week 9
  • Week 10
  • Week 11
  • Week 12
  • Week 13
SAA-C03 · AssociateSolutions Architect - Associate
SOA-C02 · AssociateCloudOps Engineer - Associate
SAP-C02 · ProfessionalSolutions Architect - Professional
DOP-C02 · ProfessionalDevOps Engineer - Professional
SCS-C03 · SpecialtySecurity - Specialty
MLA-C01 · AssociateMachine Learning Engineer - Associate
AIF-C01 · FoundationalAI Practitioner - Foundational
DEA-C01 · AssociateData Engineer - Associate
MLS-C01 · SpecialtyMachine Learning - Specialty
합격 후기

© CertNote · 주간랩스

  • 소개
  • 수정 기록
  • 문의
  • 이용약관
  • 개인정보처리방침
← DVA-C02/Week 6/Day 5

기준: DVA-C02 시험 가이드·오류 제보

DVA-C02· AssociateWeek 6 · Day 5읽기 약 19분

Day 5 - Week 6 종합 복습: DynamoDB 전체 지형도

Week 6의 마지막 날이다. DynamoDB는 DVA-C02 범위의 핵심 서비스이고, API 이름만 외워서는 변형 문제를 풀기 어렵다. 이 day에서는 한 주간 배운 내용을 하나의 지형도로 연결한다. 대상은 파티션 키 설계 수학, 읽기 일관성 모델, LSI/GSI 내부 차이, DAX 캐시 계층, Streams + Lambda 연동, 트랜잭션 2PC, TTL 비동기 삭제이고, 마지막에 종합 문제를 푼다. 모든 항목을 "파티션 수준에서 데이터가 어떻게 저장되고 읽히는가"라는 관점으로 본다.

DynamoDB 전체 아키텍처 지형도

클라이언트 요청
      │
      ▼
  [DAX 클러스터]  ─── 캐시 히트 → μs 반환
      │ 캐시 미스
      ▼
[DynamoDB 요청 라우터]
      │
      ▼
[파티션 메타데이터 서비스]
  파티션 키 → 해시 → 담당 스토리지 노드 결정
      │
      ▼
[스토리지 노드 (B-Tree + WAL)]
  Primary Node ──복제──► Replica 1
               ──복제──► Replica 2 (3개 AZ 분산)
      │
      ├── 읽기 (Eventually Consistent): Replica 어느 것이든
      ├── 읽기 (Strongly Consistent): Primary만
      └── 쓰기: Primary → WAL → 복제 완료
      │
      ▼
[DynamoDB Streams 샤드]  (변경 24시간 보존)
      │
      ▼
[Lambda ESM 폴링]
  배치 처리 → BisectBatchOnFunctionError → DLQ

AWS가 2022년 USENIX ATC에 낸 DynamoDB 논문에 따르면, 각 파티션의 복제본은 Write-Ahead Log(WAL)와 키-값 데이터를 담는 B-tree로 구성된다. 쓰기 요청이 오면 리더(Primary) 복제본이 WAL 레코드를 만들어 다른 복제본에 보내고, 쿼럼(과반) 복제본이 그 레코드를 각자의 WAL에 영속화하면 애플리케이션에 성공을 응답한다. 나머지 복제본은 그 뒤에 따라온다. Eventually Consistent 읽기는 어느 복제본이든 처리할 수 있어, 아직 최신 쓰기를 반영하지 않은 복제본에서 오래된 데이터를 볼 수 있다. Strongly Consistent 읽기는 Primary에서만 읽으므로 항상 최신이지만 RCU를 2배 소비한다.

파티션 키 설계 — 핫 파티션 수학

파티션 한도: 3,000 RCU + 1,000 WCU + 10GB

항목이 특정 파티션에 집중되면 그 파티션이 한도에 도달해 ProvisionedThroughputExceededException이 발생한다(hot partition 문제).

나쁜 파티션 키 예시:
  status = "PENDING" → 대부분의 새 주문이 한 파티션에 집중
  date = "2026-06-27" → 오늘 데이터가 모두 한 파티션

좋은 파티션 키 예시:
  orderId = UUID → 무작위 분산
  userId + timestamp → 사용자별 분산 + 시간 정렬

Write Sharding 패턴:
  partition_key = userId + "#" + str(random.randint(0, 9))
  → 동일 userId가 10개 파티션에 분산
  → 읽을 때 0~9 모두 Query 후 병합 필요

Adaptive Capacity는 2018년 도입된 기능으로, 한 파티션의 트래픽이 증가하면 다른 파티션의 잉여 용량을 자동으로 이동시켜 핫 파티션이 프로비저닝된 용량을 초과해도 일시적으로 버틸 수 있게 한다. 또한 Burst Capacity는 파티션이 마지막 300초(5분) 동안 사용하지 않은 용량을 최대 300초치 예비로 축적하고, 갑작스러운 스파이크 시 이를 소진한다. Adaptive Capacity와 Burst Capacity는 자동 동작하지만 지속적인 핫 파티션에는 근본 해결책이 되지 않는다.

RCU/WCU 수학 빠른 정리

읽기 (기준: 4KB, ceil 올림):
  Eventually Consistent = ceil(size/4KB) × 0.5
  Strongly Consistent   = ceil(size/4KB) × 1
  Transactional Read    = ceil(size/4KB) × 2

쓰기 (기준: 1KB, ceil 올림):
  Standard Write        = ceil(size/1KB) × 1
  Transactional Write   = ceil(size/1KB) × 2

핵심: 읽기는 4KB 기준, 쓰기는 1KB 기준 → 같은 항목에서 WCU가 RCU보다 4배 많이 필요

계산 예시:

6.5KB 항목, 강력한 일관성, 초당 40회:
  ceil(6.5/4) = 2 → 2 × 1 × 40 = 80 RCU

3KB 항목, 트랜잭션 쓰기, 초당 20회:
  ceil(3/1) = 3 → 3 × 2 × 20 = 120 WCU

⚠️ 함정: FilterExpression은 RCU를 절감하지 않는다. 조건에 맞지 않는 항목도 읽기 후 필터링하므로 RCU는 이미 소비된다. RCU를 절약하려면 KeyConditionExpression으로 읽을 항목 수 자체를 줄여야 한다. GSI를 만들어 조회 패턴에 맞는 파티션 키를 부여하는 것이 올바른 접근이다.

LSI vs GSI 내부 동작 비교

항목LSIGSI
PK기본 테이블과 동일다른 속성 가능
SK다른 속성다른 속성 가능
생성 시점테이블 생성 시에만언제든 추가/삭제
최대 개수5개20개 (기본 한도, 증가 요청 가능)
일관성 모델Eventually + Strongly 모두 지원Eventually Consistent만
용량기본 테이블 용량 공유별도 RCU/WCU 설정
Sparse Index지원지원
스토리지 구조기본 테이블과 같은 파티션에 함께 저장완전히 별도의 파티션 공간

LSI는 기본 테이블과 동일한 파티션 키를 공유하므로 같은 파티션 내에 함께 저장된다. 이 덕분에 기본 테이블의 Primary 노드가 LSI 데이터도 함께 관리해 Strongly Consistent 읽기가 가능하다. GSI는 완전히 별도의 파티션 공간에 비동기 복제되므로 복제 지연이 존재하고 Eventually Consistent만 지원한다. "GSI는 별개의 테이블"이라고 생각하면 이 차이가 자연스럽다.

Sparse Index 패턴: 모든 항목이 가지지 않는 속성을 GSI의 파티션 키로 쓰면, 그 속성이 있는 항목만 GSI에 나타난다.

Users 테이블:
  userId(PK) | email | isPremium (일부만 있음)

GSI: isPremium-index
  PK = isPremium → isPremium 속성 있는 항목만 인덱싱
  Query "isPremium = true" → 프리미엄 사용자만 효율적 조회
  isPremium 없는 일반 사용자는 GSI에 아예 없음 → 저장 비용 절감

Sparse Index 예시: 예약 상태가 "PENDING"인 항목에만 pendingAt 속성을 부여해 GSI의 PK로 쓴다. 예약이 확정되면 pendingAt을 삭제해 GSI에서 자동으로 제거된다. 전체 테이블 Scan 없이 "현재 PENDING 예약 전체"를 GSI Query로 O(PENDING 수)에 조회할 수 있다.

DAX 캐시 계층 — 언제 우회하는가

DAX 캐시 적용:
  GetItem → Item Cache (기본 TTL 5분)
  Query   → Query Cache (기본 TTL 5분)
  Scan    → Query Cache

DAX 캐시 우회 (DynamoDB 직접):
  ConsistentRead=true 강력한 일관성 읽기
  TransactGetItems
  모든 쓰기 (Put/Update/Delete)

DAX 쓰기는 Write-Through: DynamoDB 먼저 쓰고 → Item Cache 업데이트 → 완료 반환. Write-Back이 아니므로 데이터 손실 없음.

⚠️ 함정: DAX는 VPC 내부에서만 접근 가능하다. 인터넷에서 직접 접근 불가. Lambda가 DAX를 사용하려면 Lambda도 같은 VPC에 있어야 하고, DAX 클러스터의 보안 그룹에서 Lambda의 보안 그룹을 허용해야 한다. DAX 클러스터는 최소 3개 노드(Multi-AZ)로 구성해야 고가용성이 보장된다.

DynamoDB Streams + Lambda ESM 상세

Stream 뷰 유형:
  KEYS_ONLY:          PK + SK만 (가장 저렴)
  NEW_IMAGE:          변경 후 전체 항목
  OLD_IMAGE:          변경 전 전체 항목
  NEW_AND_OLD_IMAGES: 변경 전/후 모두 (감사 로그)

Lambda ESM 핵심 설정:
  BatchSize:                    1~10,000 레코드
  BisectBatchOnFunctionError:   오류 시 배치 반으로 분할 재시도
  MaximumRetryAttempts:         최대 재시도 횟수 (기본: 무한)
  DestinationConfig:            실패 레코드 → SQS DLQ 또는 SNS
  ParallelizationFactor:        샤드당 병렬 Lambda 수 (1~10)
  FilterCriteria:               특정 이벤트 패턴만 Lambda 트리거

DynamoDB Streams는 내부적으로 Kinesis 기반 아키텍처로 동작한다. 각 파티션마다 하나의 Stream 샤드가 존재하고, 샤드 내에서는 파티션 키 단위 이벤트 순서가 보장된다. Lambda ESM은 샤드를 폴링하는 방식이다 — Streams가 Lambda를 "push"하는 게 아니라 Lambda가 Streams를 "pull"한다. ParallelizationFactor=10으로 설정하면 하나의 샤드를 10개 Lambda가 병렬 처리하지만 같은 파티션 키의 이벤트 순서 보장이 복잡해진다.

FilterCriteria 예시 — INSERT 이벤트만 처리:

{
  "Filters": [
    {
      "Pattern": "{\"eventName\": [\"INSERT\"]}"
    }
  ]
}

Lambda 함수 내 TTL 삭제 이벤트 식별:

def handler(event, context):
    for record in event['Records']:
        if record['eventName'] == 'REMOVE':
            user_identity = record.get('userIdentity', {})
            if user_identity.get('type') == 'Service':
                # TTL에 의한 자동 삭제 → 비즈니스 로직 건너뜀
                continue
            # 명시적 DeleteItem 호출 → 감사 로그 기록
            log_deletion(record['dynamodb']['OldImage'])

가상의 사례로, 주문 완료 시 DynamoDB Streams로 이벤트를 받아 검색 인덱스를 갱신하는 Lambda가 BatchSize=100으로 설정돼 있다. 주문이 급증해 처리가 지연되고 Lambda 타임아웃으로 배치 전체가 실패하면, 같은 100개 레코드를 반복 재시도하는 루프에 빠진다. BisectBatchOnFunctionError=true와 DestinationConfig(DLQ)를 설정하면 독성 메시지(Poison Pill)는 DLQ로 격리하고 정상 레코드는 계속 처리할 수 있다.

트랜잭션 vs 조건부 쓰기 선택 기준

단일 항목, 조건 필요 → ConditionExpression (빠르고 저렴)
여러 항목 원자성 필요 → TransactWriteItems (2× 비용)
읽기와 쓰기 원자성 필요 → TransactGetItems + TransactWriteItems
멱등한 API 요청 → ClientRequestToken (10분 유효)
시나리오추천 API이유
중복 주문 방지PutItem + attribute_not_exists단일 항목, 조건만 필요
재고 차감 + 주문 생성TransactWriteItems두 테이블 원자성 필요
동시 수정 충돌 감지UpdateItem + version 조건Optimistic Locking
대량 데이터 적재BatchWriteItem원자성 불필요, 속도 우선
선착순 쿠폰 클레임UpdateItem + attribute_not_exists단일 항목, First-Write-Wins

PITR vs On-Demand Backup vs TTL

항목PITROn-Demand BackupTTL
목적실수 복구장기 보존 스냅샷임시 데이터 자동 삭제
보존 기간최대 35일 (초 단위 복원)무기한0~48시간 내 비동기 삭제
비용GB당 추가 과금GB당 추가 과금무료 (WCU 소비 없음)
복원 대상새 테이블로만새 테이블로만-
자동화자동 (활성화 시)수동 또는 AWS Backup자동

PITR이 35일 제한인 이유는 AWS 내부적으로 변경 로그(WAL)를 35일 보존하기 때문이다. Kinesis Data Streams for DynamoDB를 추가 연결하면 변경 이력을 최대 365일 보존할 수 있다. Kinesis Firehose → S3로 파이프라인을 구성하면 S3 수명 주기 정책으로 수년간 보존할 수 있다. 장기 감사 로그가 필요하면 Streams + Kinesis가 정석이다.

Global Tables — Active-Active 설계의 함의

충돌 해결: Last Writer Wins (최신 타임스탬프 우선)
복제 방식: DynamoDB Streams 기반 비동기
일관성:   각 리전에서 로컬 강력한 일관성만 가능
요건:     Streams 활성화 필수, 온디맨드 or 동일 프로비저닝

Global Tables를 쓸 때 알아야 하는 함정: "글로벌 Strongly Consistent"는 존재하지 않는다. 서울에서 쓴 데이터가 버지니아에 복제되기 전에 버지니아에서 강력한 일관성 읽기를 해도 서울의 최신 데이터를 볼 수 없다. 각 리전은 자신의 로컬 복제본 기준으로만 일관성을 보장한다.

Global Tables에서 두 리전이 동시에 같은 항목을 수정하면 Last Writer Wins로 충돌이 해결된다. 두 리전 모두 성공 응답을 반환했는데 한 쪽의 쓰기가 최종적으로 덮어써진다. 금융 데이터처럼 양쪽 쓰기 모두 영구적이어야 하는 경우 Global Tables의 충돌 해결 정책이 부적합할 수 있다. 이런 경우 단일 "primary" 리전에서만 쓰기를 허용하고 다른 리전은 읽기만 하는 아키텍처를 택해야 한다.

핵심 수치 암기표

항목 최대 크기:          400KB
트랜잭션 최대:           100개 항목, 4MB
BatchWriteItem:          25개 항목, 16MB
BatchGetItem:            100개 항목, 16MB
Streams 보존:            24시간 (고정)
Kinesis for DDB 보존:    최대 365일
PITR 복원 창:            35일
TTL 삭제 지연:           0~48시간
온디맨드 모드 전환:       24시간에 1회
파티션 한도:             3,000 RCU + 1,000 WCU + 10GB
GSI 기본 최대:           20개
LSI 최대:                5개 (생성 시만)
DAX 기본 TTL:            5분 (Item Cache, Query Cache)
트랜잭션 ClientRequestToken: 10분 유효

📝 연습 문제

선택지를 클릭하면 정답·해설이 펼쳐집니다.

문제 1

4KB 항목을 최종 일관성으로 초당 200회, 강력한 일관성으로 초당 100회 읽는다. 총 프로비저닝 RCU는?

문제 2

DynamoDB GSI에 대한 설명 중 옳지 않은 것은?

문제 3

DynamoDB Streams에서 Lambda ESM의 BisectBatchOnFunctionError=true를 설정했을 때 동작은?

문제 4

DAX를 사용 중인 애플리케이션에서 금융 계좌 잔액을 조회할 때 항상 최신 값을 보장해야 한다. 올바른 접근법은?

문제 5

DynamoDB 테이블의 온디맨드 모드에서 초당 요청이 갑자기 기존 최고치의 5배로 증가했다. 어떤 현상이 발생하는가?

문제 6

status = "ACTIVE" 속성이 있는 사용자만 GSI에 인덱싱하려 한다. 가장 효율적인 방법은?

문제 7

DynamoDB Streams의 NEW_AND_OLD_IMAGES 뷰 타입을 사용하는 가장 적합한 시나리오는?

문제 8

정답 2개 선택

다음 중 DynamoDB TTL에 대한 올바른 설명을 모두 고르시오.

문제 9

DynamoDB 테이블에 orderId(PK), createdAt(SK), category가 있다. "특정 category의 주문을 createdAt 오름차순으로 조회"하려 한다. 가장 효율적인 인덱스 설계는?

문제 10

전자상거래 플랫폼에서 주문 이벤트를 DynamoDB에 저장하고, 새 주문(INSERT) 시 실시간 알림을 보내야 한다. INSERT 이벤트만 처리하도록 Lambda를 구성하는 가장 효율적인 방법은?

문제 11

DynamoDB TransactWriteItems에서 ConditionCheck 액션의 역할은?

문제 12

DynamoDB 단일 테이블 설계(Single-Table Design)에서 엔티티 타입별 쿼리를 지원하는 일반적인 패턴은?

이전DynamoDB: 트랜잭션, 조건부 쓰기, TTL의 내부 동작Week 6 · Day 4다음 RDS: 관리형 RDBMS의 두 얼굴, Multi-AZ와 Read ReplicaWeek 7 · Day 1

참고 공식 자료

  • DVA-C02 공식 시험 안내(새 탭에서 열림)
  • Amazon DynamoDB 공식 문서(새 탭에서 열림)
  • AWS Lambda 공식 문서(새 탭에서 열림)
  • Amazon Kinesis 공식 문서(새 탭에서 열림)

이 페이지

  • DynamoDB 전체 아키텍처 지형도
  • 파티션 키 설계 — 핫 파티션 수학
  • RCU/WCU 수학 빠른 정리
  • LSI vs GSI 내부 동작 비교
  • DAX 캐시 계층 — 언제 우회하는가
  • DynamoDB Streams + Lambda ESM 상세
  • 트랜잭션 vs 조건부 쓰기 선택 기준
  • PITR vs On-Demand Backup vs TTL
  • Global Tables — Active-Active 설계의 함의
  • 핵심 수치 암기표
  • Week 6 종합 연습 문제