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
  • Week 7
  • Week 8
  • Week 9
  • Week 10
  • Week 11
  • Week 12
  • Week 13
    • 1.최종 복습 1: IAM, EC2, Lambda, API Gateway
    • 2.최종 복습 2: S3, DynamoDB, RDS, ElastiCache
    • 3.최종 복습 3: 보안, 모니터링, CI/CD
    • 4.최종 복습 4: 메시징, 컨테이너, 아키텍처 패턴
    • 5.최종 모의고사 + 시험 준비 완료
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 13/Day 2

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

DVA-C02· AssociateWeek 13 · Day 2읽기 약 14분

Day 2 - 최종 복습 2: S3, DynamoDB, RDS, ElastiCache

📅 날짜: 2026년 8월 10일 (월요일)
🎯 주제: 스토리지 및 데이터베이스 최종 복습
⏱️ 학습 시간: 약 120분


🎯 학습 목표

  • S3, DynamoDB, RDS, ElastiCache의 시험 핵심을 최종 정리한다
  • 데이터베이스 선택 시나리오 문제를 풀어본다

📖 핵심 암기표

S3 핵심 암기

최대 객체 크기: 5TB
멀티파트: 5GB+ 필수, 100MB+ 권장
스토리지 클래스: Standard > IA(30일) > Glacier(90일) > Deep Archive(180일)
암호화: SSE-S3(AWS관리), SSE-KMS(KMS), SSE-C(고객키제공+HTTPS)
Block Public Access: 버킷 정책 Override
HTTPS 강제: aws:SecureTransport=false Deny
버전 관리: 삭제 마커, Suspend만 가능 (비활성화 불가)
CRR/SRR: 버전 관리 필수, 기존 객체 자동 복제 안 됨
프리사인 URL: 최대 7일, PUT으로 직접 업로드
정적 웹사이트: HTTP만, HTTPS는 CloudFront+ACM

DynamoDB 핵심 암기

항목 최대 크기: 400KB
RCU: 강력한(1/4KB), 최종적(0.5/4KB), 트랜잭션(2/4KB)
WCU: 1/1KB, 트랜잭션 2/1KB
LSI: 같은 PK, 다른 SK, 생성 시만, 강력 일관성 지원
GSI: 다른 PK/SK, 언제든, 최종적만, 별도 용량
Streams: 24시간 보존, 4가지 뷰 유형
TTL: 무료, 48시간 내 비동기 삭제
트랜잭션: 최대 25개 항목, 4MB, 비용 2배
Optimistic Locking: 버전 번호로 동시 수정 방지

RDS 핵심 암기

Multi-AZ: 동기 복제, 자동 Failover, 고가용성
Read Replica: 비동기 복제, 읽기 확장, 최대 15개
암호화 변경: 스냅샷 → 암호화 복사 → 새 DB
IAM 인증 토큰: 15분 유효
자동 백업: 최대 35일, DB 삭제 시 함께 삭제
수동 스냅샷: 무기한, DB 삭제 후 유지
Aurora: 3AZ 6사본, MySQL 5배, Serverless, 글로벌 DB(1초 미만)

ElastiCache 핵심 암기

Redis: 영속성, 백업, Multi-AZ, 복잡한 자료구조
Memcached: 단순, 멀티스레드, 영속성 없음
Lazy Loading: Cache Miss → DB 조회 → 캐시 저장
Write-Through: 쓰기 시 캐시도 업데이트

🧠 도메인 1·2 추가 - 스토리지·DB 시험 직전 압축

S3 함정 모음

함정정답
"최대 객체 크기?"5 TB
"단일 PUT 최대?"5 GB
"멀티파트 파트 최소?"5 MB (마지막 제외)
"멀티파트 파트 최대?"10,000개
"버전 관리 비활성화 가능?"❌ (Suspended만)
"정적 웹사이트 HTTPS?"❌ → CloudFront + ACM
"CloudFront ACM 리전?"us-east-1 강제
"OAI vs OAC?"OAC 권장 (SSE-KMS·SigV4 지원)
"강력한 일관성 시점?"2020년부터 모든 동작
"Glacier 최소 보존?"90일 (Instant Retrieval/Flexible), Deep Archive 180일
"SSE-S3 헤더?"AES256
"SSE-KMS 헤더?"aws:kms
"Bucket Key 효과?"KMS 비용 최대 99% 절감

DynamoDB 함정 모음

함정정답
"항목 최대 크기?"400 KB
"트랜잭션 최대 항목?"100개 (이전 25개), 4MB
"LSI 추가 시점?"테이블 생성 시만
"GSI 일관성?"Eventually Consistent만
"Strong Consistency 1KB?"1 RCU
"Eventually 1KB?"0.5 RCU
"Transaction Write 1KB?"2 WCU
"Streams 보존?"24시간 (고정)
"Kinesis for DDB 보존?"최대 1년
"DAX 용도?"DDB 마이크로초 캐시 (VPC 내부)
"MemoryDB vs ElastiCache Redis?"Strong consistent vs Eventually
"Atomic Counter 멱등성?"❌ — 중복 위험
"TTL 만료 후 삭제 시간?"0~48시간
"PartiQL?"DDB의 SQL 호환 쿼리

RDS·Aurora 함정

함정정답
"Multi-AZ Standby 읽기?"불가 (Cluster Deployment는 가능)
"Read Replica 최대?"RDS 5 / Aurora 15
"기존 RDS 암호화 변경?"스냅샷 → 암호화 복사 → 새 DB
"Aurora 사본?"3 AZ × 2 = 6
"Aurora 쓰기 정족수?"4/6
"Aurora Replica Failover?"< 30초
"Aurora Global Replication?"복제 지연 일반적으로 < 1초, RTO 수 분
"Aurora Backtrack?"MySQL only, 72시간 in-place
"RDS Proxy 효과?"연결 풀링·Lambda·Failover 66% ↓
"IAM 토큰?"15분 + SSL 필수
"Auto 백업 최대?"35일 + DB 삭제 시 함께 삭제
"수동 스냅샷?"무기한·DB 삭제 후 유지

Redis vs Memcached 한 줄 결정

필요선택
영속성Redis
Multi-AZ HARedis
복잡한 자료구조Redis
Sorted Set (리더보드)Redis
멀티스레드 단순 캐시Memcached

🗺️ 데이터 계층 선택: 표 대신 결정 트리로

스토리지·DB 문제는 "서비스 설명"이 아니라 "요구사항 목록"으로 출제된다. 그래서 서비스별 특징표를 외우는 것보다, 요구사항에서 어떤 단어를 만나면 어디로 꺾이는지를 트리로 갖고 있는 편이 훨씬 빠르다.

요구사항 문장에서 먼저 찾을 단어들
────────────────────────────────────────────────────────────
"파일" · "이미지" · "정적 자산" · "아카이브"
        └─▶ S3 ── 접근 빈도는? ── 자주 → Standard
                              ├─ 가끔(30일+) → Standard-IA / One Zone-IA
                              ├─ 거의 없음(90일+) → Glacier 계열
                              └─ 패턴 예측 불가 → Intelligent-Tiering

"키로 조회" · "밀리초" · "무제한 확장" · "서버리스"
        └─▶ DynamoDB ── 더 빨라야? → + DAX(마이크로초, VPC 내부)
                     ├─ 변경 이력 필요? → Streams(24h) / Kinesis(최대 365일)
                     └─ 다중 리전 쓰기? → Global Tables(Last Writer Wins)

"조인" · "트랜잭션" · "SQL" · "기존 애플리케이션 이관"
        └─▶ RDS ── 가용성? → Multi-AZ(동기·자동 페일오버)
                 ├─ 읽기 확장? → Read Replica(비동기, RDS 5 / Aurora 15)
                 ├─ 커넥션 폭주(Lambda)? → RDS Proxy
                 └─ 간헐적·예측 불가 → Aurora Serverless

"캐시" · "세션" · "리더보드" · "Pub/Sub"
        └─▶ ElastiCache ── 영속성·HA·자료구조 필요? → Redis
                        └─ 단순 문자열 캐시·멀티스레드 → Memcached

"여러 EC2가 같은 파일을" → EFS      "초고속 임시 디스크" → 인스턴스 스토어

이 트리에서 혼동하기 쉬운 갈림길은 Multi-AZ와 Read Replica다. 둘 다 "복제본을 만든다"지만 목적이 정반대다. Multi-AZ는 동기 복제 + 대기 인스턴스로 장애 시 자동 전환(고가용성)을 노리고, 대기 인스턴스는 원칙적으로 읽기에 쓸 수 없다. Read Replica는 비동기 복제로 읽기 부하를 나눠 갖는 것이며, 복제 지연이 존재하므로 "방금 쓴 값을 즉시 읽어야 하는" 경로에는 쓰면 안 된다. 시험에서 "성능 향상"이라는 단어가 나오면 Multi-AZ는 오답, "장애 시 다운타임 최소화"가 나오면 Read Replica는 오답이다.

동기 복제와 비동기 복제의 차이는 일관성과 지연 시간의 교환이다. 동기 복제는 쓰기를 두 곳에 확정한 뒤 응답하므로 일관성(C)은 좋지만 쓰기 지연(L)이 늘고, 한쪽이 느려지면 전체가 느려진다. 비동기 복제는 쓰기 응답이 빠르지만 복제본이 잠시 뒤처져 최종 일관성이 된다. Aurora는 이 이분법을 스토리지 계층으로 옮겨 풀었다 — 3개 AZ에 6개 사본을 두고 쓰기 정족수 4/6, 읽기 정족수 3/6으로 처리해, 한 AZ가 통째로 사라져도 쓰기가 계속되면서 지연은 정족수만큼만 기다린다. "6사본·4/6 정족수"라는 숫자를 외울 때 정족수가 왜 과반보다 큰지(AZ 하나 + 디스크 하나가 동시에 죽어도 견디려고)까지 붙여 두면 잊히지 않는다.


🪣 S3를 코드로: 프리사인 URL과 버킷 정책

S3 문제에서 가장 실무적인 축은 "서버를 거치지 않고 클라이언트가 직접 올리고 받게 하라"는 요구다. 답은 프리사인 URL이다.

import boto3
from botocore.exceptions import ClientError
 
s3 = boto3.client("s3", region_name="ap-northeast-2")
 
def create_upload_url(bucket: str, key: str, expires: int = 900) -> str:
    """클라이언트가 서버를 거치지 않고 직접 PUT 하도록 만드는 서명 URL."""
    try:
        return s3.generate_presigned_url(
            ClientMethod="put_object",
            Params={
                "Bucket": bucket,
                "Key": key,
                "ContentType": "image/jpeg",
                "ServerSideEncryption": "aws:kms",   # 업로드 시 암호화 강제
            },
            ExpiresIn=expires,      # 초 단위. SigV4 기준 최대 7일(604800초)
        )
    except ClientError as e:
        # 서명 자체는 로컬 계산이라 여기서 실패하면 대개 자격 증명/리전 문제
        raise RuntimeError(f"presign failed: {e}") from e

프리사인 URL에서 반드시 짚어야 할 성질이 둘 있다. 첫째, URL의 권한은 URL을 만든 주체의 권한을 넘지 못한다. Lambda 실행 역할에 s3:PutObject가 없으면 URL은 만들어져도 사용 시 403이 난다. 둘째, 만료 시간은 서명한 자격 증명의 수명에도 묶인다. 역할의 임시 자격 증명이 1시간짜리면 7일짜리 URL을 발급해도 그 자격 증명이 끝나는 순간 무효가 된다. "7일"이라는 숫자만 외우고 이 조건을 놓치면 실무에서 문제가 된다.

// 버킷 정책 — HTTPS 강제 + 암호화되지 않은 업로드 거부
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyInsecureTransport",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::my-media-bucket",
        "arn:aws:s3:::my-media-bucket/*"
      ],
      "Condition": { "Bool": { "aws:SecureTransport": "false" } }
    },
    {
      "Sid": "DenyUnencryptedUploads",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::my-media-bucket/*",
      "Condition": {
        "StringNotEquals": { "s3:x-amz-server-side-encryption": "aws:kms" }
      }
    }
  ]
}

aws:SecureTransport=false를 Deny 하는 형태여야 한다는 점이 시험 포인트다. "true를 Allow"로 쓰면 다른 곳의 Allow가 여전히 HTTP를 허용할 수 있어 강제가 되지 않는다. 강제는 언제나 Deny로 건다.

암호화 세 방식 — 키를 누가 쥐느냐

방식키 소유·관리요청 헤더감사(CloudTrail)특징
SSE-S3AWS가 전부 관리AES256키 사용 로그 없음가장 단순, 추가 비용 없음
SSE-KMSKMS 키(고객 관리 가능)aws:kms키 사용 내역 남음접근 제어·감사 강함, KMS API 호출 발생
SSE-C고객이 키를 매 요청에 제공키를 헤더로 전달AWS가 키 보관 안 함HTTPS 필수, 키 분실 시 복구 불가

⚠️ 함정: 트래픽이 많은 버킷에서 SSE-KMS를 쓰면 객체 접근마다 KMS API가 호출되어 KMS 요청 한도에 걸리고 비용도 급증한다. 해법이 S3 Bucket Key다 — 버킷 단위 중간 키를 두어 KMS 호출 횟수를 줄이고, 이를 통해 KMS 비용을 최대 99%까지 낮춘다. 시험에서 "SSE-KMS 사용 후 비용 급증/스로틀링"이 보이면 답은 대개 Bucket Key다. 또 하나, 정적 웹사이트 호스팅은 HTTP만 지원하므로 HTTPS가 요구되면 반드시 CloudFront + ACM(인증서는 us-east-1)이 함께 나와야 한다.

# 대용량 업로드는 CLI가 알아서 멀티파트로 쪼갠다 (8MB 초과 시 기본 동작)
aws s3 cp ./bigfile.zip s3://my-media-bucket/backups/bigfile.zip \
  --sse aws:kms --sse-kms-key-id alias/media-key
 
# 미완료 멀티파트는 요금을 계속 먹는다 — 반드시 확인·정리
aws s3api list-multipart-uploads --bucket my-media-bucket
aws s3api abort-multipart-upload \
  --bucket my-media-bucket --key backups/bigfile.zip --upload-id "EXAMPLE_ID"
 
# 근본 처방: 수명 주기 규칙으로 미완료 멀티파트 자동 정리
aws s3api put-bucket-lifecycle-configuration --bucket my-media-bucket \
  --lifecycle-configuration '{
    "Rules": [{
      "ID": "abort-incomplete-mpu",
      "Status": "Enabled",
      "Filter": {"Prefix": ""},
      "AbortIncompleteMultipartUpload": {"DaysAfterInitiation": 7}
    }]
  }'

"S3 청구서에 저장한 적 없는 용량이 잡힌다"는 신고의 대표적인 원인이 미완료 멀티파트 업로드다. 업로드가 중간에 끊기면 이미 올라간 파트들이 버킷에 남지만 객체 목록(ListObjects)에는 보이지 않는다. 콘솔에서 아무리 뒤져도 파일이 없는데 스토리지 요금은 계속 나가는 상황이 이렇게 만들어진다. 처방은 위처럼 AbortIncompleteMultipartUpload 수명 주기 규칙을 걸어 두는 것이고, 이 규칙은 프로덕션 버킷에 걸어 두는 것이 좋다.

S3의 요청 성능은 접두사(prefix) 단위로 확장된다. 접두사당 초당 3,500회의 PUT/COPY/POST/DELETE와 5,500회의 GET/HEAD를 처리하며, 접두사를 늘리면 그만큼 선형으로 늘어난다. 그래서 logs/2026-08-10/...처럼 날짜가 앞에 오는 키 설계는 특정 날짜에 요청이 몰려 한 접두사에 부하가 집중되지만, logs/a3f/2026-08-10/...처럼 해시를 앞에 두면 여러 접두사로 흩어진다. 이 "앞자리를 흩뜨려 분산한다"는 발상은 DynamoDB의 write sharding과 완전히 같은 아이디어다 — 저장소가 달라도 핫스팟은 키의 앞부분이 만든다는 원리는 반복된다.


🧮 DynamoDB: 계산과 조건부 쓰기

용량 계산은 공식보다 기준 단위를 먼저 떠올려야 한다. 읽기는 4KB, 쓰기는 1KB, 언제나 올림(ceil).

강력한 일관성 읽기 = ceil(항목KB / 4) × 1 × 초당 요청수
최종 일관성 읽기   = ceil(항목KB / 4) × 0.5 × 초당 요청수
트랜잭션 읽기      = ceil(항목KB / 4) × 2 × 초당 요청수

일반 쓰기          = ceil(항목KB / 1) × 1 × 초당 요청수
트랜잭션 쓰기      = ceil(항목KB / 1) × 2 × 초당 요청수

빠른 검산: 5KB 강력 읽기 100회/초 → ceil(5/4)=2 → 2×1×100 = 200 RCU
          5KB 일반 쓰기 100회/초 → ceil(5/1)=5 → 5×1×100 = 500 WCU
          같은 항목이라도 쓰기가 압도적으로 비싸다

동시 수정 문제는 조건부 쓰기(conditional write) 로 푼다. 낙관적 잠금(Optimistic Locking)은 별도 기능이 아니라 조건부 쓰기의 응용이다.

from botocore.exceptions import ClientError
 
def update_stock_safely(table, product_id: str, expected_version: int, new_stock: int):
    """버전이 그대로일 때만 갱신 — 다른 사람이 먼저 바꿨으면 실패시킨다."""
    try:
        table.update_item(
            Key={"PK": f"PRODUCT#{product_id}", "SK": "DETAIL"},
            UpdateExpression="SET stock = :s, version = :nv",
            ConditionExpression="version = :ev",          # 낙관적 잠금의 핵심
            ExpressionAttributeValues={
                ":s": new_stock,
                ":nv": expected_version + 1,
                ":ev": expected_version,
            },
        )
    except ClientError as e:
        if e.response["Error"]["Code"] == "ConditionalCheckFailedException":
            # 다른 요청이 먼저 갱신함 → 최신 항목을 다시 읽고 재시도
            raise ConcurrencyConflict(product_id) from e
        raise

ConditionExpression이 없으면 마지막 쓰기가 앞의 쓰기를 조용히 덮어쓴다(lost update). 반대로 ADD stock :delta 같은 원자적 카운터는 동시성에는 안전하지만 멱등하지 않다 — 같은 요청이 두 번 도착하면 두 번 더해진다. "동시성 안전"과 "재시도 안전(멱등)"은 다른 문제이며, 시험은 이 둘을 구분해서 묻는다.

상황올바른 도구
항목이 없을 때만 생성ConditionExpression: attribute_not_exists(PK)
남이 안 바꿨을 때만 수정버전 속성 + ConditionExpression(낙관적 잠금)
조회수·재고 증감ADD(원자적 카운터) — 단, 중복 호출 주의
여러 항목을 전부 성공/전부 실패TransactWriteItems(WCU 2배)
중복 호출 방지요청 ID를 키로 한 attribute_not_exists 삽입(멱등성 테이블)

DynamoDB 에러로 원인 가르기

에러뜻처방
ProvisionedThroughputExceededException용량 초과(스로틀링)RCU/WCU 증액, 온디맨드 전환, 핫 파티션 완화
ConditionalCheckFailedException조건 불충족재조회 후 재시도 (오류가 아니라 설계된 신호)
ValidationException요청 형식·크기 위반항목 400KB 초과, 키 누락, 예약어 사용 여부 확인
TransactionCanceledException트랜잭션 일부 실패CancellationReasons로 실패 항목 확인
ItemCollectionSizeLimitExceededExceptionLSI 항목 컬렉션 10GB 초과LSI 재설계 또는 GSI로 전환
ResourceNotFoundException테이블/인덱스 없음리전·이름·GSI 생성 완료 여부 확인

⚠️ 함정: 스로틀링을 만나면 반사적으로 용량을 올리는데, 테이블 전체 용량은 남는데도 특정 파티션만 터지는 경우가 많다. 파티션 하나가 감당하는 상한은 약 3,000 RCU와 1,000 WCU이고, 파티션 키가 status나 날짜처럼 카디널리티가 낮으면 트래픽이 한 파티션에 몰린다. 이때의 답은 증액이 아니라 키 설계 변경(샤딩·고카디널리티 키) 이다. 시험에서 "용량을 늘렸는데도 스로틀링이 계속된다"는 문장이 나오면 곧바로 핫 파티션을 의심한다.


🔌 RDS와 ElastiCache: 연결과 캐시의 실제

Lambda + RDS 조합은 서버리스에서 문제가 생기기 쉬운 지점이다. 함수는 순식간에 수백 개로 늘어나는데, RDS의 최대 연결 수는 인스턴스 크기에 묶여 있다. 그래서 RDS Proxy가 등장한다 — 연결을 풀링해 재사용하고, 장애 조치 시간을 크게 줄이며, IAM 인증과 Secrets Manager를 통합한다.

# 비밀번호 대신 IAM 인증 토큰으로 접속 (토큰 유효 15분, SSL 필수)
TOKEN=$(aws rds generate-db-auth-token \
  --hostname myproxy.proxy-abc123.ap-northeast-2.rds.amazonaws.com \
  --port 3306 --region ap-northeast-2 --username app_user)
 
mysql --host=myproxy.proxy-abc123.ap-northeast-2.rds.amazonaws.com \
      --port=3306 --user=app_user --password="$TOKEN" \
      --ssl-ca=/opt/rds-ca-bundle.pem
 
# 기존 미암호화 RDS를 암호화하려면? 스냅샷 → 암호화 복사 → 복원 (in-place 불가)
aws rds create-db-snapshot --db-instance-identifier prod-db --db-snapshot-identifier prod-snap
aws rds copy-db-snapshot --source-db-snapshot-identifier prod-snap \
  --target-db-snapshot-identifier prod-snap-enc --kms-key-id alias/rds-key
aws rds restore-db-instance-from-db-snapshot \
  --db-instance-identifier prod-db-enc --db-snapshot-identifier prod-snap-enc

"이미 돌고 있는 RDS의 암호화를 켤 수 있는가"의 답은 불가 — 스냅샷을 암호화하며 복사한 뒤 새 인스턴스로 복원이다. 암호화는 생성 시점에 정해지는 속성이라는 원칙을 기억하면 된다.

캐시 전략은 코드로 보면 차이가 선명하다.

# Lazy Loading (Cache-Aside): 읽을 때만 채운다
def get_product(product_id):
    cached = redis.get(f"product:{product_id}")
    if cached:
        return json.loads(cached)                  # 캐시 히트
    row = db.query_product(product_id)             # 캐시 미스 → DB
    redis.setex(f"product:{product_id}", 300, json.dumps(row))  # TTL 필수
    return row
 
# Write-Through: 쓸 때 캐시도 같이 갱신한다
def update_product(product_id, payload):
    db.update_product(product_id, payload)
    redis.setex(f"product:{product_id}", 300, json.dumps(payload))
전략장점단점어울리는 상황
Lazy Loading실제로 읽는 데이터만 캐시, 캐시 장애에 강함첫 요청은 항상 느림(미스), 갱신 누락 시 오래된 값읽기 편중, 데이터 일부만 뜨겁게 쓰일 때
Write-Through캐시가 항상 최신쓰기마다 비용, 안 읽힐 데이터도 캐시 점유쓴 직후 곧바로 읽는 패턴
TTL 병행위 둘의 오래된 값 문제를 시간으로 상쇄완벽한 최신성은 아님사실상 모든 실무 구성의 기본

실무에서는 둘 중 하나를 고르는 게 아니라 Lazy Loading + TTL을 기본으로 깔고, 즉시 최신성이 필요한 소수 키에만 Write-Through를 얹는다. 시험에서 "오래된 데이터가 보인다"는 증상은 TTL 부재 또는 무효화 누락이고, "쓰기가 느려졌다"는 증상은 Write-Through의 대가다.

가상의 사례로, 캐시를 도입한 서비스가 새벽 배포 직후 DB 부하로 넘어졌다. 원인은 캐시 스탬피드(cache stampede) — 캐시를 비우거나 대량의 키가 동시에 TTL 만료를 맞으면, 수천 개의 요청이 동시에 미스를 내고 전부 DB로 몰린다. 완화책은 (1) TTL에 무작위 지터를 더해 만료 시점을 흩고, (2) 같은 키에 대해서는 한 요청만 DB에 가도록 잠그며(single-flight), (3) 배포 후 핵심 키를 미리 채워 두는 워밍이다. "캐시를 켰는데 오히려 장애가 났다"는 시나리오는 이 현상일 수 있다.


정리

스토리지·DB 영역의 시험 문제는 "이 데이터에 어떤 접근 패턴이 있는가" 한 질문으로 수렴한다. 파일이면 S3, 키 조회면 DynamoDB, 조인·트랜잭션이면 RDS, 반복 조회 가속이면 캐시다.

그 위에 얹히는 세부 규칙은 모두 "그 접근 패턴이 만들어내는 부작용을 어떻게 막느냐"의 답이다.

  • S3 강제는 Deny 조건으로 건다.
  • KMS 비용은 Bucket Key로 줄인다.
  • 암호화 전환은 스냅샷 복사로 한다.
  • DynamoDB 동시성은 조건부 쓰기로 다룬다.
  • Lambda의 연결 폭주는 RDS Proxy로 막는다.

숫자(5TB·400KB·35일·15분·48시간)는 마지막에 확인하는 값이고, 먼저 잡아야 할 것은 접근 패턴이다.


📝 최종 모의고사 - Part 2

📝 연습 문제

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

문제 1

DynamoDB에서 5KB 항목을 강력한 일관성으로 읽을 때 RCU는?

문제 2

S3 버킷에 HTTPS만 허용하는 버킷 정책의 조건은?

문제 3

운영 중인 RDS 테이블에 GSI를 추가할 수 있는가?

문제 4

ElastiCache에서 Write-Through 전략의 단점은?

문제 5

S3 교차 리전 복제(CRR)의 전제 조건은?

문제 6

Aurora Serverless의 최적 사용 케이스는?

문제 7

DynamoDB TTL 만료 후 실제 삭제까지 걸리는 시간은?

문제 8

S3 수명 주기 정책에서 Glacier로 이동하기 위한 최소 보존 기간은?

📌 오늘의 요약

  1. S3: HTTPS 강제(SecureTransport), 버전 관리, CRR(버전관리 필수), 스토리지 클래스
  2. DynamoDB: RCU/WCU 계산, LSI(생성시만)/GSI(언제든), TTL(48시간), 트랜잭션(2배)
  3. RDS: Multi-AZ(동기/Failover) vs Read Replica(비동기/읽기확장)
  4. Aurora: 3AZ 6사본, MySQL 5배, Serverless(간헐적), 글로벌(1초 미만)
  5. ElastiCache: Redis(영속성/복잡) vs Memcached(단순/멀티스레드)
이전최종 복습 1: IAM, EC2, Lambda, API GatewayWeek 13 · Day 1다음 최종 복습 3: 보안, 모니터링, CI/CDWeek 13 · Day 3

참고 공식 자료

  • DVA-C02 공식 시험 안내(새 탭에서 열림)
  • Amazon RDS · Aurora 공식 문서(새 탭에서 열림)
  • Amazon S3 공식 문서(새 탭에서 열림)
  • Amazon DynamoDB 공식 문서(새 탭에서 열림)
  • Amazon ElastiCache 공식 문서(새 탭에서 열림)
  • AWS KMS 공식 문서(새 탭에서 열림)

이 페이지

  • 학습 목표
  • 핵심 암기표
  • S3 핵심 암기
  • DynamoDB 핵심 암기
  • RDS 핵심 암기
  • ElastiCache 핵심 암기
  • 도메인 1·2 추가 - 스토리지·DB 시험 직전 압축
  • S3 함정 모음
  • DynamoDB 함정 모음
  • RDS·Aurora 함정
  • Redis vs Memcached 한 줄 결정
  • 데이터 계층 선택: 표 대신 결정 트리로
  • S3를 코드로: 프리사인 URL과 버킷 정책
  • 암호화 세 방식 — 키를 누가 쥐느냐
  • DynamoDB: 계산과 조건부 쓰기
  • DynamoDB 에러로 원인 가르기
  • RDS와 ElastiCache: 연결과 캐시의 실제
  • 정리
  • 최종 모의고사 - Part 2
  • 오늘의 요약