RDS 읽기 전용 복제본으로 SELECT 부하 분산하기 — Multi-AZ와의 차이점까지

프로덕션 RDS 인스턴스의 CPU가 SELECT 쿼리 때문에 80%를 넘어서는 순간, 대부분의 엔지니어는 인스턴스를 스케일업하거나 캐시 레이어를 먼저 떠올린다. 하지만 읽기 부하가 명확히 분리 가능한 구조라면, RDS 읽기 전용 복제본(Read Replica)이 가장 직접적인 해결책이다. 문제는 Read Replica와 Multi-AZ를 혼동해서 잘못된 선택을 하는 경우가 생각보다 많다는 점이다.

TL;DR — Read Replica vs. Multi-AZ 핵심 비교

항목Read ReplicaMulti-AZ
주목적읽기 부하 분산 (성능)자동 장애 조치 (가용성)
복제 방식비동기 복제동기 복제
엔드포인트별도 엔드포인트 제공단일 엔드포인트 (자동 전환)
읽기 트래픽 수신가능 (직접 연결)불가 (Standby는 읽기 불가)
독립 승격가능 (독립 DB로 승격)자동 장애 조치만 지원
리전 간 배포가능 (Cross-Region)단일 리전 내 다중 AZ
비용 구조Replica 인스턴스 비용 추가Standby 인스턴스 비용 추가

RDS 읽기 전용 복제본이 동작하는 방식

Read Replica는 소스 DB 인스턴스의 변경 사항을 비동기적으로 수신한다. MySQL과 MariaDB는 바이너리 로그(binlog) 기반 복제를 사용하고, PostgreSQL은 물리적 복제 슬롯(WAL 스트리밍)을 사용한다. 이 비동기 특성 때문에 Replica에는 항상 약간의 복제 지연(replication lag)이 존재할 수 있다 — 최신 데이터가 반드시 필요한 쿼리에는 적합하지 않다.

애플리케이션은 소스 인스턴스의 엔드포인트와 별개로 Replica 전용 엔드포인트에 직접 연결해야 한다. RDS가 자동으로 쿼리를 라우팅해주지 않는다. 읽기/쓰기 분리는 애플리케이션 레벨 또는 프록시 레이어(예: RDS Proxy)에서 처리해야 한다.

graph LR App["애플리케이션"] Source["소스 인스턴스
(쓰기 엔드포인트)"] R1["Read Replica 1
(읽기 엔드포인트)"] R2["Read Replica 2
(읽기 엔드포인트)"] App -->|"INSERT / UPDATE / DELETE"| Source Source -->|"비동기 복제"| R1 Source -->|"비동기 복제"| R2 App -->|"SELECT"| R1 App -->|"SELECT"| R2
  1. 애플리케이션은 쓰기(INSERT/UPDATE/DELETE)를 소스 인스턴스 엔드포인트로 전송한다.
  2. 소스 인스턴스는 변경 사항을 비동기적으로 Read Replica에 복제한다.
  3. 애플리케이션은 SELECT 쿼리를 Replica 엔드포인트로 직접 라우팅한다.
  4. 여러 Replica가 있을 경우, 애플리케이션 또는 RDS Proxy가 부하를 분산한다.

Multi-AZ는 읽기 부하를 분산하지 않는다

Multi-AZ의 Standby 인스턴스는 읽기 트래픽을 받지 않는다. 소스와 동기 복제를 유지하면서 장애 발생 시 자동으로 승격되는 것이 유일한 역할이다. 즉, Multi-AZ를 활성화해도 SELECT 부하는 전혀 줄어들지 않는다.

Multi-AZ는 비행기의 보조 엔진과 같다. 평소에는 작동하지 않지만, 주 엔진이 멈추면 즉시 인계받는다. Read Replica는 실제로 함께 비행하는 두 번째 비행기다.

두 기능은 상호 배타적이지 않다. 프로덕션 환경에서는 Multi-AZ로 가용성을 확보하고, Read Replica로 읽기 성능을 확장하는 구성을 함께 사용하는 것이 일반적이다.

RDS 읽기 전용 복제본 생성 — 단계별 가이드

1단계: 소스 인스턴스 자동 백업 활성화 확인

Read Replica를 생성하려면 소스 인스턴스의 자동 백업이 활성화되어 있어야 한다 — 백업 보존 기간이 0보다 커야 한다. 이 조건이 충족되지 않으면 Replica 생성 자체가 실패한다. 먼저 현재 설정을 확인한다.

aws rds describe-db-instances \
  --db-instance-identifier my-source-db \
  --query 'DBInstances[0].BackupRetentionPeriod' \
  --output text

반환값이 0이면 자동 백업이 비활성화된 상태다. 다음 명령으로 활성화한다.

aws rds modify-db-instance \
  --db-instance-identifier my-source-db \
  --backup-retention-period 7 \
  --apply-immediately

2단계: Read Replica 생성

소스 인스턴스와 동일한 리전에 Replica를 생성한다. 인스턴스 클래스는 워크로드에 맞게 조정할 수 있다 — 읽기 전용이라도 소스보다 작은 클래스를 사용하면 복제 지연이 누적될 수 있다.

aws rds create-db-instance-read-replica \
  --db-instance-identifier my-read-replica \
  --source-db-instance-identifier my-source-db \
  --db-instance-class db.r6g.large \
  --availability-zone us-east-1b \
  --publicly-accessible false

3단계: Replica 엔드포인트 확인

Replica가 available 상태가 되면 전용 엔드포인트를 확인한다. 이 엔드포인트를 애플리케이션의 읽기 전용 데이터소스 설정에 사용한다.

aws rds describe-db-instances \
  --db-instance-identifier my-read-replica \
  --query 'DBInstances[0].Endpoint' \
  --output table

4단계: 복제 지연 모니터링

비동기 복제의 특성상 Replica가 소스보다 얼마나 뒤처져 있는지 지속적으로 확인해야 한다. CloudWatch의 ReplicaLag 메트릭이 이를 측정한다. 지연이 지속적으로 증가한다면 Replica 인스턴스 클래스를 업그레이드하거나 Replica 수를 조정해야 한다.

aws cloudwatch get-metric-statistics \
  --namespace AWS/RDS \
  --metric-name ReplicaLag \
  --dimensions Name=DBInstanceIdentifier,Value=my-read-replica \
  --start-time 2024-01-15T00:00:00Z \
  --end-time 2024-01-15T01:00:00Z \
  --period 60 \
  --statistics Average \
  --output table

운영 중 자주 겪는 실수 — 증상에서 원인까지

Replica를 만들었는데 소스 인스턴스 CPU가 전혀 줄지 않는 경우가 있다. 로그를 보면 읽기 쿼리가 여전히 소스 엔드포인트로 들어오고 있다. 처음엔 Replica 복제 문제를 의심하기 쉽지만, 실제 원인은 대부분 애플리케이션 설정이다.

ORM 프레임워크(예: Spring Data JPA, Django ORM)는 기본적으로 단일 데이터소스를 사용한다. Replica 엔드포인트를 별도 데이터소스로 등록하고, 읽기 전용 트랜잭션이나 쿼리를 해당 데이터소스로 명시적으로 라우팅하는 설정을 추가하지 않으면 모든 쿼리가 소스로 향한다. RDS 자체는 쿼리 유형을 보고 자동으로 라우팅하지 않는다.

RDS Proxy를 사용하는 경우에도 동일하다 — Proxy 자체가 읽기/쓰기를 자동으로 분리하지 않는다. 읽기 전용 Proxy 엔드포인트를 별도로 구성하고 애플리케이션이 이를 사용하도록 설정해야 한다.

스토리지 암호화와 Cross-Region Replica 고려사항

암호화되지 않은 소스 인스턴스에서도 암호화된 Read Replica를 생성할 수 있다. 이는 기존 암호화되지 않은 DB를 암호화하는 데 활용되는 일반적인 방법이다 — Replica를 암호화된 상태로 생성한 뒤 독립 인스턴스로 승격하는 방식이다.

Cross-Region Read Replica는 재해 복구(DR) 전략의 일환으로 사용할 수 있다. 다른 리전에 Replica를 생성하면 해당 리전에서 독립 인스턴스로 승격 가능하다. 단, 리전 간 데이터 전송 비용이 발생하며, 복제 지연이 동일 리전 대비 더 클 수 있다.

aws rds create-db-instance-read-replica \
  --db-instance-identifier my-cross-region-replica \
  --source-db-instance-identifier arn:aws:rds:us-east-1:123456789012:db:my-source-db \
  --db-instance-class db.r6g.large \
  --region ap-northeast-2

Read Replica에 필요한 최소 IAM 권한

Replica 생성 및 모니터링에 필요한 최소 권한은 다음과 같다. 프로덕션 환경에서는 특정 리소스 ARN으로 범위를 제한하는 것을 권장한다.

🔽 IAM 정책 예시 (클릭하여 펼치기)
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "RDSReadReplicaManagement",
      "Effect": "Allow",
      "Action": [
        "rds:CreateDBInstanceReadReplica",
        "rds:DescribeDBInstances",
        "rds:ModifyDBInstance",
        "rds:DeleteDBInstance"
      ],
      "Resource": "arn:aws:rds:us-east-1:123456789012:db:*"
    },
    {
      "Sid": "CloudWatchReplicaLagMonitoring",
      "Effect": "Allow",
      "Action": [
        "cloudwatch:GetMetricStatistics",
        "cloudwatch:ListMetrics"
      ],
      "Resource": "*"
    }
  ]
}
graph TD A["시작: 읽기 부하 증가"] --> B{"자동 백업 활성화? (BackupRetentionPeriod > 0)"} B -->|"아니오"| C["modify-db-instance 백업 보존 기간 설정"] C --> D["Read Replica 생성"] B -->|"예"| D D --> E["Replica 상태 확인 (available 대기)"] E --> F["애플리케이션 읽기 데이터소스 Replica 엔드포인트로 변경"] F --> G["ReplicaLag 모니터링 (CloudWatch)"] G --> H{"지연 누적?"} H -->|"예"| I["Replica 인스턴스 클래스 업그레이드 또는 Replica 추가"] H -->|"아니오"| J["정상 운영"]
  1. 자동 백업 활성화 여부를 먼저 확인한다 — 이 조건이 없으면 Replica 생성이 차단된다.
  2. Replica 생성 후 available 상태가 될 때까지 대기한다.
  3. 애플리케이션의 읽기 전용 데이터소스를 Replica 엔드포인트로 구성한다.
  4. ReplicaLag 메트릭을 지속적으로 모니터링하여 지연 누적 여부를 확인한다.

RDS 읽기 전용 복제본 스케일링 마무리 및 다음 단계

Read Replica는 SELECT 부하를 소스 인스턴스에서 분리하는 가장 직접적인 방법이다. 단, 효과를 보려면 애플리케이션이 실제로 Replica 엔드포인트를 사용하도록 명시적으로 구성해야 하고, 복제 지연을 지속적으로 모니터링해야 한다. Multi-AZ는 가용성 문제를 해결하지만 읽기 성능과는 무관하다 — 두 기능의 목적을 명확히 구분하는 것이 올바른 아키텍처 결정의 출발점이다.

다음 단계로 고려할 수 있는 옵션:

핵심 용어 정리

용어설명
Read Replica소스 DB의 변경 사항을 비동기적으로 수신하는 읽기 전용 복제 인스턴스. 별도 엔드포인트를 통해 읽기 트래픽을 수신한다.
Multi-AZ동기 복제를 통해 Standby 인스턴스를 유지하는 고가용성 구성. Standby는 읽기 트래픽을 처리하지 않는다.
ReplicaLag소스 인스턴스와 Replica 간의 복제 지연 시간(초). CloudWatch에서 모니터링 가능하다.
비동기 복제소스가 트랜잭션을 커밋한 후 Replica에 변경 사항을 전달하는 방식. Replica에 최신 데이터가 즉시 반영되지 않을 수 있다.
승격 (Promote)Read Replica를 독립적인 쓰기 가능 DB 인스턴스로 전환하는 작업. 소스와의 복제 연결이 끊어진다.

Related Posts

댓글

이 블로그의 인기 게시물

EC2 SSH 연결 타임아웃 완전 해결 가이드: Security Group 인바운드 규칙부터 라우팅까지

S3 정적 웹사이트 호스팅 완전 가이드: HTML/CSS 사이트를 무료로 배포하는 법

EC2 인스턴스 중지(Stop) vs 종료(Terminate): EBS 데이터는 살아남는가