AWS Aurora MySQL로 재해복구(DR) 구성하기
회사에서 DB는 밴드의 드러머랑 비슷해요. 평소엔 눈에 잘 안 띄는데, 한 번 멈추면 공연이 끝납니다. 그래서 우리가 신경 써야 하는 게 바로 DR(Disaster Recovery, 재해복구). 오늘은 AWS에서 Amazon Aurora MySQL로 DR을 어떻게 깔끔하게 구성하는지, 실제로 무엇이 다른지, 장단점은 뭔지, 대체제와 비교하면 어떤지까지 한 번에 정리해드릴게요. 어려운 용어? 최대한 쉬운 예로 풀어서 갑니다.
참고: 원문 링크 — 우아한형제들 기술블로그(배민 테크블로그)
DR, 한 줄 정의
- DR은 “서비스가 박살나도(지진, 화재, 리전 장애, 사람 실수…) 데이터를 최대한 잃지 않고, 빠르게 다시 일어나게 만드는 전체 계획”입니다.
- 핵심 지표:
- RPO(Recovery Point Objective): 잃을 수 있는 데이터 최대치(예: 1초). “얼마나 최근까지의 데이터를 살릴 수 있나?”
- RTO(Recovery Time Objective): 복구 완료까지 걸리는 시간(예: 1분). “얼마나 빨리 살아나나?”
Aurora MySQL로 제대로 구성하면, RPO/RTO를 현실적으로 꽤 낮출 수 있습니다. 그게 오늘의 포인트예요.
왜 Aurora MySQL인가? (한 줄 요약: 스토리지 레벨의 마법)
- 일반 MySQL 복제는 “binlog(변경 로그)”를 읽고 쓰는 논리적 복제라 지연이 늘 수 있어요.
- Aurora는 스토리지 계층(6중 복제, 3AZ)에 로그를 거의 실시간으로 복제해서, 쓰기/복구 성능이 안정적이고, Global Database로 지역 간(리전 간) 복제까지 빠르게 뻗습니다.
- 간단히 말해 “SSD에 바로 새겨 넣고, 그걸 빠르게 다른 도시로 복사해두는 느낌”이라서 DR에 유리합니다.
Aurora로 DR 구성하는 3가지 루트
1) 최상: Aurora Global Database
- 형태: 한 리전(Region)에 Primary(쓰기 가능), 다른 리전들에 Secondary(읽기 전용) 클러스터.
- 특징:
- 스토리지 레벨 비동기 복제. 보통 지연이 1초 미만(공식 문서 기준 “typical <1s”)인 경우가 많음.
- 장애 시 Secondary를 승격(promote)하면 새 Primary로 전환. 일반적으로 수십 초~1분대 RTO를 기대.
- Secondary에서 읽기 부하 분산. Write forwarding 기능(옵션)으로 보조 리전에서의 쓰기를 Primary로 전달 가능(지연 감수). 멀티라이터는 아님.
- 장점:
- 낮은 RPO/RTO. 리전 장애에도 빠르게 기동.
- 애플리케이션 코드 변경이 적음(엔드포인트 전환 정도).
- 리드(읽기) 글로벌 분산으로 성능 이점.
- 단점:
- 비용이 제법 나갑니다(보조 리전 클러스터/스토리지/리전 간 데이터 전송).
- 아키텍처가 살짝 복잡. 네트워크/보안/운영 자동화 설계 필요.
- 자동 완전 무인 글로벌 페일오버는 아직 ‘클릭 한 번 or 자동화 스크립트’ 수준으로 봐야 합니다(운영 플랜 필수).
참고 문서:
- Aurora Global Database 소개: https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-global-database.html
- 운영 모범사례(블로그): https://aws.amazon.com/blogs/database/running-multi-region-applications-with-amazon-aurora-global-database/
2) 실속: RDS MySQL(또는 다른 MySQL)로 외부 복제
- 형태: Primary는 Aurora MySQL, 다른 리전에 RDS MySQL(또는 EC2 MySQL/온프레)로 binlog 기반 논리 복제.
- 장점:
- 비용 탄력적(보조를 더 작은 스펙으로 시작 가능).
- Aurora에 묶이지 않고 범용 MySQL로 복구 가능(탈AWS 고려 시 유리).
- 단점:
- 복제 지연이 커질 수 있음(네트워크·부하 영향). RPO가 분 단위가 될 수도.
- 페일오버 때 수동 손질이 많음(복제 끊기, 승격, 엔드포인트 전환).
- 운영 난이도↑.
참고 문서:
- Aurora MySQL → MySQL 복제: https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Replication.MySQL.html
3) 기본기: 단일 리전 Multi-AZ + 스냅샷/백업 기반 DR
- 형태: 같은 리전 Multi-AZ(고가용성), 주기 스냅샷과 PITR(Point-In-Time Recovery)로 다른 리전에 복구.
- 장점:
- 비용/구성 간단. 대부분의 서비스 초기엔 이걸로도 충분.
- 단점:
- 리전 장애면 스냅샷으로 재배포해야 해서 RTO가 길고, RPO도 백업 주기에 의존.
구성 따라 하기: Aurora Global Database 버전
아래는 “현실적으로 많이 쓰는” 파이프라인입니다. 콘솔/CLI 어느 쪽이든 큰 흐름은 같습니다.
1) 네트워크/보안 바닥 깔기
- 각 리전에 VPC, 2~3개 서브넷(AZ 분산), 보안 그룹 준비.
- 보안 그룹: 앱→DB 3306 포트, 관리용 접근 최소화.
- DNS는 Route 53 권장(페일오버 라우팅 편해요).
2) Primary 리전에 Aurora MySQL 클러스터 만들기
- 엔진: Aurora MySQL(보통 MySQL 8.0 호환 v3 권장).
- DB 인스턴스: Writer 1대 + Reader N대(읽기 분산/백업용).
- 백업 유지기간 설정(PITR), 암호화(KMS) ON. KMS는 다중 리전 키 고려(다른 리전에서도 복호화되게).
- 파라미터 그룹: binlog 관련은 외부 복제를 안 쓰면 기본값이면 충분. (특수 요구 없으면 Aurora Global DB엔 필수 아님)
- 옵션: Backtrack(수분~수시간 롤백), 성능 인사이트.
3) Global Database로 확장
- 콘솔: Global Database 생성 → “Add region”으로 보조 리전 추가 → 보조 리전에 “Reader 인스턴스” 구성.
- CLI(개념 예시): 실제 파라미터는 환경에 맞춰 조정하세요.
aws rds create-global-cluster --global-cluster-identifier my-aurora-global aws rds create-db-cluster --db-cluster-identifier primary-cluster \ --engine aurora-mysql --engine-version 8.0.mysql_aurora-3.x \ --global-cluster-identifier my-aurora-global ... # 보조 리전에서 (해당 리전 프로파일/엔드포인트로): aws rds create-db-cluster --db-cluster-identifier secondary-cluster \ --engine aurora-mysql --engine-version 8.0.mysql_aurora-3.x \ --global-cluster-identifier my-aurora-global ...
4) 애플리케이션 연결
- Primary 쓰기는 Writer Endpoint로.
- 읽기 부하는 Primary/Secondary 리전의 Reader Endpoint로 분산.
- 드라이버 설정: DNS TTL 짧게, 연결 재시도/타임아웃, 커넥션 풀 재생성 전략 준비.
5) 페일오버(훈련이 반, Fail-over)
- 용어: Fail-over는 이중화 구성된 환경에서 장애가 발생했을 때 임시 서버 영역으로 전환되는 것을 말해요. 정상화 되어서 다시 원상태로 복원하는 것은 페일백(Failback)이라고 하죠.
- 시나리오:
- 계획된 전환: Console/CLI로 “Managed planned failover” 수행(다운타임 최소화).
- 비계획 전환: Secondary 리전에서 보조 클러스터 승격(promote) → Route 53 엔드포인트 스위치 → 앱 재시도/풀 리프레시.
- 자동화:
- CloudWatch 알람 → EventBridge → Lambda로 승격/Route 53 업데이트 스크립트.
- 운영 Runbook 문서화: 누가, 언제, 무엇을, 순서대로.
6) 운영 체크리스트
- 모니터링: ReplicaLag, CommitLatency, Deadlock, MaxConnections, CPU, IOPS.
- 백업: 정기 스냅샷+PITR 검증(실제 복구 테스트).
- 보안: KMS 키 로테이션, 암호화, 최소 권한, 감사.
- 비용: 보조 리전 인스턴스/스토리지/데이터 전송 요금 주기 점검.
- DR 리허설: 분기별로 “게임데이” 운영(진짜로 스위치해보는 연습).
RPO/RTO 현실 수치(경험치+공식 가이드 기준)
- Aurora Global Database:
- RPO: 보통 1초 미만(네트워크/부하에 따라 달라짐).
- RTO: 계획 전환 수십 초
1분대, 비계획 전환도 1수분 내 목표 가능(자동화 수준에 좌우).
- 외부 복제(MySQL binlog):
- RPO: 수십 초~수분(피크 시 더 늘 수 있음).
- RTO: 수분~수십 분(승격과 연결 전환 절차가 더 큼).
- 스냅샷/백업 기반:
- RPO: 백업 주기 의존(최대 하루).
- RTO: 새로 띄우는 데 수십 분~수시간.
이건 어디까지나 “설계+운영 품질”에 따라 움직입니다. 테스트가 답입니다. 진짜로 스위치해보면 감이 와요.
다른 제품들과 비교
- Aurora MySQL vs RDS MySQL
- Aurora 장점: 스토리지 레벨 복제(6중, 3AZ), 빠른 장애 복구, Global Database로 저지연 리전 간 복제, 성능/운영 편의성.
- RDS MySQL 장점: 더 친숙하고 싸게 시작 가능, Aurora 독점 기능에 덜 묶임.
- DR 관점: RPO/RTO를 낮추고 싶으면 Aurora 우세. 비용/단순성은 RDS MySQL이 가벼움.
- Aurora MySQL vs 자체 MySQL(EC2, 온프레)
- Aurora 장점: 관리형(백업·패치·모니터링), 스토리지 복제, 글로벌 옵션.
- 자체 구축 장점: 완전 자유(커스텀 가능), 라이선스 자유도.
- DR 관점: 시간·인력 여유 없으면 Aurora가 압승. 고유 요구가 있으면 직접 구축도 의미.
- Aurora MySQL vs GCP Cloud SQL / Azure Database for MySQL
- 기능 세대가 비슷해도 “Global DB”로 스토리지 레벨 저지연 리전 복제는 Aurora가 강력한 편.
- 대신 멀티클라우드 DR이 필요하면 Aurora Global만으론 부족. 외부 복제나 CDC로 끌어가야.
- Aurora MySQL vs 분산 SQL(CockroachDB, YugabyteDB)
- 이들은 본질이 멀티리전/멀티리더 지향. 대신 운영 복잡도와 학습 비용이 큼.
- Aurora는 “관리형 MySQL 호환”이라는 익숙함 속에서 글로벌 리드 확장과 빠른 DR을 줌.
장단점 총정리
장점
- 스토리지 레벨 복제로 낮은 RPO, 빠른 RTO.
- 글로벌 리드 확장(Secondary 리전에서 읽기 분산).
- 운영 난이도 대비 성능·안정성 우수.
- 백업/PITR/모니터링/암호화 등 관리 기능 일체 포함.
단점
- 비용: 보조 리전까지 운영하면 월 청구서가 무거워짐.
- 완전 자동의 ‘무인’ 글로벌 페일오버는 여전히 자동화 스크립트/런북이 필요.
- MySQL 100% 동일은 아님(엔진·파라미터·일부 기능 제약 존재). 특정 기능 호환성은 사전 검증 필수.
- 크로스리전 쓰기 지연(Write Forwarding)은 편의 기능이지 저지연 다중 쓰기 대체는 아님.
돈 얘기(간단 계산 포인트)
- 컴퓨트: Primary/Secondary 각각의 DB 인스턴스 시간당 요금.
- 스토리지: 클러스터 스토리지(GB·월), 백업 스토리지.
- 리전 간 데이터 전송: 변경분 복제 비용.
- 추가 기능: Performance Insights, Enhanced Monitoring 등.
- 네트워크: NAT/인터페이스 비용 미미하지만 트래픽 많으면 체크.
Secondary는 업무 시간 외 Scale-down, 읽기 부하 없을 땐 최소 사양부터 시작 → 점진 증설. 예약 인스턴스/세이빙 플랜도 계산해볼 만합니다.
앱 개발자가 챙기면 좋은 것들
- 커넥션 재시도/풀 리프레시 로직: 페일오버 때 필수.
- DNS TTL, JDBC 드라이버 failover 옵션, Read/Write split.
- 멱등성(Idempotency): 같은 요청 두 번 처리돼도 안전하도록(장애 순간 중복 가능).
- 읽기 일관성: 글로벌 읽기는 미세한 지연/오래된 데이터 가능. 비즈니스 허용범위 설정.
- 장애 훈련: “우리 서비스는 진짜로 몇 분 안에 살아나나?” 팀 전체가 몸으로 알아야 합니다.
간단 실무 시나리오 예시
- 음원 스트리밍 서비스
- Primary(서울) Writer + Reader 2대.
- Secondary(도쿄) Reader 2대로 현지 사용자 읽기 지연 줄이기.
- 매월 DR 리허설: 도쿄 승격 → Route 53 전환 → 앱 확인 → 롤백.
- 결과: RTO 2분, RPO 1초 미만 목표로 안정 운영.
- 커머스 결제
- 강한 쓰기 일관성 필요. 글로벌 멀티라이터는 지연/복잡도가 큼.
- 현실적 타협: 단일 리전 쓰기 + 보조 리전 읽기. 결제는 항상 Primary에서.
- 장애 시 페일오버 스크립트 즉시 실행. 큐 기반으로 주문/결제 재처리 안전장치.
한 번에 보기: 구축 단계 체크리스트
- 리전/AZ 설계, VPC·서브넷·SG 구성
- Aurora MySQL Primary 클러스터 생성, 백업·암호화·모니터링 설정
- Global Database로 보조 리전 추가, Reader 구성
- 애플리케이션 엔드포인트/드라이버 설정(재시도·TTL·풀 리프레시)
- Route 53 페일오버/헬스체크 또는 Lambda 자동화
- CloudWatch 알람, 로그, 성능지표 대시보드
- DR 리허설(분기 1회 이상), RPO/RTO 실제 수치 기록
- 비용 점검 및 스케일 정책 수립
참고 자료(공식)
- Aurora Global Database: https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-global-database.html
- Aurora MySQL 복제(외부 MySQL): https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Replication.MySQL.html
- Backtrack: https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Managing.Backtrack.html
- RDS/Aurora 엔드포인트: https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.Overview.Endpoints.html
- AWS 블로그(글로벌 DB 사례): https://aws.amazon.com/blogs/database/running-multi-region-applications-with-amazon-aurora-global-database/
참고: 우아한형제들 기술블로그 원문(이미지 포함)
마무리: “DR은 보험이 아니라 근력”
DR은 ‘혹시 몰라서’가 아니라 ‘기본 체력’입니다. 평소에 근력 운동하듯이, 작은 다운타임이라도 바로 일어나는 습관을 몸에 익히면, 진짜 큰 장애가 와도 크게 흔들리지 않습니다. Aurora MySQL + Global Database는 그 근력을 키우기 딱 좋은 헬스장 기구 같아요. 요령은 간단합니다. 작게 시작하고, 자주 연습하고, 숫자로 확인하세요. 그럼 어느 순간 “장애? 와도 된다”는 자신감이 생깁니다. 그게 진짜 팀의 경쟁력이죠.