date
slug
author
status
tags(최대 3개)
summary
type
thumbnail
category
updatedAt
들어가며
인프라 관점에서 아임웹은 세 겹이 공존하는 프로덕션입니다. 자기 도메인을 연결할 수 있는 100만 개의 사이트, 이를 서빙하는 약 8만 개의 Amazon CloudFront 배포, 그 뒤의 Amazon EC2·Amazon ECS·Amazon EKS 세 세대 컴퓨팅이 함께 돌아갑니다. 평시 피크 기준 초당 약 3,000건의 요청을 처리하고(일 데이터 전송량 약 50TB), 대형 이벤트 때는 단일 고객사에서만 초당 12,000건이 넘는 트래픽이 몰리기도 합니다. 네트워크 복잡도는 고객 수에 비례해 증가합니다.
서비스 진입 경로는 계정과 VPC, 클러스터에 걸쳐 확장되어 왔습니다. 그 과정에서 로드밸런서 계층의 한도에 부딪혔는데, ECS 서비스당 Target Group 5개 제한처럼 한도 상향 신청으로는 풀리지 않는 것이 섞여 있었습니다. 이를 계기로 MFE(Microfrontend) 서빙 경로를 대상으로 서비스 네트워크를 재설계했습니다.
재설계의 골자는 외부 진입점(North-South)과 서비스 간 연결(East-West)의 분리입니다. 기존 CloudFront, WAF, 운영 ALB(Application Load Balancer) 진입점은 유지한 채, 계정 경계 통과는 NLB(Network Load Balancer), L7 라우팅은 Kong Gateway, 게이트웨이에서 애플리케이션까지의 연결은 Amazon VPC Lattice가 담당하도록 구성했습니다.
이 글에선 3가지 범위를 다룹니다. VPC Lattice의 적용 위치를 판단하기 위해 수행한 검증, Service 단위 과금 구조에 맞춘 서비스 통합과 그 과정에서 확인한 컨트롤러 제약, 무중단 이관을 위한 Pod 편입 시점 제어입니다. 본문의 수치와 동작은 자사 환경에서 측정한 값이며, 리전과 워크로드 특성에 따라 달라질 수 있습니다.
확장이 막힌 네트워크
아임웹 네트워크는 트래픽 대부분이 고객 소유의 도메인으로 들어오는 특수성을 가집니다. 약 8만 개의 고객 도메인이 각자의 CloudFront 배포를 거쳐 운영 ALB에 도달하고, ALB는 일반/VIP/이벤트/격리 등 고객 티어에 따라 6개로 나뉘어 있습니다. 티어가 달라도 응답하는 플랫폼은 하나입니다. 어느 ALB로 들어와도 같은 앱이 응답해야 하니, 공용 앱일수록 모든 ALB에 연결되어야 합니다. 이 규모에서 한도 상향 신청은 운영의 일부였지만, 상향으로 밀어낼 수 있는 한계와 설계를 바꿔야만 넘을 수 있는 한계는 다릅니다.
문제가 처음 나타난 곳은 MFE입니다. 앱 90여 개가
/{prefix}/* 경로 규칙으로 ALB를 타고 라우팅되는 구조에서 세 가지 한계가 나타났습니다.첫째, ALB 리스너 규칙 한도.
상향을 받아 200개로 운영 중이었지만 앱은 그보다 더 늘어날 전망이었고, 앱 수에 비례해 규칙이 늘어나는 구조 자체는 상향으로 해결되지 않습니다.
둘째, Amazon ECS 서비스당 Target Group 5개 제한
Target Group은 로드밸런서 1개에만 귀속됩니다. 한 앱을 여러 ALB에서 서빙하려면 ALB 수만큼 전용 Target Group이 필요한데, 공용 셸 앱은 모든 진입점에서 서빙되어야 해서 이미 5개를 다 썼습니다. 여섯 번째 ALB에는 연결할 수 없었습니다. 이 한도는 상향 대상이 아니며, 재설계의 직접적인 트리거였습니다.
셋째, ALB 증설은 이미 시도한 우회였습니다. MFE 전용 ALB 3개가 운영 ALB에서
/{prefix}/* 경로를 넘겨받는 2단 ALB 체인을 운영하고 있었는데, 규칙 상한이 3배가 될 뿐 증가 구조는 동일했고, ALB는 다른 ALB를 타겟으로 받을 수 없어 체인을 더 이어 붙일 수도 없었습니다.
여기에 신규 워크로드 런타임은 보안 격리를 위해 별도 AWS 계정의 Amazon EKS 클러스터로 이전하기로 결정된 상태였습니다. 요구사항을 정리하면 다음과 같습니다.
- 기존 CloudFront / WAF / 운영 ALB 진입점은 유지
- 서비스가 늘어도 기존 진입점의 로드밸런서와 ALB 규칙이 늘지 않아야 함
- 운영 계정 ALB에서 신규 계정 EKS로 VPC와 계정 경계를 넘어야 함.
- host와 path 기반 L7 라우팅이 필요
- 라우팅이 GitOps 선언으로 움직여야 한다: 프리뷰·카나리 포함
- Pod는 전부 private subnet: 제로 트러스트 지향
이 여섯 가지를 놓고 보면, 1번과 4번까지는 기존 ELB 체계 안에서도 풀 수 있습니다. 문제는 2번과 3번입니다. ELB 모델에서는 Target Group이 로드밸런서 1개에 귀속되어 진입점이 늘 때마다 연결 구성이 함께 늘어나지만, VPC Lattice는 서비스를 서비스 네트워크에 한 번 등록하면 여기에 연결된 여러 VPC·계정에서 공통으로 접근할 수 있습니다. "진입점 수 × 앱 수"로 곱해지던 연결 구성을 등록 한 번으로 끊을 수 있어 VPC Lattice를 검토하게 되었습니다.
왜 Lattice와 Kong인가
Amazon VPC Lattice는 VPC와 계정 경계를 넘어 서비스들을 연결하는 관리형 애플리케이션 네트워킹 서비스입니다. Service·Listener·Rule·Target Group 등 구성요소가 ALB와 거의 1:1로 대응됩니다. ALB를 아는 분이라면 구조가 낯설지 않습니다. 새로운 개념은 Service Network 하나입니다.
VPC를 Service Network에 연결(association)하면 그 VPC 안의 워크로드가 등록된 서비스들을 DNS 이름으로 호출합니다. 중간 홉이 없다는 뜻은 아닙니다. 요청은 Lattice가 중간에서 받아 타겟으로 전달하며, 달라지는 것은 그 중간 계층을 저희가 만들고 관리하지 않아도 된다는 것입니다. VPC Peering도, Transit Gateway 라우팅도, 서비스마다 늘어나는 PrivateLink 엔드포인트도 필요 없습니다. 계정이 달라도 AWS Resource Access Manager(RAM) 공유로 같은 모델이 유지됩니다.
설계에서 중요한 것은 Lattice가 하지 않는 일입니다. VPC Lattice는 퍼블릭 인터넷 진입점을 제공하지 않습니다. VPC를 Service Network에 직접 연결(association)하는 방식에서는 서비스 DNS가 link-local 대역(169.254.171.x) 주소로 해석되어 클라이언트는 연결된 VPC 안의 워크로드가 되고, Service Network 타입 VPC Endpoint를 두면 Peering·Transit Gateway·Direct Connect·VPN 너머의 다른 VPC나 온프레미스까지 넓어집니다. 어느 쪽이든 클라이언트는 사설 네트워크 안의 워크로드지, 인터넷의 사용자는 아닙니다. 그렇다면 관리형 진입점을 앞에 세울 수는 있을까요. 테스트 계정에서 직접 검증했습니다.
시도 1. ELB Target Group을 target-type=lattice로 생성 → ValidationError: enum value set: [lambda, ip, instance, alb] # lattice 타입이 없음 시도 2. ALB 리스너의 forward 대상에 Lattice Service ARN 지정 → 'Lattice service ARN' is not a valid target group ARN 시도 3. CloudFront VPC Origin에 Lattice Service ARN 지정 → InvalidArgument: Arn Invalid Format # 대조군 ALB ARN은 통과
세 가지 시도가 모두 같은 답을 돌려줬습니다. ALB의 전달 대상으로도, CloudFront VPC Origin으로도 Lattice 서비스를 직접 지정할 수는 없습니다(반대로 Lattice의 Target Group이 ALB를 타겟으로 받는 것은 가능합니다). Lattice는 인터넷을 마주 보는 진입점이 아니라, 사설 네트워크 안에서 서비스와 서비스를 잇는 계층입니다. 그래서 이 계층에는 East-West 연결을 맡기고, 인터넷에서 오는 트래픽을 받아줄 진입 계층은 따로 세우기로 했습니다. 그 자리의 후보를 순서대로 검토했습니다.
후보 | 판정 | 이유 |
ALB 증설 | 기각 | 이미 운영 중인 2단 ALB 체인에서 확인 — 규칙 증가 구조 동일, ALB → ALB 연결 불가 |
Network Load Balancer(NLB) 단독 | 기각 | L4라서 host/path 기반 분기 불가 |
Lattice를 진입점으로 | 기각 | 위 실측대로 불가. 중간 proxy를 두면 그 proxy가 새 운영 컴포넌트가 됨 |
Lattice를 전체 라우터로 | 기각 | 약 8만 개의 고객 도메인을 규칙으로 넣으면 ALB에서 겪은 규칙 증식이 재현됨
|
표에서 보듯 한 서비스로 전 구간을 잇는 답은 없었습니다. 그래서 구간을 나눠 각자 잘하는 것 하나씩만 맡겼습니다. 계정 경계는 NLB로 넘고(L4), L7 라우팅은 Kong 한 곳에 모으고, 게이트웨이에서 앱까지는 Lattice로 연결합니다.
NLB는 골랐다기보다 남았습니다. ALB 뒤에 ALB를 이어 붙일 수는 없습니다. ALB의 Target Group이 instance/ip/lambda 타입만 받기 때문입니다. IP 타입으로 붙이는 우회도 생각할 수 있지만 ALB의 IP는 수시로 바뀌어 오래가지 못합니다. 결국 고정 IP를 가진 NLB만 ALB 뒤에 설 수 있었습니다(Target Group의 alb 타입은 반대로 NLB가 ALB를 타겟으로 받을 때만 쓰는 예외입니다).
L7 게이트웨이 자리에는 후보가 셋 있었습니다. AWS Load Balancer Controller는 가장 익숙한 선택지지만, ALB 규칙 한도가 그대로 따라와 출발점의 문제로 되돌아갑니다. Istio는 라우팅 하나가 필요한 자리에 서비스 메시 전체를 들여놓는 셈이라 목적에 비해 무거웠습니다. 남은 Kong Ingress Controller는 db-less 모드에서 설정이 Git 선언만으로 반영되어, 라우팅을 GitOps로 움직이겠다는 요구사항과 맞아떨어졌습니다.
전체 구조

구조는 두 축으로 나뉩니다. 외부에서 들어오는 North-South, 서비스 사이를 잇는 East-West입니다. 각 계층의 책임은 하나씩입니다. ALB는 신규/레거시 경로 분기만, NLB는 경계 통과만 담당하고, 외부 라우팅의 복잡도는 Kong에 모입니다. Kong은 워크로드 클러스터가 아니라 인프라팀이 관리하는 중앙 게이트웨이 계정에 배치해, 클러스터가 늘어나도 라우팅 정책의 소유권이 한 곳에 유지되도록 했습니다.
선언 하나가 사슬이 되기까지
Kong의 Gateway API HTTPRoute.backendRef는 Kubernetes Service만 가리킬 수 있습니다. 그래서 Lattice 도메인을 가리키는 ExternalName Service를 다리로 둡니다. 이 값 하나가 앱의 목적지이므로, 뒤에서 다룰 서비스 통합 이후 앱의 그룹 간 이관과 롤백은 이 값을 바꾸는 작업이 됩니다.
다만 Host 헤더는 그대로 넘길 수 없습니다. Lattice가 Host로 서비스를 식별하기 때문에, 고객 도메인이 담긴 원본 Host가 들어오면 라우팅이 실패합니다. URLRewrite 필터로 upstream Host를 Lattice 도메인으로 바꾸고, 원본은 X-Forwarded-Host에 실어 앱까지 보냅니다.

이 전체 사슬은 GitOps 선언에서 파생됩니다. 앱 선언 1개를 넣으면 ArgoCD Application 두 개(EKS 워크로드, Kong 라우트)가 만들어집니다. AWS Gateway API Controller가 HTTPRoute를 읽어 공유 Lattice Service의 규칙과 Target Group을 생성합니다(신규 그룹이면 Service까지). 그다음 external-dns가 Amazon Route 53 Private Hosted Zone에 DNS 레코드를 만듭니다. Lattice 리소스를 콘솔에서 수동으로 만드는 일은 없습니다.
이관은 기존 ECS 경로를 유지한 채 ALB 규칙 우선순위로 앱 하나씩 전환하고, 문제가 보이면 규칙만 되돌립니다.
도입에서 마주한 문제 ① Service 79개를 14개로, 고정비 82% 절감
새 경로로 앱 69개를 이관한 다음 날, 이관 초기라 트래픽이 거의 없었는데도 Lattice 일 비용이 $3.57에서 $53.35로 증가했습니다.
원인은 과금 구조에 있습니다. Lattice의 고정비는 트래픽이 아니라 provision된 Service 개수 × 시간에 부과됩니다(서울 리전 기준 서비스당 시간당 $0.0325, 월 약 $23.7. 이 글의 금액은 모두 정가 기준입니다). 당시 저희는 "앱 1개 = Lattice Service 1개" 구조였습니다. 앱을 옮길수록 Service가 함께 늘어 79개 시점에 월 고정비가 약 $1,874가 되었고, 남은 앱까지 모두 옮기면 연 약 $53,000 규모가 됩니다. 서비스 간 연결을 Lattice로 모은다는 방향과, 연결할수록 고정비가 정비례로 증가하는 구조는 양립하기 어려웠습니다.
해결의 실마리도 과금 단위에 있습니다. Service 단위 과금이고 규칙은 과금 항목이 아닙니다. Service 1개에 규칙 N개를 담아 앱 N개가 공유하면 고정비는 N분의 1이 됩니다. 실제로 Lattice Service 79개를 14개로 통합해 월 고정비를 $1,874에서 $332로 82% 절감했고, 같은 비율이면 전체 이관 시에도 연 $10,000 미만으로 유지됩니다. 8개가 아니라 14개인 이유는 Gateway API 스펙상 HTTPRoute의 hostname이 route 전체에 적용되기 때문입니다. 자기 도메인(host)으로 서빙되는 앱은 통합할 수 없어 전용 Service로 남습니다(공유 그룹 8 + host 전용 6).
통합하면 무료 요청 한도(서비스당 시간당 30만 건)는 그룹당 하나로 줄어듭니다. 다만 앱당 트래픽이 낮은 현재 워크로드에서는 요청 요금 증가보다 고정비 절감이 큽니다. 앱은 많고 앱당 트래픽은 적은 워크로드라면 서비스 통합이 유리합니다. 그런데 "규칙으로 뭉친다"가 선언 한 줄로 끝나지는 않았습니다.
통합을 가로막은 컨트롤러 제약
EKS 환경에서 VPC Lattice를 위해 AWS Gateway API Controller를 사용할 때, HTTPRoute 1개가 Lattice Service 1개에 1:1로만 매핑되는 제약이 있습니다. 여러 HTTPRoute를 하나의 Service로 묶어달라는 요청이 이슈 #644로 등록되어 있으나 아직 해결되지 않았습니다. 이는 Lattice 자체의 한계가 아니라 컨트롤러 구현체의 한계입니다.
결과적으로 여러 애플리케이션이 하나의 Lattice Service를 공유하려면, 단일 HTTPRoute 안에 모든 앱의 라우팅 규칙을 몰아넣어야 합니다. 각 앱이 개별적으로 HTTPRoute를 관리하던 기존의 GitOps 구조를 전면 개편해야 하는 상황이었으며, 세 가지 방식으로 대응했습니다.
- 공유 HTTPRoute의 소유자를 플랫폼 전용 Application으로 일원화하고 앱 배정을 자동화했습니다. 빈자리가 있는 가장 낮은 번호 그룹에 배정하고, 정원이 차면 다음 그룹을 자동 생성합니다.
- 규칙을 경로 길이 내림차순으로 강제 정렬합니다. Gateway API의 PathPrefix는 경로 세그먼트 단위 매칭이지만, Lattice의 prefix 매칭은 문자열 단위입니다. 이 차이 때문에 /shop 규칙이 앞에 있으면 /shopping 요청을 에러 없이 가로챕니다. 정렬을 Helm 차트 렌더링 단계에 고정해 구조적으로 차단했습니다.
- 규칙 한도 초과를 PR/CI 단계에서 검사합니다. 규칙 수 한도는 AWS 서비스 쿼터입니다. 한도 10에서 규칙 11개를 선언하자 컨트롤러 로그에
ServiceQuotaExceededException만 남고 배열 마지막 규칙이 생성되지 않았습니다. 그런데 HTTPRoute status와 ArgoCD는 정상으로 표시됐습니다. 런타임에서 탐지하기 어려운 이유입니다.

통합 전에 두 가지를 실측했습니다. 그룹 route에 규칙을 추가해도 기존 앱에 순단이 없었고(160샘플 전부 200), 앱의 개별 → 그룹 전환과 롤백도 무중단이었습니다(반영 1~2초, 248샘플 전부 200). 재배치가 무중단이므로 초기 배정이 완벽할 필요도 없습니다. 그룹 조정은 PR 하나로 끝납니다.
통합 후에는 처리량 한도도 그룹이 나눠 쓴다
비용 다음으로 그룹이 나눠 쓰게 되는 것은 처리량입니다. 한도 문서에 기재된 서비스당 AZ당 10,000 RPS가 통합 후에는 그룹 공유 예산이 됩니다. 그래서 트래픽이 몰리는 이벤트성 앱은 같은 그룹에 두지 않고, 그룹 합산 RPS를 모니터링 항목에 두었습니다. 한도에 접근하는 그룹은 분리하면 됩니다.
주의할 점이 두 가지 더 있습니다. 그룹 route와 Kong 라우트를 서로 다른 ArgoCD Application이 소유하므로, 한 PR에 넣으면 두 Application의 반영 순서를 보장할 수 없어 순간 404가 발생할 수 있습니다. 그래서 PR을 분리합니다. 그리고 공유 Lattice Service에서는 Service 단위 지표가 어느 앱의 것인지 가리키지 못하므로, 앱 단위 모니터링은 Target Group 차원으로 함께 이관해야 합니다.

도입에서 마주한 문제 ② 배포 순간의 5xx를 고객이 보지 않게
첫 이관 대상은 고객 화면을 직접 그리는 프론트엔드였습니다. 배포 순간의 5xx는 API 재시도 뒤로 숨지 않고 고객 화면에 그대로 노출됩니다. 배포 중 요청을 한 건도 잃지 않는 것이 이관의 조건이었습니다.
하지만 배포 순간에 트래픽을 받을 수 없는 Pod가 잠깐 생기는 문제가 있습니다. Kubernetes의 Pod Ready와 로드밸런서 편입 완료는 서로 다른 사건입니다. Pod가 Ready가 되어야 컨트롤러가 타겟을 등록하고, 등록 후에야 헬스체크가 시작되므로, 네트워크 편입은 항상 Ready보다 늦습니다.

이 시간차 동안에는 헬스체크가 끝나지 않은 타겟에 트래픽이 갈 수 있습니다. ALB 환경에서 이 문제의 표준 해법은 Pod Readiness Gate입니다. 게이트는 Pod의 Ready 조건 목록에 "로드밸런서 헬스체크 통과"를 하나 더 추가하는 장치입니다. readiness probe만 통과하면 Ready였던 Pod가, 게이트가 있으면 로드밸런서 편입까지 끝나야 Ready가 됩니다. 트래픽을 받을 수 없는 Pod로 롤아웃이 이어지지 못하게 막습니다.
Lattice용 게이트도 컨트롤러가 제공하지만, 저희 구조에서는 게이트가 붙지 않았습니다. 저희는 Argo Rollouts로 카나리 배포를 하고 있었습니다. 기본 구성대로 stable과 canary 두 개의 Kubernetes Service를 두고, 각각에 Lattice Target Group을 하나씩 붙여 두 Target Group의 weight로 트래픽 비율을 조정하는 구조였습니다.
게이트 조건은 컨트롤러가 Pod 생성 순간에 한 번만 추가합니다. 이때 기준은 그 Pod를 담당하는 (selector로 가리키는) Service가 Lattice에 연결되어 있는가입니다. 이 기준은 공식 문서에 없는 동작이라 컨트롤러 소스로 확인했으며, 최신 버전까지 동일하게 유지되고 있습니다.
그런데 카나리 배포에서 canary Service의 selector는 새 버전 Pod가 만들어진 뒤에야 새 버전으로 옮겨갑니다. 새 Pod가 생성되는 순간에는 canary Service가 아직 이전 버전을 가리키고 있으므로, 컨트롤러에게는 담당 Service가 없는 Pod로 보입니다. 그래서 조건 추가가 누락됩니다. 강제로 주입하면 Pod는 Lattice를, Lattice는 Kubernetes Service의 변경을, Argo는 Pod의 준비를 기다리는 교착이 생깁니다.
이는 AWS나 VPC Lattice의 제약이 아닙니다. Lattice와 Argo Rollouts 카나리를 함께 쓰는 조합을 Argo Rollouts의 Gateway API 플러그인이 아직 지원하지 않아 생기는 문제이고, 지원 코드는 반영되는 중입니다. 이 글의 이야기는 그 지원이 들어오기 전 버전 조합에 한정됩니다.

그래서 ①의 Lattice 리소스는 적을수록 좋다는 원칙을 카나리에도 적용해 Kubernetes Service 하나와 Lattice Target Group 하나로 재설계하고, Service 안의 Pod 비율로 트래픽을 나눴습니다. Service가 하나가 되자 배포 중에 selector를 갈아탈 일이 없어져, Deployment와 Rollout 모두에 게이트가 붙었습니다. 이제 Pod는 Lattice 타겟 등록과 헬스체크 통과까지 끝나야 Ready가 됩니다. weight 기반의 정밀한 비율 조정을 Pod 수 기반 분배로 바꾼 트레이드오프는 남았습니다.
게이트가 유일한 방어선은 아닙니다. 창 자체를 좁히고, 창이 열려 있는 동안 요청이 왜 살아남는지도 실측으로 확인해 두었습니다. 헬스체크 interval을 30초에서 10초로 조정하면서 퇴출 민감도는 기본 수준으로 유지했습니다. 검증 환경에서 6.6~20 RPS의 연속 요청을 흘리며 배포 4회를 관찰한 결과, 1.5~3.5초의 편입 창에서 요청 35,700건 모두 정상 응답했습니다.
이유는 세 가지입니다. Lattice의 fail-open 동작 (타겟이 전부 unhealthy일 때에 한해 전체 타겟에 분배하는 동작입니다), DRAINING으로 남는 구 Pod와 preStop 유예, 실제 서빙 경로를 검사하는 readiness probe. 이 중 마지막이 최후의 안전망입니다. probe가 실제 서빙 가능 여부를 반영하지 않는 앱에게는 게이트도 fail-open도 안전망이 되지 못합니다.
맺음말
결과부터 요약하면 이관은 전 과정 무중단이었고, 배포 편입 창에서의 요청 유실은 실측 0건(35,700건 모두 정상 응답)이었습니다. Lattice 고정비는 82% 절감된 구조로 유지되고 있습니다.
이번 이관은 새 관리형 서비스를 하나 도입하는 일이라기보다, 문서에 적힌 동작과 실제 동작 사이의 간극을 실측으로 메워가는 과정이었습니다.
- 관리형 서비스의 과금 단위는 아키텍처 결정사항입니다. "앱 1개 = Lattice Service 1개" 구조는 연 $53,000 규모의 고정비 구조였고, 과금 단위(서비스 × 시간)를 기준으로 설계를 바꾸자 같은 기능이 82% 낮은 비용으로 유지되었습니다.
- 제약을 만나면 출처부터 구분해야 합니다. 서비스의 공식 한도인지, 컨트롤러 구현의 지원 범위인지, 자사 구조가 만든 운영 규칙인지에 따라 대응이 달랐습니다. 그중 Lattice가 지원하는 것과 Gateway API Controller가 지원하는 것 사이의 간극이 가장 많은 공수를 만들었고, GitOps 소유권 구조의 재설계로 이어졌습니다.
- Synced, Ready, HEALTHY는 각각 다른 시점을 가리킵니다. 이 시간차는 어느 로드밸런서에서든 존재합니다. 게이트가 붙지 않는다면 그 원인이 된 구조 자체를 바꾸는 것도 선택지입니다. 어느 쪽이든, 그 시간차 동안 요청이 살아남는 이유는 실측으로 확인해야 합니다.
세 가지 모두 Lattice에 한정된 이야기는 아닙니다. 관리형 서비스 위에 아키텍처를 세울 때마다 되풀이될 질문이라 생각하며, 비슷한 확장 한계를 만난 팀에 이 기록이 참고가 되기를 바랍니다.
참고 자료
이승민A SRE Engineer
손이 떨리는 겁쟁이 SRE입니다. 끝없는 자동화를 추구합니다.

