기준: DVA-C02 시험 가이드오류 제보
RDS를 처음 쓰는 사람들은 보통 "EC2에 MySQL 깔면 되는데 왜 굳이 RDS?"라고 묻는다. 그 답은 단순한 편의성이 아니다. RDS는 "관계형 데이터베이스의 운영(Day-2 ops)이라는, 사실은 가장 무겁고 실수가 잦은 영역을 AWS가 대신 짊어진다"는 약속이다. 마이너 패치, 백업, 로그 회전, 페일오버 자동화, 스토리지 확장 — 이 모든 게 콘솔 토글이나 API 한 번으로 끝난다.
DVA-C02 시험에서 RDS가 차지하는 비중은 단순한 "DB 선택지"가 아니다. Lambda·API Gateway·ECS 같은 컴퓨트 서비스가 어떤 데이터 스토어를 선택해야 하는지를 묻는 시나리오 문제에서 RDS가 후보로 나온다. 그래서 Multi-AZ와 Read Replica의 차이, 그리고 이 둘이 Aurora나 DynamoDB와 어떻게 갈리는지를 먼저 구분해 둘 필요가 있다.
RDS는 2009년 10월 출시됐다. 당시 AWS는 EC2(2006)와 S3(2006)로 IaaS 시장을 장악한 상태였지만, "EC2에 DB를 직접 깔자"는 흐름은 의외로 더디게 퍼졌다. 이유는 DBA의 부재였다. 스타트업이 EC2에 MySQL을 띄우긴 쉬워도, 매일 새벽 백업이 깨졌을 때 복구할 사람이 없었다. 데이터 한 번 날리면 서비스가 끝나는 회사가 속출했다.
RDS는 그 공백을 메우려고 나왔다. 자동 백업·자동 패치·자동 페일오버를 옵션 토글 수준으로 내려서, DBA 없는 팀도 운영 가능한 RDBMS를 제공한다는 것이 핵심 가치 제안이다. 이것이 시험에 나오는 "EC2 self-managed vs RDS managed" 비교의 본질이다. EC2는 자유와 책임을 모두 가져가고, RDS는 자유를 일부 양보하는 대신 책임을 AWS에 넘긴다.
| 비교 차원 | EC2에 직접 설치 | RDS | Aurora |
|---|---|---|---|
| OS·엔진 패치 | 직접 | AWS 자동 (윈도우 지정) | AWS 자동 |
| 자동 백업 | 직접 cron | 자동 (1-35일 보존) | 자동 + Backtrack |
| 페일오버 | HAProxy/Keepalived 수동 구성 | Multi-AZ (1-2분 자동) | 30초 이내 |
| 스토리지 | EBS 수동 확장 | Auto Scaling 옵션 | 10GB-128TB 자동 |
| 슈퍼유저 권한 | ✅ | ❌ (rdsadmin 제외) | ❌ |
| SSH 접근 | ✅ | ❌ | ❌ |
| OS 커스텀 모니터링 | ✅ | Enhanced Monitoring만 | 동일 |
| 가격 (동일 사양) | 인스턴스 + EBS | 약 20-30% 프리미엄 | 약 50% 프리미엄 (성능 5배) |
RDS에서 고객이 다루는 것은 DB 파라미터 그룹, 사용자 권한, 스키마, 데이터뿐이고 그 아래는 모두 AWS 책임이다.
지원 엔진은 6종이다. MySQL, PostgreSQL, MariaDB는 오픈소스로 라이선스 비용이 없고, Oracle, SQL Server는 상용 라이선스가 별도로 붙는다(Oracle은 BYOL 가능, SQL Server는 License Included만 가능).
Aurora MySQL/PostgreSQL은 AWS가 호환만 유지하면서 스토리지·복제 레이어를 완전히 재설계한 별개 엔진으로, RDS의 한 변종이지만 내부 아키텍처는 전혀 다르다(Day 34에서 상세히).
Multi-AZ는 한 줄로 표현하면 "다른 AZ에 standby를 두고 synchronous physical replication으로 동일 상태를 유지하다가, primary가 죽으면 DNS 엔드포인트를 standby로 옮긴다"는 메커니즘이다.
이 한 줄 안에 시험 문제와 실무 사고의 원인이 모두 들어 있다.
먼저 synchronous physical replication의 의미다. MySQL/PostgreSQL의 일반적인 binlog 기반 복제는 logical replication이다. RDS Multi-AZ는 그 아래 스토리지 레이어에서 EBS Multi-Attach와 유사한 블록 수준 복제를 쓴다(엄밀히는 DRBD 계열의 동기 블록 복제). 클라이언트가 commit을 보내면 primary는 standby에서 write ack를 받기 전까지 클라이언트에 OK를 돌려주지 못한다. 이것이 동기 복제의 본질이며, RPO(Recovery Point Objective)를 거의 0에 가깝게 만드는 이유다.
[클라이언트]
| commit
v
[Primary RDS] (AZ-a)
|
| EBS 블록 동기 복제 (AZ 간 RTT 1-2ms)
v
[Standby RDS] (AZ-b)
|
| write ack
^
[클라이언트]에 commit OK
AZ 간 RTT가 1-2ms이므로 Multi-AZ의 성능 비용이 생긴다. 한 트랜잭션의 commit latency가 single-AZ 대비 평균 +1-2ms 늘어난다. OLTP 워크로드에서 TPS 10,000 수준이라면 이 latency가 connection pool 깊이와 곱해져 처리량을 떨어뜨릴 수 있다. 운영 현장에서는 이를 "Multi-AZ는 RPO≈0의 대가로 약 10-15% 성능 페널티를 받는다"고 말한다. "성능이 우선" 시나리오에서 Multi-AZ를 답으로 고르면 함정에 빠진다.
페일오버 트리거는 6가지다. ① primary AZ 장애 ② primary 인스턴스 장애 ③ 네트워크 분할 ④ DB 인스턴스 클래스 변경(scale-up) ⑤ OS 패치 ⑥ 수동 reboot --force-failover. ⑤⑥은 운영자가 의도적으로 trigger하는 케이스다. 페일오버 자체는 60-120초가 일반적이다. DNS TTL이 짧아서(보통 5-30초) 애플리케이션에 연결 재시도 로직이 있으면 자동으로 재연결된다.
⚠️ 함정: "Multi-AZ Standby에서 읽기 쿼리를 처리할 수 있는가?" — 기존 Multi-AZ DB Instance Deployment에서는 불가능. Standby는 오직 페일오버 대기 + 백업 I/O 분산 용도다. 2022년 도입된 Multi-AZ DB Cluster Deployment(MySQL/PostgreSQL only)는 2개의 read-capable standby를 두어 standby에서 읽기가 가능하다. "Multi-AZ인데 standby에서 읽고 싶다"는 시나리오에서는 후자를 골라야 한다.
다른 클라우드와 비교하면 설계 철학이 더 또렷이 보인다.
| 차원 | AWS RDS Multi-AZ | GCP Cloud SQL HA | Azure Database for MySQL Flexible Server |
|---|---|---|---|
| 복제 방식 | 블록 수준 동기 | regional persistent disk (블록 동기) | binlog 기반 동기 |
| 페일오버 시간 | 60-120초 | 60초 이내 | 60-120초 |
| Standby 읽기 | 불가 (Cluster mode는 가능) | 불가 | Replica 옵션 별도 |
| 가격 | 2배 (standby 인스턴스 비용) | 약 2배 | zone-redundant HA 약 2배 |
2019년 8월 23일 AWS Tokyo 리전(ap-northeast-1)의 한 AZ에서 냉방 시스템 제어 SW 버그로 일부 서버가 과열되어 EC2·EBS·RDS가 약 6시간 영향을 받았다. 당시 Multi-AZ로 구성된 RDS는 자동 페일오버로 다른 AZ의 standby가 primary가 됐지만, Single-AZ로 배포된 RDS는 같은 AZ의 EBS가 죽으면서 함께 다운됐다. 교훈은 분명하다. RDS의 데이터는 한 AZ의 EBS에 묶여 있으므로 Single-AZ는 곧 Single-Point-of-Failure다.
Read Replica는 Multi-AZ와 완전히 다른 문제를 푼다. Multi-AZ가 가용성(availability)을 푼다면, Read Replica는 확장성(scalability), 그것도 읽기 트래픽 한정의 확장성을 푼다.
내부 동작은 logical asynchronous replication이다. MySQL은 binlog, PostgreSQL은 WAL streaming replication을 쓴다. primary가 트랜잭션을 commit하면 변경이 binlog/WAL에 기록되고, replica의 IO thread가 이를 pull해서 자기 storage에 apply한다. primary는 replica의 ack를 기다리지 않는다 — 그래서 primary 성능에 영향이 거의 없는 대신, replica는 항상 primary보다 수 ms ~ 수십 초 뒤처질 수 있다(replication lag).
# 실무 패턴: 읽기/쓰기 라우팅 분리
import pymysql
from contextlib import contextmanager
WRITER_HOST = "mydb.cxxxx.ap-northeast-2.rds.amazonaws.com"
READER_HOSTS = [
"mydb-ro-1.cxxxx.ap-northeast-2.rds.amazonaws.com",
"mydb-ro-2.cxxxx.ap-northeast-2.rds.amazonaws.com",
]
@contextmanager
def write_conn():
conn = pymysql.connect(host=WRITER_HOST, user="app", ...)
try: yield conn
finally: conn.close()
@contextmanager
def read_conn():
import random
host = random.choice(READER_HOSTS) # 단순 로드밸런싱
conn = pymysql.connect(host=host, user="app_ro", ...)
try: yield conn
finally: conn.close()
# 사용
def get_user_profile(user_id):
with read_conn() as c: # 읽기는 replica
return c.execute(...)
def create_order(order):
with write_conn() as c: # 쓰기는 primary
return c.execute(...)⚠️ 함정 (Read-Your-Writes 문제): "주문을 방금 INSERT 한 사용자가 바로 주문 목록을 조회"하는 시나리오에서 replica에 lag가 있으면 방금 만든 주문이 안 보인다. 해결 패턴은 세 가지다. ① 동일 세션 내 쓰기 직후 N초간은 primary에서 읽기 ② Aurora처럼 lag가 ms 단위인 엔진 사용 ③ session token/cookie에 commit timestamp를 담아 replica가 그 시점 이후 적용된 데이터인지 확인. 이는 분산 시스템에서 말하는 session consistency(또는 monotonic read consistency) 보장 패턴이다.
Read Replica의 비동기 복제는 분산 시스템의 eventually consistent 모델이다. 쓰기 가용성과 읽기 확장성을 위해 강일관성을 일부 양보하는 AP 시스템에 가깝다.
시험에 나오는 Read Replica의 제약은 다음과 같다.
두 기능이 헷갈리는 이유는 둘 다 "AZ가 분리된다"는 공통점이 있기 때문이다. 그러나 푸는 문제 자체가 다르다.
| 차원 | Multi-AZ | Read Replica |
|---|---|---|
| 목적 | HA / DR | 읽기 확장 + (선택적) DR |
| 복제 방식 | Synchronous block-level | Asynchronous logical |
| 일관성 | Strong (RPO≈0) | Eventual (lag 존재) |
| Standby 읽기 | ❌ (Cluster mode는 ✅) | ✅ |
| 자동 페일오버 | ✅ (60-120초) | ❌ (수동 promote) |
| 최대 개수 | 1 standby | 15 (MySQL/PG) |
| Cross-Region | ❌ (단일 리전) | ✅ |
| 추가 비용 | 인스턴스 2배 | replica 인스턴스당 |
| 시나리오 키워드 | "고가용성", "자동 페일오버", "DR" | "읽기 부하", "분석 쿼리", "지리적 분산" |
두 기능은 동시 사용이 가능하다. production에서 자주 쓰는 조합은 "Multi-AZ + 2-3개 Read Replica"다. Multi-AZ가 single-AZ 장애 대응을, Read Replica가 읽기 트래픽 분산과 분석 쿼리 격리를 담당한다. "고가용성 + 분석 워크로드 격리"가 동시에 나오면 둘 다 답이다.
DVA 시험에서 RDS Proxy는 Lambda 시나리오의 정답 후보로 나온다. Lambda + RDS 조합의 대표적인 안티패턴을 해결하는 도구이기 때문이다.
문제 상황: Lambda는 요청당 컨테이너가 생기고 죽는다. 동시 호출이 1,000개 들어오면 Lambda 1,000개가 각자 RDS에 새 TCP 연결을 만든다. MySQL은 connection 하나당 메모리 ~256KB ~ 1MB를 쓰고, max_connections는 인스턴스 클래스에 따라 100-1,000 수준이다. 즉 burst 트래픽 한 번에 RDS가 "Too many connections" 에러를 내며 멈춘다.
RDS Proxy는 그 사이에 connection pool을 둔다. Lambda는 proxy에 연결하고, proxy는 RDS에 미리 만들어둔 connection들을 재사용한다. 결과: RDS의 실제 connection 수는 proxy pool 크기로 고정되고, Lambda 동시성과 디커플링된다.
| 효과 | 수치 |
|---|---|
| Connection 재사용 | RDS connection 사용량 최대 66% 감소 |
| 페일오버 시간 | 클라이언트가 체감하는 페일오버 시간 66% 단축 |
| IAM 인증 통합 | Lambda 실행 역할로 DB 접근 |
| Secrets Manager 통합 | 비밀번호 자동 회전 지원 |
RDS Proxy는 내부적으로 multiplexing과 connection pinning 두 모드를 쓴다. Multiplexing은 여러 클라이언트 요청을 하나의 백엔드 connection에 인터리브해서 보내는 모드(가장 효율적). 그러나 트랜잭션 안에서 SET 같은 세션 변수를 쓰거나 LOCK TABLES, prepared statement, temp table을 쓰면 proxy가 pinning으로 전환해 그 클라이언트에 backend connection을 묶는다. Pinning이 많아지면 사실상 connection pool 효과가 사라지므로 CloudWatch DatabaseConnectionsCurrentlySessionPinned 메트릭을 모니터링해야 한다.
# 1) Multi-AZ로 RDS 생성
aws rds create-db-instance \
--db-instance-identifier mydb \
--db-instance-class db.t3.medium \
--engine mysql \
--master-username admin \
--master-user-password "$(aws secretsmanager get-random-password --output text --query RandomPassword)" \
--allocated-storage 20 \
--multi-az \
--backup-retention-period 7 \
--storage-encrypted
# 2) Read Replica 생성
aws rds create-db-instance-read-replica \
--db-instance-identifier mydb-ro-1 \
--source-db-instance-identifier mydb
# 3) 페일오버 수동 트리거 (테스트)
aws rds reboot-db-instance \
--db-instance-identifier mydb \
--force-failover
# 4) Replica를 독립 DB로 promote
aws rds promote-read-replica \
--db-instance-identifier mydb-ro-1RDS의 두 가지 핵심 기능은 분산 시스템의 두 가지 trade-off를 그대로 옮긴 것이다. Multi-AZ는 강일관성을 유지하면서 가용성을 확보하기 위해 AZ 간 동기 복제를 쓴다(같은 리전 내 CP). Read Replica는 읽기 확장을 위해 일관성을 약화시키고 비동기 복제를 쓴다(AP). 두 도구를 함께 쓰면 production-grade RDBMS 운영이 가능하다.
다음 글에서는 RDS의 또 다른 핵심 영역 — 암호화, IAM 인증, 백업, 모니터링 — 을 본다. Capital One 같은 사고가 왜 일어났는지, IMDSv2와 IAM DB Authentication이 그 답으로 어떻게 자라났는지를 같이 본다.
선택지를 클릭하면 정답·해설이 펼쳐집니다.
문제 1
한 핀테크 회사가 다음 요구사항을 모두 만족하는 RDS 아키텍처를 설계해야 한다. ① 단일 AZ 장애 시 RPO ≈ 0, RTO < 2분 ② 분석 팀의 무거운 read 쿼리가 OLTP 성능에 영향을 주지 않도록 격리 ③ 서울 ↔ 도쿄 간 DR 가능. 최소 비용으로 만족하는 구성은?
문제 2
Lambda 함수가 burst 트래픽 시 RDS MySQL에 "Too many connections" 에러를 일으킨다. 가장 직접적이고 비용 효율적인 해결책은?
문제 3
RDS Multi-AZ에 대한 다음 설명 중 옳은 것은?
문제 4
RDS Read Replica의 특성으로 옳지 않은 것은?
문제 5
EC2에 직접 MySQL을 설치한 환경에서 RDS로 마이그레이션할 때 잃게 되는 권한·기능이 아닌 것은?
문제 6
Aurora가 아닌 RDS MySQL/PostgreSQL에서 standby에서 읽기 쿼리를 처리하려면?
문제 7
한 게임 회사가 Asia-Pacific 전역 사용자를 대상으로 리더보드 조회 응답 latency를 100ms 이하로 유지하려 한다. 데이터는 MySQL에 저장돼 있고 쓰기는 서울 리전에서만 발생한다. 가장 적합한 구성은?