왜 이 사례를 봐야 할까요?

라이브 스포츠 중계처럼 트래픽이 초 단위로 0에서 수백만으로 치솟는 워크로드에서, 인프라 스케일링 자체보다 더 무서운 건 "스케일링이 안 먹히는 것처럼 보이는" 상황입니다. NLB를 2대에서 6대로 늘렸는데도 500 에러가 그대로 터진다면, 그건 서버 문제가 아니라 DNS 라우팅 정책 문제일 가능성이 큽니다.

이 글은 모바일 관측 플랫폼 bitdrift가 T20 월드컵 크리켓 중계 중 1억 2,100만 대의 동시 gRPC 연결을 처리한 실제 사례를 다룹니다. 핵심은 단 하나의 설정 변경이었어요. 코드도, 아키텍처도 건드리지 않았습니다.

근거자료: AWS Architecture Blog — How bitdrift scaled to 121 million concurrent gRPC connections

이 글을 읽고 나면 다음을 판단할 수 있게 됩니다.

  • 우리 서비스의 DNS 라우팅 정책이 persistent connection 환경에서 병목이 될 수 있는지
  • CloudFront + 다중 NLB 구조에서 왜 스케일 아웃이 무효화되는지
  • Multi-Value Answer 라우팅으로 전환할 때의 실무 체크리스트

CloudFront edge nodes distributing gRPC connections across multiple NLB origins via Route 53 multi-value routing System Abstract Visual

문제의 본질: Weighted 라우팅은 "한 번에 IP 1개"만 반환한다

많은 팀이 Route 53 Weighted 라우팅을 "부하 분산"이라고 이해합니다. 하지만 실제 동작은 다릅니다. Weighted 라우팅은 DNS 쿼리 1건당 IP 1개만 반환합니다. 가중치는 "어느 IP를 뽑을 확률"일 뿐, "여러 IP를 동시에 알려주는 것"이 아닙니다.

이게 CloudFront 규모에서 벌어지면 이렇게 됩니다.

  1. CloudFront 엣지 노드가 origin 도메인을 resolve → IP 1개 획득
  2. 그 IP를 TTL(60초) 동안 캐싱
  3. 모든 엣지 노드가 같은 타이밍에 같은 IP로 몰림
  4. 해당 NLB 하나가 thundering herd로 과부하
  5. NLB를 6대로 늘려도, 여전히 쿼리당 1개 IP만 반환 → 분산 안 됨

여기서 결정적인 차이가 있습니다. HTTP는 요청이 짧게 끝나지만, gRPC는 연결이 길게 유지됩니다. 연결이 성립된 순간 resolve된 origin에 그대로 눌러앉기 때문에, stateless 트래픽에서는 "약간 기울어진 정도"로 끝날 DNS 설정이 persistent connection에서는 치명적 과부하로 증폭됩니다.

해결책: Multi-Value Answer 라우팅

Multi-Value Answer 라우팅은 DNS 쿼리 1건당 최대 8개 IP를 반환하며, 레코드별 헬스 체크가 내장됩니다. CloudFront 엣지 노드는 첫 resolve 시점부터 여러 origin에 연결을 분산시킬 수 있습니다.

# 기존 Weighted 레코드 확인
aws route53 list-resource-record-sets \
  --hosted-zone-id Z0123456789ABCDEFGHIJ \
  --query "ResourceRecordSets[?Name=='origin.example.com.']"

# 각 NLB용 헬스 체크 생성 (Multi-Value 라우팅은 헬스 체크 필수)
aws route53 create-health-check --caller-reference "nlb-1-$(date +%s)" \
  --health-check-config '{
    "Type": "TCP",
    "FullyQualifiedDomainName": "nlb-1-abcdef.elb.us-east-1.amazonaws.com",
    "Port": 443,
    "RequestInterval": 10,
    "FailureThreshold": 3
  }'

# Multi-Value Answer 레코드 생성 (IP 기반 A 레코드, Alias 불가)
aws route53 change-resource-record-sets \
  --hosted-zone-id Z0123456789ABCDEFGHIJ \
  --change-batch '{
    "Changes": [{
      "Action": "CREATE",
      "ResourceRecordSet": {
        "Name": "origin.example.com",
        "Type": "A",
        "SetIdentifier": "nlb-1",
        "MultiValueAnswer": true,
        "TTL": 60,
        "ResourceRecords": [{"Value": "203.0.113.10"}],
        "HealthCheckId": "abcdef12-3456-7890-abcd-ef1234567890"
      }
    }]
  }'

반드시 지켜야 할 제약

  • Alias 레코드는 사용 불가. Multi-Value Answer는 IP 기반 A 레코드만 지원합니다. NLB 각 AZ에 Elastic IP를 할당해야 합니다.
  • ALB는 이 패턴에 못 씁니다. ALB는 고정 IP를 지원하지 않기 때문입니다.
  • 같은 레코드 이름에 라우팅 정책을 섞을 수 없습니다. Multi-Value 레코드 검증 후 기존 Weighted 레코드는 삭제해야 합니다.
  • TTL은 60초 정도로 낮게 유지하세요. 장애 조치 속도가 빨라집니다.

전환 전후를 정리하면 다음과 같습니다.

항목Before (Weighted)After (Multi-Value)
DNS 쿼리당 반환 IP1개최대 8개
origin 분산TTL 동안 단일 NLB로 집중첫 resolve부터 다중 NLB로 분산
급증 시 동작thundering herd, 단일 NLB 과부하균등 분산, 단일 병목 없음
피크 시 에러CloudFront ↔ NLB 구간 5xx 폭증서버 사이드 에러 0건
고객 측 변경DNS 설정 변경만

AWS architecture diagram showing Route 53 DNS routing layer between CloudFront and multi-AZ NLB fleet Development Concept Image

실측 데이터가 말해주는 것

이 사례에서 가장 인상적인 건 **"코드도, 아키텍처도 안 바꿨다"**는 사실입니다. 순수하게 Route 53 라우팅 정책만 교체했고, 결과는 다음과 같았습니다.

지표Before (3/1~2)After (3/7~9)개선
피크 5xx 에러율79.80%0.033%99.96% 감소 (약 2,418배)
평균 5xx 에러율1.87%0.003%99.84% 감소 (약 623배)
서버 사이드 장애다중 origin 실패0건100% 제거
동시 접속 기기 (3/8)1억 2,100만 대무에러 처리
피크 RPS563K164K이벤트 스케일 차이

특히 눈여겨볼 부분은 2월 27일 이벤트에서 약 80%의 요청이 HTTP 500으로 실패했다는 점입니다. 3월 1일에는 NLB를 4대로 늘렸는데도 문제가 재발했어요. Weighted 라우팅이 여전히 IP 1개만 반환했기 때문에, origin을 늘리는 행위 자체가 무의미했던 겁니다.

이 기술의 한계와 주의사항

  • Multi-Value가 만능은 아닙니다. DNS 기반 분산이므로, 클라이언트 측 DNS 캐싱이나 리졸버 동작에 따라 실제 분포가 편향될 수 있습니다.
  • 헬스 체크 지연에 주의. Request interval을 10초(Fast)로 두더라도, unhealthy 판정까지 최소 수십 초가 걸립니다. 순간적인 장애에는 여전히 취약합니다.
  • Elastic IP 관리 부담. NLB 각 AZ에 EIP를 붙여야 하므로 IP 관리 정책이 필요합니다. 오토스케일링과는 상성이 나쁩니다.
  • HTTP 워크로드에는 효과가 제한적. 짧은 요청-응답 패턴에서는 기존 Weighted 라우팅도 큰 문제가 없을 수 있습니다. persistent connection(gRPC, WebSocket)에서 특히 치명적이라는 점을 기억하세요.
  • 국내 SI/금융 환경에서는 사전 심의·보안 검토 절차 때문에 장애 중 긴급 DNS 변경이 어렵습니다. 평시에 Multi-Value 전환을 검증해두는 편이 안전합니다.

다음 단계 학습 방향

  1. Route 53 라우팅 정책 4종 비교 — Simple, Weighted, Latency, Multi-Value Answer, Failover의 실제 동작 차이를 직접 테스트해보세요.
  2. gRPC 로드밸런싱 심화 — 클라이언트 사이드 LB(예: gRPC의 round_robin) vs 서버 사이드 LB의 트레이드오프를 정리해두면 좋습니다.
  3. CloudFront origin failover 설계 — Multi-Value와 Origin Group을 조합한 이중 방어 전략을 검토해보세요.

프론트엔드 쪽 스케일링 이슈를 함께 보고 있다면 Interop 2026에서 주목할 CSS 신기능 정리도 참고해보세요. 그리고 서버리스/엣지 배포 파이프라인을 운영 중이라면 Vercel Node.js 20 지원 종료 마이그레이션 가이드도 미리 챙겨두시면 좋습니다.

Server engineer monitoring 121 million concurrent gRPC connections dashboard with zero error metrics Algorithm Concept Visual

정리: 스케일링이 안 먹힐 때 의심해야 할 것

이번 사례의 교훈은 명확합니다.

  1. DNS 라우팅 정책은 극한 스케일에서 아키텍처 결정만큼 중요합니다. Weighted와 Multi-Value Answer의 차이는 단순한 취향 문제가 아닙니다.
  2. persistent connection은 DNS 문제를 증폭시킵니다. HTTP에서는 무시할 수준의 편향이 gRPC/WebSocket에서는 서비스 전체 장애로 이어집니다.
  3. 스케일 아웃이 안 먹히면, 먼저 라우팅 계층을 의심하세요. NLB를 2대에서 6대로 늘렸는데도 에러가 그대로라면, 그건 origin 문제가 아닙니다.
  4. 사전 용량 검토(pre-event capacity review)를 습관화하세요. 라이브 이벤트 중에 근본 원인을 분석하는 건 지옥입니다.

만약 지금 CloudFront 뒤에 다중 NLB를 두고 gRPC나 WebSocket을 서비스하고 있다면, 오늘 바로 Route 53 콘솔을 열어 라우팅 정책을 확인하시길 권합니다. 설정 한 줄이 1억 대의 연결을 버티게 만들 수도, 혹은 무너뜨릴 수도 있습니다.

본 콘텐츠는 신뢰할 수 있는 출처를 바탕으로 AI 도구를 활용하여 초안이 작성되었으며, 편집자의 검토를 거쳐 발행되었습니다. 전문가의 조언을 대체하지 않습니다.