기준: DVA-C02 시험 가이드오류 제보
Aurora는 2014년 re:Invent에서 처음 공개됐을 때 많은 사람을 어리둥절하게 만들었다. "MySQL 호환인데 MySQL이 아니다"라는 어색한 표현. AWS의 메시지는 명확했다 — SQL 엔진 코드는 MySQL/PostgreSQL을 거의 그대로 쓰지만, 그 아래의 스토리지·복제·트랜잭션 레이어를 클라우드 환경에 맞게 처음부터 재설계했다. 이 결정이 가져온 결과가 "MySQL 대비 5배, PostgreSQL 대비 3배 성능 + 자동 확장 스토리지 + 1초 미만 cross-region 복제"라는 숫자다.
DVA-C02에서 Aurora는 RDS와 묻는 각도가 다르다. RDS는 "관리형 DB의 trade-off"를 묻고, Aurora는 "왜 RDS로 부족한가, 어떤 시나리오에서 Aurora를 골라야 하는가"를 묻는다. 그 답을 이해하려면 Aurora의 스토리지 구조와 quorum 기반 복제를 알아야 한다. 오늘은 그 내부를 들여다본다.
전통적인 MySQL/PostgreSQL은 1990년대 단일 서버 환경을 가정해서 설계됐다. binlog/WAL을 디스크에 쓰고, 백업은 그 디스크를 복사하고, 복제는 binlog를 다른 서버로 보내는 식이다. 이 모델을 클라우드에 그대로 옮기면 ① EBS 한 볼륨에 의존하므로 단일 AZ 장애에 취약 ② 복제는 비동기 binlog 기반이라 lag 발생 ③ 스토리지 확장은 수동 ④ 백업/복원은 인스턴스 크기에 비례하는 시간 — 이런 한계가 그대로 따라온다.
Aurora 논문(SIGMOD 2017 "Amazon Aurora: Design Considerations for High Throughput Cloud-Native Relational Databases", Verbitski et al.)이 던진 핵심 통찰은 단순했다. "네트워크가 새로운 병목이다. 따라서 네트워크 트래픽을 줄이는 것이 곧 성능이다." 전통 DB는 commit 시점에 ① data page ② undo log ③ redo log ④ binlog ⑤ double-write buffer 등 같은 데이터를 여러 형태로 디스크에 쓴다. AWS 측정에 따르면 MySQL은 한 commit당 약 7.4번의 디스크 I/O가 발생한다.
Aurora는 이 중 redo log만 분산 스토리지에 보내고, 페이지 재구성은 스토리지 노드가 백그라운드로 처리한다. 결과적으로 I/O 횟수는 1/6 수준, 네트워크 트래픽은 7.7배 줄었다.
일반 MySQL의 commit:
애플리케이션 → MySQL
↓
로컬 디스크 쓰기 (data page, redo log, undo log, binlog, double-write...)
↓
binlog 기반 replica 복제 (비동기)
Aurora의 commit:
애플리케이션 → Aurora
↓
"redo log record"만 6개 스토리지 노드에 송신
↓
4/6에서 ack 받으면 commit 완료
(스토리지 노드가 백그라운드로 data page 재구성)
Aurora 스토리지 노드는 단순한 EBS 볼륨이 아니다. redo log를 받아서 page를 reconstruct할 수 있는 작은 서버다. Aurora의 한 스토리지 노드는 들어오는 log record를 자기 로컬 디스크에 append하고, 그 log를 적용한 페이지 버전을 만들어 둔다. 읽기 요청이 "이 페이지의 특정 LSN 시점 버전"을 요구하면 스토리지 노드가 즉시 응답한다.
이 구조 덕분에 ① binlog가 사라지고 ② replica는 자체 스토리지 없이 primary와 같은 스토리지를 참조하며 ③ 백업은 사실상 무료(continuous backup) ④ 스토리지 확장은 자동(10GB 단위 segment를 추가/제거). 이것이 Aurora 차별점의 근원이다.
Aurora 스토리지를 설명하는 대표적인 그림은 "6 copies across 3 AZs"다. 이 숫자는 임의로 정한 것이 아니라 분산 시스템의 fault tolerance 수학에서 유도한 값이다.
3 AZ × 2 copies = 6 사본
쓰기 quorum: V_w = 4 (6 사본 중 4개 ack 받으면 commit)
읽기 quorum: V_r = 3 (6 사본 중 3개에서 읽으면 valid)
V_w + V_r > N (4 + 3 > 6) → 강한 일관성 보장
2 × V_w > N (8 > 6) → 동시 쓰기 충돌 방지
이 설정이 보장하는 것:
Aurora의 (N=6, W=4, R=3)은 AZ 단위 장애와 노드 단위 장애를 함께 견디도록 고른 값이다.
RDS Read Replica는 각 replica가 자기 스토리지를 가지고 primary의 binlog를 받아 자기 디스크에 apply한다. 이 모델의 한계가 ① replica마다 스토리지 비용이 발생한다 ② lag는 binlog 전송 + apply 속도에 의존(보통 수 초 ~ 수십 초) ③ replica 추가 시 초기 동기화에 시간 소요.
Aurora Replica는 자체 스토리지가 없다. Primary와 같은 분산 스토리지를 공유한다. 그래서:
| 차원 | RDS Read Replica | Aurora Replica |
|---|---|---|
| 스토리지 | 각자 보유 | 공유 |
| 복제 메커니즘 | 비동기 binlog/WAL | redo log 알림 (스토리지는 공유) |
| 복제 lag | 초 ~ 분 | 보통 100ms보다 훨씬 짧음 |
| 최대 개수 | 15 (MySQL/PG/MariaDB/SQL Server, 소스당) | 15 |
| 초기 동기화 | 전체 copy 필요 | 즉시 |
| 페일오버 시간 | 수동 promote (수 분) | 자동 (~30초) |
⚠️ 함정: Aurora Replica의 페일오버 시간이 30초인 것은 인스턴스 클래스가 같을 때다. Primary와 다른 인스턴스 클래스의 replica가 있으면 페일오버 우선순위가 떨어지고, 페일오버 후 성능 저하가 일어날 수 있다. "Aurora 페일오버 후 성능 저하" 시나리오의 원인은 replica 인스턴스 크기 불일치일 수 있다. Tier 0-15 우선순위로 페일오버 순서를 명시할 수 있다.
Aurora는 RDS와 달리 인스턴스 단위 endpoint가 아닌 클러스터 단위 endpoint가 기본이다. 5종을 구분해야 한다.
| 엔드포인트 | DNS 형태 | 역할 |
|---|---|---|
| Cluster Endpoint (Writer) | myclu.cluster-xxxx.region.rds.amazonaws.com | 현재 primary로 자동 라우팅 (페일오버 시 자동 갱신) |
| Reader Endpoint | myclu.cluster-ro-xxxx.region.rds.amazonaws.com | 모든 read replica에 DNS round-robin (load balancing) |
| Custom Endpoint | myclu-analytics.cluster-custom-xxxx... | 사용자가 지정한 인스턴스 그룹 (예: 분석 워크로드용 큰 replica만) |
| Instance Endpoint | myinst-1.xxxx.region.rds.amazonaws.com | 특정 인스턴스 직접 (운영 디버깅용) |
| Global Database Writer | 자동 발급 | Global DB의 모든 리전에서 같은 endpoint, 자동으로 primary 리전 writer로 라우팅 |
Reader Endpoint의 부하 분산은 DNS 레벨에서 일어난다. 같은 endpoint를 resolve하면 매번 다른 replica IP가 반환된다(TTL 5초). 이 때문에 두 가지 문제가 생긴다.
실무에서는 ① 짧은 connection lifetime ② Aurora 클라이언트 라이브러리(MariaDB Connector/J Aurora cluster aware, Aurora Postgres JDBC wrapper) 사용 ③ RDS Proxy로 routing 위임 중 하나가 필요하다. "Reader Endpoint를 썼는데 한 replica에만 부하가 몰린다"는 시나리오의 원인은 connection 유지 + DNS 캐싱이다.
# 실무: 분석 워크로드를 custom endpoint로 격리
ANALYTICS_ENDPOINT = "myclu-analytics.cluster-custom-xxxx.region.rds.amazonaws.com"
OLTP_READER_ENDPOINT = "myclu.cluster-ro-xxxx.region.rds.amazonaws.com"
WRITER_ENDPOINT = "myclu.cluster-xxxx.region.rds.amazonaws.com"
def get_analytics_conn():
return pymysql.connect(host=ANALYTICS_ENDPOINT, ...)
def get_oltp_read_conn():
return pymysql.connect(host=OLTP_READER_ENDPOINT, ...)
def get_write_conn():
return pymysql.connect(host=WRITER_ENDPOINT, ...)Aurora Serverless는 트래픽에 따라 컴퓨트 용량이 자동으로 늘었다 줄었다 한다. 단위는 ACU(Aurora Capacity Unit) — 1 ACU ≈ 2GB 메모리 + 그에 상응하는 CPU/네트워크. v1과 v2의 차이는 시험에 나온다.
| 항목 | Aurora Serverless v1 (레거시) | Aurora Serverless v2 (권장) |
|---|---|---|
| 확장 단위 | 2배 단위 점프 (2→4→8 ACU) | 0.5 ACU 단위 미세 조정 |
| 확장 속도 | 분 단위 | 초 단위 |
| Min Capacity | 1 ACU (또는 일시정지) | 0 ACU (auto-pause) ~ 0.5 ACU |
| Max Capacity | — | 256 ACU(Aurora MySQL) / 384 ACU(Aurora PostgreSQL), 플랫폼 버전에 따라 다름 |
| 콜드 스타트 | 일시정지 후 첫 요청 ~30초 | 스케일링은 무중단. auto-pause(0 ACU) 재개 시 약 15초(24시간 넘게 정지하면 30초 이상) |
| Multi-AZ | 옵션 | 표준 |
| 데이터 API | ✅ | ✅ (2023부터) |
| 신규 | 단종 절차 | 권장 |
v1과 v2의 가장 큰 차이는 확장 메커니즘이다. v1은 새 인스턴스로 트래픽을 옮기는(scale-up) 방식 — 그래서 점프가 크고 느리다. v2는 대부분의 스케일링 이벤트에서 라이터/리더를 같은 호스트에 둔 채 용량을 조정하며, 진행 중인 DB 작업을 방해하지 않는다. 이것이 "미세 조정"의 근거다. v2는 "사용량 기반 과금이 가능한 정규 Aurora 인스턴스"에 가깝다.
사용 시나리오별 선택은 다음과 같다.
Aurora Global Database는 primary 리전 1개 + secondary 리전 최대 10개로 구성된다. RDS Cross-Region Read Replica와 다른 점은 ① 전용 복제 인프라(스토리지 레벨 복제) ② 일반적으로 lag < 1초 ③ Secondary가 자체 read replica를 최대 16개 보유 가능 ④ managed failover RTO는 수 분 단위(지원 버전의 switchover는 보통 30초 미만).
[Primary Region: ap-northeast-2 서울]
Aurora Writer + Replicas
│
│ (스토리지 레벨 replication, < 1초)
│
├──→ [Secondary: us-east-1 버지니아]
│ Read-only Aurora cluster
│ 자체 read replica 0-16개
│
└──→ [Secondary: eu-west-1 아일랜드]
Read-only Aurora cluster
자체 read replica 0-16개
Aurora Global Database의 복제는 redo log shipping에 가깝지만 binlog가 아니다. Primary의 스토리지 노드가 redo log를 추가로 secondary region의 스토리지 노드에게 직접 전송한다. 이 채널은 AWS backbone 네트워크(같은 백본 위에서 평균 RTT 100-200ms)를 사용하고, 압축·중복 제거가 적용되어 일반 인터넷 대비 효율적이다. 그 결과 cross-region lag이 일반적으로 1초 미만이다. "글로벌 분산 + 1초 미만 lag + RDBMS" 시나리오의 답은 Aurora Global Database다.
| 차원 | RDS Cross-Region Read Replica | Aurora Global Database |
|---|---|---|
| 복제 방식 | binlog 비동기 | redo log shipping (전용 인프라) |
| 일반 lag | 수 초 ~ 수십 초 | < 1초 |
| 페일오버 | 수동 promote | Managed 페일오버 (수 분 단위) |
| Secondary 리전 수 | 다수 가능 (각각 별개 replica) | 최대 10개 (managed cluster) |
| Secondary read replica | N/A (자체가 replica) | 각 리전마다 16개까지 |
| RPO | 수십 초 ~ 분 | < 1초 |
⚠️ 함정: Aurora Global Database의 secondary는 읽기 전용이다. 단순 write를 시도하면 read-only error. 또한 "관리되는 페일오버(managed failover)"는 명시적으로 트리거해야 하며 자동이 아니다 — primary region이 완전히 죽었을 때 운영자가 promote를 실행. 자동 페일오버가 필요하면 Route 53 health check + Lambda로 직접 자동화하거나 RDS Proxy를 활용한다. "Aurora Global Database가 자동으로 페일오버한다"는 보기는 함정이다.
Aurora MySQL에는 RDS에 없는 기능 — Backtrack이 있다. 데이터를 과거 시점으로 새 인스턴스 생성 없이 되돌린다. 최대 72시간 전까지 가능. PITR은 새 인스턴스를 만들지만 Backtrack은 같은 인스턴스를 시간만 되돌린다.
| 항목 | Backtrack | PITR |
|---|---|---|
| 새 인스턴스 생성 | ❌ (in-place) | ✅ |
| 속도 | 초 ~ 분 | 분 ~ 시간 (DB 크기 의존) |
| 지원 | Aurora MySQL만 | RDS + Aurora |
| 최대 기간 | 72시간 | 35일 |
| 비용 | Backtrack window 별도 | 자동 백업 무료 범위 |
| 시나리오 | "방금 DROP TABLE" 즉시 롤백 | 어제 사고난 데이터 복원 |
가상의 사례로, 한 게임 회사 개발자가 production Aurora MySQL에 DELETE FROM users 를 WHERE 절 없이 실행했다(개발 DB와 헷갈림). Backtrack이 활성화돼 있어 콘솔에서 "5분 전으로 되돌리기" 한 번에 약 3분 만에 복구했다. PITR이었다면 ① 새 인스턴스 생성(30분) ② 데이터 export/import(시간 단위) ③ 애플리케이션 endpoint 전환이라는 복잡한 절차가 필요했을 것이다. "Aurora에서 빠른 실수 복구"는 Backtrack이 답이다.
Aurora는 클러스터를 수 초 만에 클론할 수 있다. 클론은 같은 스토리지를 공유하면서 copy-on-write 방식으로 동작 — 클론에서 데이터를 수정해야 비로소 그 페이지만 새로 복사된다. 결과: ① 클론 생성 즉시 가능 ② 초기 비용 = 0 ③ 수정량만큼만 추가 스토리지 비용.
[Primary Aurora] ────┬──── [Clone A] (개발 환경)
│
├──── [Clone B] (테스트 환경)
│
└──── [Clone C] (분석 워크로드)
처음엔 모두 같은 스토리지 페이지 공유
수정 발생 시 그 페이지만 클론 전용 복사 (COW)
production DB의 클론을 만들어 production-grade 데이터로 테스트하는 패턴이 있다. 일반 mysqldump/export는 TB 단위에서 수 시간 걸리지만, Aurora 클론은 거의 즉시 만들어진다. CI/CD 파이프라인에서 매 빌드마다 클론을 만들어 테스트하고 끝나면 삭제하는 워크플로우에도 쓸 수 있다.
| 시나리오 키워드 | 권장 |
|---|---|
| 표준 MySQL/PostgreSQL/MariaDB/Oracle/SQL Server | RDS |
| 5배 성능 / 15 replica / 자동 스토리지 확장 | Aurora |
| 글로벌 분산 + 1초 미만 lag | Aurora Global Database |
| 간헐적 트래픽 + 자동 확장 | Aurora Serverless v2 |
| 72시간 내 in-place 롤백 | Aurora MySQL Backtrack |
| Oracle/SQL Server BYOL | RDS (Aurora 미지원) |
| 최소 비용 단순 DB | RDS (Aurora 대비 ~20% 저렴) |
Aurora의 차별점은 "스토리지 레이어를 재설계했다"는 한 문장에서 파생된다.
시험은 이 인과관계를 시나리오 형태로 묻는다. "어떤 요구사항에서 어떤 Aurora 기능이 답인가"를 판단해야 한다.
RDS는 "기존 DBMS를 클라우드에 옮긴" 1세대 관리형 DB, Aurora는 "DBMS를 클라우드 네이티브로 다시 설계한" 2세대다. DynamoDB는 "관계형 모델 자체를 버린" 또 다른 답이다. 같은 문제(데이터 영속성, 확장성, 가용성)에 세 가지 다른 답이 있다는 점을 이해하면 시험 시나리오를 풀 수 있다.
다음 글에서는 이번 주 전체(RDS + ElastiCache + Aurora)를 시나리오 중심으로 묶고, Week 7 종합 평가를 정리한다.
선택지를 클릭하면 정답·해설이 펼쳐집니다.
문제 1
Aurora의 스토리지 구성으로 옳은 것은?
문제 2
Aurora Replica와 RDS Read Replica의 가장 큰 차이는?
문제 3
한 SaaS 회사가 글로벌 사용자를 대상으로 Aurora MySQL을 사용 중이다. 도쿄·런던에서도 read latency가 100ms 이하여야 하고, 서울 region이 다운되면 1분 내 다른 region으로 failover해야 한다. 가장 적합한 구성은?
문제 4
Aurora Serverless v2의 특징으로 옳지 않은 것은?
문제 5
Aurora Backtrack에 대한 설명으로 옳은 것은?
문제 6
Aurora Reader Endpoint의 부하 분산 메커니즘은?
문제 7
한 핀테크 회사가 Aurora MySQL production DB의 데이터로 매일 밤 분석 환경을 만들고 싶다. 기존엔 mysqldump + import로 6시간 걸렸는데, 5분 안에 끝내고 싶다. 가장 적합한 방법은?