CLD 4 단일 App 서버의 한계와 개선 - 100-hours-a-week/KTB4-13th-wiki GitHub Wiki
🚧 작성중 · 담당 미정 · 수정 2026-09-21 · 상위 컨테이너 확장 설계 · 원본 2.1.-단일-App-서버의-한계와-개선
요약 단일 App 서버의 한계와 Scale-Out, Multi-AZ 및 Auto Scaling 전략을 정리한다.
2. 기존 인프라 구조의 한계와 개선
2.1. 단일 App 서버
1. 문제 정의
V1은 하나의 t3.small App EC2에서 Nginx, Backend와 MySQL을 함께 실행한다.
App EC2
├─ Nginx
├─ Backend
└─ MySQL
V2의 7년 차 목표는 누적 가입자 250만 명, MAU 100만 명, 평균 DAU 10만 명이다. 평상시 Peak Traffic은 0.18 RPS에서 625 RPS로 증가한다. 현재 구조에는 다음과 같은 한계가 있다.
- EC2 장애 시 Backend와 MySQL이 함께 중단된다.
- Recreate 배포 중에는 요청을 처리할 Backend가 없다.
- 트래픽이 증가해도 요청을 나눠 처리할 App 서버가 없다.
- Backend와 MySQL이 자원을 공유해 각각 확장하기 어렵다.
- 서버 수가 고정되어 있어 트래픽 변화에 대응하기 어렵다.
정적 화면은 CloudFront와 S3에서 계속 제공할 수 있지만, App EC2가 중단되면 로그인·검색·리뷰·장바구니·주문·결제 등의 API는 사용할 수 없다.
현재 App EC2는 전체 API의 단일 장애 지점(SPOF)이며, Backend와 MySQL이 결합되어 있어 확장에도 한계가 있다.
2. Scale-Up과 Scale-Out 비교
| 기준 | Scale-Up | Scale-Out |
|---|---|---|
| 확장 방법 | 기존 EC2의 사양을 높임 | 같은 역할의 App EC2를 추가함 |
| 트래픽 증가 | 한 서버의 사양으로 대응 | 서버를 추가해 전체 처리량을 늘림 |
| 확장 범위 | 단일 인스턴스의 최대 사양에 제한됨 | 서버 수를 늘려 단계적으로 확장 가능 |
| 장애 영향 | 한 대만 운영하면 전체 Backend 중단 | 다른 서버가 요청을 이어서 처리 가능 |
| 배포 | 대체 서버가 없으면 배포 중 중단 | 일부 서버를 유지하며 순차 배포 가능 |
| 확장·축소 | 사양 변경 작업이 필요함 | 서버 수를 기준으로 조절 가능 |
| 비용 | 큰 사양을 실행하는 동안 같은 비용 발생 | 추가 서버와 로드밸런서 비용 발생 |
| 운영 | 비교적 단순함 | 요청 분산과 여러 서버 관리가 필요함 |
2.1. Scale-Up만으로 부족한 이유
Scale-Up은 기존 EC2의 CPU와 메모리를 늘리는 가장 단순한 확장 방법이다. 현재 서버의 자원만 부족하다면 구조를 크게 바꾸지 않고 처리량을 높일 수 있다.
하지만 App 서버가 한 대인 상태에서는 다음 문제가 남는다.
- EC2 장애 시 전체 Backend가 중단된다.
- 배포 중 요청을 처리할 대체 서버가 없다.
- 확장 범위가 단일 인스턴스의 최대 사양에 제한된다.
- Peak Traffic에 맞춘 사양을 트래픽이 적은 시간에도 유지해야 한다.
북적북적은 로그인과 검색뿐 아니라 장바구니·주문·결제를 제공한다.
App 서버가 중단되면 주문을 진행하거나 결제 결과를 확인할 수 없다. 서비스 규모가 커질수록 같은 시간의 중단도 더 많은 주문 실패와 매출 손실로 이어질 수 있다.
따라서 V2에서는 비용 효율성보다 가용성·복구성을 우선한다. 서버 한 대의 처리량만 높이고 단일 장애 지점을 남기는 Scale-Up만으로는 이 요구사항을 충족하기 어렵다고 판단했다.
EC2 장애가 자주 발생한다고 가정하는 것은 아니다. 다만 현재 구조에서는 한 번의 장애만으로 로그인·검색·주문·결제 API가 모두 중단된다. 커머스 서비스에서 이 영향 범위가 큰 것이 문제이다.
2.2. Scale-Out이 필요한 이유
Scale-Out은 같은 역할의 App 서버를 여러 대 실행하고 요청을 나눠 처리하는 방식이다.
북적북적은 사용자가 도서를 검색하고 리뷰를 비교한 뒤 장바구니와 결제로 이동하는 흐름을 가진다. 이 과정에서 서버가 중단되면 탐색이 끊기고 구매 포기로 이어질 수 있으므로, 일부 App 서버에 문제가 생겨도 사용자 흐름이 이어져야 한다.
- 한 App 서버가 중단돼도 다른 서버가 요청을 처리할 수 있다.
- 일부 서버를 유지한 상태에서 나머지 서버를 순차적으로 배포할 수 있다.
- 트래픽이 증가하면 서버를 추가해 전체 처리량을 높일 수 있다.
- 트래픽이 감소하면 불필요한 서버를 줄일 수 있다.
- 한 서버의 최대 사양에 의존하지 않고 서비스 성장에 맞춰 확장할 수 있다.
여러 서버를 사용하려면 요청을 정상 서버로 분산하고, 비정상 서버를 요청 대상에서 제외해야 한다.
3. Single-AZ와 Multi-AZ 비교
Scale-Out을 적용한 뒤에는 여러 App EC2를 같은 AZ에 둘지, 서로 다른 AZ에 나눌지 결정해야 한다.
V2의 가용성 목표는 하나의 EC2 또는 AZ가 중단돼도 App 서비스를 계속 제공하는 것이다.
| 기준 | Single-AZ | Multi-AZ |
|---|---|---|
| 서버 배치 | App EC2 2대를 같은 AZ에 배치 | App EC2 2대를 서로 다른 AZ에 배치 |
| 개별 EC2 장애 | 남은 EC2에서 요청 처리 | 남은 EC2에서 요청 처리 |
| AZ 단위 장애 | App EC2 전체가 영향을 받음 | 정상 AZ의 EC2에서 요청 처리 |
| EC2·EBS 기본 비용 | EC2 2대 비용 | 같은 사양의 EC2 2대이므로 동일 |
| 추가 부담 | 구성이 단순함 | AZ별 Subnet 구성 필요 |
Single-AZ에 App EC2를 두 대 배치하면 개별 EC2 장애와 순차 배포에는 대응할 수 있다. 하지만 두 서버가 같은 장애 범위에 있어 해당 AZ에 문제가 생기면 App 계층 전체가 중단된다.
Multi-AZ는 가용성을 위해 유지할 EC2 두 대를 서로 다른 AZ에 배치하는 방식이다. 따라서 App EC2와 EBS의 기본 실행 비용은 Single-AZ와 같다.
북적북적의 사용자 흐름은 한 번의 요청으로 끝나지 않는다. 사용자는 로그인 후 검색이나 AI 추천을 이용하고, 여러 도서의 상세와 리뷰를 비교한 뒤 장바구니·주문·결제로 이동한다. 대표 흐름에는 세션당 약 816회의 백엔드 요청이 발생하며, 일반 탐색과 구매 과정은 약 2030분 동안 이어진다.
모든 App EC2가 같은 AZ에 있으면 이 과정에서 AZ 장애가 발생했을 때 로그인·검색·리뷰·장바구니·주문·결제 API가 함께 중단된다. 사용자는 진행 중이던 탐색과 구매를 이어갈 수 없으며, 장애가 복구되더라도 검색 조건이나 장바구니·결제 상태를 다시 확인해야 할 수 있다.
Multi-AZ는 하나의 AZ 장애가 App 계층 전체와 사용자 흐름의 중단으로 이어지는 것을 막는다. App EC2를 서로 다른 AZ에 배치하면 한 AZ가 중단돼도 정상 AZ에서 도서 탐색과 주문·결제 API를 계속 제공할 수 있다.
북적북적은 도서 구매 제휴수수료로 매출을 얻으므로 App 계층의 장애는 단순한 접속 오류가 아니라 구매 기회의 손실로 이어진다. 7년 차 목표 매출을 월 1억 5천만 원으로 계산하면 분당 기대 매출은 다음과 같다.
분당 기대 매출
= 150,000,000원 ÷ (30일 × 24시간 × 60분)
= 약 3,472원/분
AZ 장애로 주문·결제 API가 중단된 시간이 T분이면 직접 매출 기회 손실의 단순 추정값은 다음과 같다.
직접 매출 기회 손실
= 3,472원 × T분
실제 손실은 사용자가 장애 후 다시 구매하지 않는 비율, 결제 재시도 실패, 고객 문의와 신뢰 하락까지 포함하므로 이 계산보다 커질 수 있다. 따라서 Multi-AZ는 EC2 비용을 늘리지 않고도 한 AZ 장애 시 구매 흐름을 계속 제공해 장애 범위와 매출 손실을 줄이는 선택이다.
3.1. 두 개 AZ를 선택한 이유
AZ 장애는 빈번하게 발생하는 장애는 아니다. Multi-AZ를 구성하는 목적은 모든 장애 상황에서 동일한 처리 용량을 유지하는 것이 아니라, 하나의 AZ가 App 계층 전체의 단일 장애 지점이 되는 것을 막는 데 있다.
두 개 AZ에 App EC2를 한 대씩 배치하면 한 AZ가 중단돼도 다른 AZ에서 도서 탐색과 주문·결제 API를 계속 제공할 수 있다. 남은 서버는 평상시 Peak 625 RPS를 처리할 수 있어야 한다.
세 개 AZ를 사용하면 장애 이후에도 두 대의 서버가 남아 처리 여유와 이중화를 유지할 수 있지만, 이를 위해 평상시 App 서버 한 대의 비용을 추가로 부담해야 한다.
현재 서비스의 목표는 장애 시 구매 흐름을 완전히 중단하지 않는 것이므로, 세 번째 서버를 상시 유지하지 않고 두 AZ를 기본 구성으로 사용한다.
4. Multi-AZ에서 App을 고정 운영하는 경우
가용성을 확보하는 가장 단순한 방법은 두 AZ에 App EC2를 한 대씩 두는 것이다. 한 EC2나 AZ에 문제가 생기면 다른 AZ의 서버가 요청을 처리할 수 있다.
하지만 두 대를 고정하는 것만으로 트래픽 변화까지 대응할 수 있는 것은 아니다.
- 한 서버가 중단되면 남은 서버 한 대가 전체 요청을 처리해야 한다.
- 서버 장애와 Peak Traffic이 겹치면 처리 용량이 부족할 수 있다.
- 두 서버의 처리량을 넘는 요청이 들어오면 직접 서버를 추가해야 한다.
- 장애 서버를 대신할 EC2도 직접 생성하고 설정해야 한다.
장애 상황에도 Peak Traffic을 처리하도록 Scale-Up으로 보완하려면 두 EC2 모두 전체 Peak를 감당할 수 있는 사양으로 높여야 한다.
그러나 북적북적은 점심 12:00~13:00과 저녁 18:00~23:00에 트래픽이 집중될 것으로 예상하므로, 큰 EC2를 계속 실행하면 나머지 시간에는 사용하지 않는 자원이 남는다.
EC2는 CPU 사용률이 아니라 실행 시간과 인스턴스 사양을 기준으로 과금된다.
반대로 작은 EC2 두 대만 유지하면 집중 시간이나 장애 상황에서 처리 용량이 부족할 수 있다. 따라서 평상시에는 가용성에 필요한 최소 서버를 유지하고, 트래픽이 증가하거나 서버가 중단되면 필요한 만큼 서버를 추가할 방법이 필요하다.
이를 위해 부하에 따라 App 실행 수를 자동으로 늘리거나 줄이는 Auto Scaling을 고려한다.
5. App 실행 및 확장 방식 비교
Auto Scaling을 구성하는 방법은 무엇을 늘릴 것인지에 따라 나뉜다.
비교할 방식은 ASG + EC2, ECS on EC2, ECS Fargate이다.
| 방식 | 늘리는 단위 | 서버 관리 | 특징 |
|---|---|---|---|
| ASG + EC2 | EC2 | 팀이 관리 | 서버와 Backend 실행 수가 함께 증가 |
| ECS on EC2 | 컨테이너와 EC2 | 팀이 관리 | ECS가 컨테이너를 관리하고 ASG가 EC2를 관리 |
| ECS Fargate | 컨테이너 | AWS가 관리 | EC2를 직접 운영하지 않고 컨테이너만 관리 |
ASG + EC2는 Backend가 실행된 서버를 한 대씩 추가하는 방식이다. ECS on EC2는 Backend 컨테이너와 이를 실행할 EC2 용량을 각각 관리한다. ECS Fargate는 Backend 컨테이너만 관리하고 기반 서버 운영은 AWS에 맡긴다.
5.1. ASG + EC2
ASG + EC2는 EC2를 확장 단위로 사용하는 방식이다. 각 EC2에서 Backend 컨테이너를 실행하고, ASG가 필요한 EC2 수를 유지한다.
V1에서는 서버가 부족하거나 중단되면 운영자가 EC2를 생성하고 Backend를 다시 실행해야 한다. ASG를 사용하면 정해진 범위 안에서 EC2 수를 조절하고, 비정상 EC2를 같은 설정의 새 EC2로 교체할 수 있다. 따라서 두 AZ에 필요한 서버 수를 유지하면서 트래픽 증가와 서버 장애에 대응할 수 있다.
EC2 단위의 확장과 장애 교체를 자동화하면서, Backend 컨테이너 실행은 별도의 운영 설정으로 통제할 수 있다는 점이 장점이다.
반면 ASG가 직접 관리하는 대상은 EC2이다. Backend 컨테이너의 실행과 재시작, 로그 수집, 상태 확인과 배포 절차는 팀이 구성해야 한다. 운영체제와 Docker의 보안 패치도 직접 관리해야 하므로 서버 운영 부담은 남는다.
새 EC2가 요청을 처리하려면 인스턴스 생성, OS 부팅, Backend 실행과 상태 확인을 거쳐야 하므로 확장에 시간이 걸린다. 새 서버가 준비될 때까지는 기존 서버가 요청을 처리해야 하며, 가용성을 위해 유지하는 최소 EC2 비용도 계속 발생한다.
5.2. ECS on EC2
ECS on EC2는 EC2 위에서 컨테이너를 실행하되, 컨테이너의 배치와 상태를 ECS가 관리하는 방식이다. ECS에서 컨테이너 실행 단위를 Task라고 하며, ECS Service는 필요한 Task 수를 유지하고 비정상 Task를 새 Task로 교체한다.
Capacity Provider는 ECS의 Task 수요와 ASG의 EC2 용량을 연결한다. 관리형 확장을 사용하면 새 Task를 배치할 공간이 부족할 때 ASG에 EC2 확장을 요청한다.
Backend 컨테이너 수 증가
→ ECS가 실행 공간 확인
→ 공간이 부족하면 ASG가 EC2 추가
→ 새 EC2에 Backend 컨테이너 배치
ECS on EC2를 사용하면 종료된 Backend Task를 자동으로 교체하고, 같은 설정으로 여러 EC2에 배치할 수 있다. 새 버전도 Task 단위로 순차 배포할 수 있어 컨테이너의 배포와 상태 관리를 자동화하기 좋다.
반면 ECS는 Task 수를, ASG는 EC2 수를 관리하므로 두 계층의 용량과 확장 상태를 함께 확인해야 한다. ECS Cluster, Service와 Capacity Provider 설정이 추가되지만 EC2와 운영체제 관리도 그대로 남는다.
북적북적의 App 계층에는 Backend 한 종류만 실행되지만, 같은 Backend Task를 여러 개 실행해 EC2의 남는 CPU와 메모리에 배치할 수 있다. 따라서 반드시 Task 하나가 늘 때마다 EC2도 한 대씩 추가되는 것은 아니다. 기존 EC2에 여유가 있으면 그 안에 Task를 먼저 배치하고, 공간이 부족할 때 EC2를 추가할 수 있다.
다만 ECS on EC2도 EC2 기동 지연이 완전히 사라지는 것은 아니다.
- 기존 EC2에 Task를 배치할 여유가 있으면 새 Task만 실행하므로 비교적 빠르게 확장할 수 있다.
- 여유 용량이 없으면 ASG가 새 EC2를 생성하고, OS 부팅과 ECS 등록이 끝난 뒤 Task를 배치해야 한다.
- 이 경우 새 EC2가 준비될 때까지 Task는 대기하므로
ASG + EC2와 같은 기동 지연이 발생한다.
ECS를 사용하면 Task 교체와 배포는 편해지지만, ECS의 Task 수와 ASG의 EC2 용량을 함께 관리해야 한다. 또한 EC2와 운영체제의 패치 및 용량 관리도 그대로 남는다.
5.3. ECS Fargate
Fargate는 EC2를 직접 운영하지 않고 Backend 컨테이너를 Task 단위로 실행하는 방식이다. 팀은 컨테이너 이미지와 CPU·메모리, 실행 수를 정하고 기반 서버와 OS는 AWS가 관리한다.
ECS on EC2처럼 Task를 실행할 EC2 용량을 따로 관리하지 않아도 되므로 구조와 운영이 단순하다. 인프라 담당자가 개발을 병행하는 북적북적의 운영 부담도 줄일 수 있다.
대신 정해진 CPU·메모리 조합에서 사양을 선택해야 하고 기반 서버를 직접 제어할 수 없다. 새 Task도 이미지 다운로드와 상태 확인을 거쳐야 하므로 바로 요청을 처리할 수 있는 것은 아니다. 또한 Backend를 계속 실행하면 트래픽이 적어도 지정한 자원에 대한 비용이 발생한다.
5.4. 비용 비교
실행 단위 두 개를 30일 동안 유지하는 기존 계산값을 기준으로 비교한다.
- 한 달:
30일 × 24시간 = 720시간 - EC2 기반 방식:
t3.small2대와 gp3 30GB씩 사용 - Fargate: 1 vCPU·2GB Task 2개 사용
| 방식 | 계산 기준 | 한 달 비용 |
|---|---|---|
| ASG + EC2 | EC2 $37.44 + gp3 $5.47 |
$42.91 |
| ECS on EC2 | 동일한 EC2·EBS 사용 | $42.91 |
| ECS Fargate | 1 vCPU·2GB Task 2개 | $81.76 |
ASG + EC2와 ECS on EC2는 같은 EC2와 EBS를 사용하므로 기본 실행 비용이 같다. ECS on EC2는 Task 관리 기능을 추가하지만 기반 EC2와 운영체제는 직접 관리한다.
Fargate는 EC2와 운영체제를 직접 관리하지 않아 운영 부담이 작지만, Backend Task 두 개를 계속 실행하는 기준에서는 월 비용이 EC2 기반 방식보다 높다. V2는 App을 상시 운영하므로 Fargate를 제외하고, ASG + EC2와 ECS on EC2를 운영 방식과 자동화 범위로 비교한다.
5.5. App 실행 방식 선택
ASG + EC2와 ECS on EC2는 모두 EC2에서 Backend를 실행하지만, 컨테이너를 관리하는 단위가 다르다.
| 기준 | ASG + EC2 | ECS on EC2 |
|---|---|---|
| 관리 단위 | EC2와 Docker 컨테이너 | ECS Task와 EC2 |
| 확장 | ASG가 EC2 수 조절 | ECS Service가 Task 수 조절, ASG가 EC2 용량 조절 |
| 장애 복구 | EC2 교체, 컨테이너 복구는 별도 구성 | Task와 EC2를 각각 교체 |
| 배포 | 스크립트·AMI·Instance Refresh 구성 | Task 단위 Rolling 배포 |
| 기본 비용 | EC2·EBS 비용 | 같은 EC2·EBS 사용 시 동일 |
ASG + EC2도 Docker 재시작 정책과 배포 스크립트를 추가하면 운영할 수 있다. 그러나 EC2 상태, 컨테이너 상태, 배포 버전을 서로 다른 방식으로 관리해야 하므로 서버 수가 늘어날수록 운영 절차가 복잡해진다.
북적북적은 검색·추천에서 도서 상세·리뷰, 장바구니·주문·결제로 이어지는 흐름을 제공한다. 배포나 Backend 장애가 이 흐름을 끊지 않으려면 정상 Task를 유지하면서 비정상 Task만 교체하고, 새 버전이 Health Check를 통과한 뒤 요청을 받아야 한다.
ECS on EC2는 ECS Service가 Task 수 유지와 Rolling 배포를 담당하고, Capacity Provider와 ASG가 Task를 실행할 EC2 용량을 연결한다. 따라서 컨테이너 실행·교체·배포를 Task Definition과 Service 기준으로 표준화할 수 있다.
ECS가 EC2 운영을 없애는 것은 아니다. EC2의 AMI·OS 패치·용량과 ECS Cluster·Service·Task Definition·Capacity Provider를 계속 관리해야 한다. 그럼에도 주문·결제 흐름을 유지하면서 컨테이너 운영을 일관되게 관리하기 위해 ECS on EC2를 선택한다. 구체적인 Task·EC2 수량은 9장에서 산정한다.
6. App 사이징과 Auto Scaling 전략
6.1. Task 처리량 기준
북적북적의 7년 차 평상시 Peak는 625 RPS이며, 이벤트 설계 기준은 1,250 RPS이다.
App EC2는 t3.small을 기본 사양으로 사용한다. 개발팀이 보유한 클라우드 크레딧을 활용해 초기 운영비를 제한하면서, 2 vCPU·2GiB 환경에서 Java·Spring Boot Backend와 ECS Agent를 실행할 수 있기 때문이다. 2GiB는 여유가 큰 사양이 아니므로 한 EC2에 Backend Task 하나만 배치하고, 처리량은 Task 수를 늘려 확보한다.
사이징 기준은 Spring Boot·MySQL·JPA 애플리케이션을 2 vCPU·2GB 환경에서 실행한 공개 사례를 사용한다. 이 사례는 점진적으로 부하를 높인 시험에서 약 240 RPS, p95 6.69ms, 성공률 100%를 기록했다. Spring Boot·MySQL 2 vCPU·2GB 부하 테스트
이 수치는 북적북적의 직접 측정값이 아니다. 공개 사례의 API와 데이터 규모가 다르므로 240 RPS를 보장 처리량으로 사용하지 않고, Task 수를 계산하기 위한 상한 참고값으로 사용한다.
북적북적은 처리시간이 짧은 홈·상세 조회와 검색·리뷰·주문·결제를 같은 Backend에서 처리한다. 요청 처리시간의 편차가 크면 평균 처리량에 여유가 있어도 느린 요청이 쌓이면서 응답시간이 증가할 수 있다.
공개 벤치마크의 최대 처리량까지 사용하면 요청 대기와 응답시간이 증가할 수 있다. 북적북적은 조회·검색·리뷰·주문·결제가 섞여 요청별 처리시간의 편차가 있으므로, 측정값의 70%를 Task 운영 기준으로 적용해 여유 용량을 둔다. 70%는 벤치마크에서 직접 측정한 값이 아니라 서비스 요청 편차와 확장 준비시간을 고려한 설계 기준이다.
Task당 운영 기준
= 240 RPS × 70%
= 168 RPS
따라서 공개 사례의 측정 처리량 240 RPS를 최대 참고값으로 두고, 실제 사이징에는 Task당 168 RPS를 적용한다. 168 RPS는 벤치마크 측정값이 아니라 북적북적의 요청 편차와 지연 증가를 고려한 운영 기준이다.
t3.small에는 Backend Task를 하나만 배치한다. 2GiB 메모리에서 여러 JVM을 실행하면 각 Task의 Heap과 OS·ECS Agent가 사용할 메모리가 부족해질 수 있고, 한 EC2 장애가 여러 Task에 동시에 영향을 줄 수 있기 때문이다.
6.2. Task 수 산정
평상시 Peak 625 RPS에 필요한 Task 수는 4개이다.
ceil(625 RPS ÷ 168 RPS)
= 4개
625 RPS ÷ 4개
= Task당 약 156 RPS
이벤트 설계 기준 1,250 RPS에 필요한 Task 수는 8개이다.
ceil(1,250 RPS ÷ 168 RPS)
= 8개
1,250 RPS ÷ 8개
= Task당 약 156 RPS
| 구간 | 전체 트래픽 | Task 수 | Task당 트래픽 | AZ별 배치 |
|---|---|---|---|---|
| 평상시 Peak | 625 RPS | 4개 | 약 156 RPS | 2개 |
| 이벤트 | 1,250 RPS | 8개 | 약 156 RPS | 4개 |
트래픽이 두 배로 증가할 때 Task 수도 두 배로 늘려 Task당 부하를 같은 수준으로 유지한다.
6.3. 실행 수 설정
ECS Service는 다음과 같이 설정한다.
| 항목 | 설정값 | 근거 |
|---|---|---|
| Min Task | 4개 | 625 RPS 처리 및 AZ별 2개 유지 |
| Desired Task | 4개 | 평상시 운영 수량 |
| Max Task | 8개 | 1,250 RPS 처리 |
Capacity Provider와 연결된 ASG는 다음과 같이 설정한다.
| 항목 | 설정값 |
|---|---|
| Min EC2 | 4대 |
| Desired EC2 | 4대 |
| Max EC2 | 10대 |
Backend Task는 EC2당 하나씩 실행한다. 트래픽 처리에는 최대 8개가 필요하며, 시작 시간이 정해진 캠페인은 이벤트 전에 Desired Task를 8개로 조정해 확장 지연을 줄인다. ASG의 추가 2대는 최대 트래픽 상태에서 기존 Task를 유지한 채 새 버전의 Task를 실행하기 위한 배포 용량으로 사용한다.
6.4. Auto Scaling 지표
주 Scaling 지표는 ALB의 CloudWatch 지표인 RequestCountPerTarget을 사용한다. 이 지표는 일정한 집계 기간 동안 각 정상 Backend Target이 처리한 요청 수를 평균으로 나타낸다. 예를 들어 Target이 4개이고 1분 동안 전체 요청이 30,000회라면 Target당 요청 수는 평균 7,500회이다. ALB RequestCountPerTarget 지표
RequestCountPerTarget
= 전체 요청 수 ÷ 정상 Target 수
Target 수가 늘어나면 같은 전체 트래픽이라도 Target당 요청 수가 낮아진다. 따라서 전체 RPS보다 현재 각 Task가 실제로 부담하는 요청량을 기준으로 ECS Task 수를 조절할 수 있다.
북적북적은 요청마다 CPU 사용 패턴이 다르다. 검색 Query나 외부 AI API를 기다리는 동안에는 응답이 지연돼도 CPU가 높지 않을 수 있다. 요청 유입량을 직접 나타내는 Target당 요청 수가 App 확장 기준에 더 적합하다.
RequestCountPerTarget 목표값
= 168 RPS × 60초
= Target당 분당 10,080회
Target당 요청 수가 분당 10,080회에 접근하면 ECS Service가 Task를 추가한다. 이 값은 Task당 운영 기준 168 RPS를 ALB의 1분 집계 단위로 변환한 것이다.
평상시 625 RPS가 4개 Target에 분산되면 Target당 약 156 RPS, 분당 9,375회이다. 이벤트 1,250 RPS에서는 8개 Target으로 확장해 Target당 약 156 RPS, 분당 9,375회를 유지한다. 두 경우 모두 목표값인 분당 10,080회 이하이므로 Task당 부하를 같은 수준으로 유지할 수 있다.
CPU, 메모리, CPU Credit과 HikariCP 대기 수는 병목 판단에 사용한다. 요청 수가 낮은데도 해당 지표가 증가한다면 Task 부족보다 Query, 응답 크기, JVM 또는 DB Connection 문제를 먼저 확인한다.
7. 장애 발생 시 가용성 유지 전략
7.1. Backend Task 장애
북적북적의 한 세션은 로그인, 검색, 도서 상세·리뷰 조회, 장바구니와 주문·결제로 이어진다. 이 중간에 특정 Task가 중단되면 사용자는 검색 결과나 장바구니 화면에서 다음 단계로 이동하지 못할 수 있다. 따라서 장애 Task를 빠르게 요청 경로에서 제외하고, 다른 Task로 요청을 보내는 것이 필요하다.
ALB Health Check가 실패한 Task는 Target Group에서 제외한다. 정상 Task로만 요청을 전달하므로 장애 Task가 검색·리뷰·주문 요청을 계속 받지 않는다.
ECS Service는 원하는 Task 수를 유지하도록 새 Task를 실행한다. 새 Task가 Health Check를 통과한 뒤 요청 대상에 포함되므로 준비되지 않은 컨테이너가 트래픽을 받지 않는다.
이를 위해 세션과 업로드 파일을 Task 내부에 저장하지 않는다. 세션은 외부 저장소에 두고, 이미지는 S3에 저장해야 다른 Task로 요청이 전환돼도 사용자의 로그인 상태와 업로드 결과가 유지된다.
7.2. EC2 장애
EC2가 중단되면 해당 EC2에서 실행 중인 Backend Task도 함께 중단된다. 같은 EC2에 Backend와 다른 구성요소를 함께 배치한 V1에서는 이 장애가 로그인·검색·리뷰·주문·결제 전체의 중단으로 이어졌다. V2에서는 Task를 여러 EC2에 분산해 장애 범위를 한 실행 단위로 제한한다.
Capacity Provider는 부족해진 Task 배치 용량을 확인하고, ASG가 새 t3.small을 실행하도록 연결한다.
새 EC2가 ECS Cluster에 등록된 뒤 Backend Task를 배치하고, ALB Health Check를 통과한 시점부터 요청을 전달한다. 장애가 발생한 EC2를 복구하는 동안에도 다른 EC2의 Task가 요청을 처리한다.
7.3. AZ 장애
평상시에는 두 AZ에 Task를 2개씩 배치한다. 한 AZ가 중단되면 다른 AZ의 Task 2개가 요청을 계속 처리한다.
AZ 장애 직후 운영 기준 용량
= 2개 × 168 RPS
= 약 336 RPS
이는 평상시 Peak 625 RPS 전체를 유지하는 용량은 아니므로 일부 요청의 응답시간이 증가할 수 있다. 그러나 서비스 전체가 중단되는 대신 로그인·검색·도서 조회 같은 핵심 기능을 계속 제공할 수 있다. Capacity Provider와 ASG는 정상 AZ에 EC2와 Task를 추가해 처리 용량을 회복한다.
평상시부터 AZ별 4개, 총 8개를 실행하면 한 AZ가 중단돼도 다른 AZ에서 625 RPS를 처리할 수 있다. 하지만 평상시 필요 수량의 두 배를 상시 실행해야 하므로, 북적북적은 비용을 고려해 평상시 4개를 운영하고 장애 시 복구하는 구성을 선택한다.
7.4. 배포 중 가용성 유지
배포 중에는 기존 정상 Task를 유지한 상태에서 새 버전의 Task를 실행한다. 새 Task가 Health Check를 통과한 뒤 기존 Task를 종료하므로 Backend 전체가 동시에 중단되지 않는다. 검색·추천 사용자가 탐색을 계속하고, 장바구니와 결제 사용자가 배포 때문에 API 오류를 받지 않도록 하기 위한 설정이다.
주문·결제 요청이 진행 중인 동안 기존 Task를 즉시 종료하지 않도록 Connection Draining을 적용한다. 주문·결제 API는 네트워크 오류나 Task 교체 후 클라이언트가 재시도할 수 있으므로 멱등성 키를 사용해 같은 주문이 중복 생성되지 않도록 한다.
7.5. 장애 시 서비스 우선순위
처리 용량이 줄어든 상황에서는 주문·결제와 로그인 요청을 우선 처리한다. 결제는 매출과 직접 연결되고, 로그인이 막히면 기존 사용자의 모든 기능이 중단되기 때문이다. 검색·도서 상세와 리뷰 조회는 응답시간이 증가하더라도 계속 제공하고, AI 추천과 이미지 인식처럼 외부 처리시간이 긴 기능은 일시적으로 요청을 제한할 수 있다.
이를 통해 App Task나 EC2 장애가 발생하더라도 전체 기능을 동시에 중단하지 않고, 사용자의 구매 흐름과 핵심 계정 기능을 우선 유지한다. 장애가 장기화되면 제한된 기능과 복구 상태를 사용자에게 안내해 반복 요청이 장애를 더 키우지 않도록 한다.
✏️ 이 페이지는 레포 docs/cld/4-container-expansion/app-server.md에서 수정한다. 위키에서 직접 고치면 다음 반영 때 덮어써진다.