이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.
- Scale up과 scale out 중 무엇을 선택할지 어떤 지표로 판단하는가?
- App instance를 늘리면 오히려 DB나 외부 API 장애가 커지는 경우는 언제인가?
- 확장 선택은 성능, 장애 격리, 운영 복잡도 중 무엇을 바꾸는가?
개요
Scale up은 더 큰 장비로 한 노드의 한계를 올리는 선택이다. Scale out은 여러 노드로 부하를 나누는 선택이다. 둘 중 무엇이 좋은지는 기술 취향이 아니라 병목 위치가 결정한다. App CPU가 포화라면 app scale out이 직접 효과를 낼 수 있다. DB write lock이나 외부 API quota가 병목이라면 app을 늘리는 순간 더 많은 요청이 병목으로 몰린다.
이 문서가 바꾸는 설계 축
| 축 | 바뀌는 내용 |
|---|---|
| 성능 | 병목 계층의 capacity를 올리거나 우회 경로를 만든다. |
| 정합성 | write 병목을 queue나 shard로 나누면 중복, 순서, transaction 경계가 바뀐다. |
| 장애 격리 | scale out은 일부 노드 장애를 흡수하지만 shared dependency 장애는 키울 수 있다. |
| 운영 복잡도 | node 수, 배포, autoscaling, capacity review, 비용 추적이 늘어난다. |
먼저 병목을 분류한다
| 관찰 지표 | 병목 후보 | 바로 scale out해도 되는가? |
|---|---|---|
| App CPU 85%, DB 여유 | app compute | 가능성이 높다. |
| App memory OOM | app memory 또는 leak | scale up 전 leak과 object size 확인 |
| DB CPU 90%, app 여유 | DB query/read | app 증설은 위험할 수 있다. |
| lock wait 증가 | DB write/hot row | app 증설보다 transaction 분리 |
| pool pending 증가 | DB connection 또는 slow query | pool만 키우면 악화 가능 |
| external quota 95% | 외부 API | app 증설 효과 낮음 |
| network egress 포화 | payload/CDN | 응답 크기와 CDN 검토 |
| 이 표 없이 “트래픽이 늘었으니 서버를 늘린다”고 하면 병목을 더 세게 두드릴 수 있다. |
대표 시나리오
주문 목록 API와 주문 생성 API가 같이 느려졌다고 하자.
| 지표 | 값 |
|---|---|
| App CPU | 45% |
| Hikari pending | 120 |
| DB CPU | 82% |
| lock wait | 증가 |
| read QPS | 8,000 |
| write TPS | 700 |
| 외부 결제 API quota | 60% |
| 이 상황에서 app instance를 2배로 늘리면 DB connection 요청도 늘어난다. | |
| 사용자 요청은 더 많이 DB로 들어가고 lock wait는 더 길어질 수 있다. | |
| 먼저 읽기와 쓰기를 나누고, 주문 목록은 cache/replica/query 개선, 주문 생성은 hot row와 transaction을 본다. |
Scale up이 적합한 경우
Scale up은 구조 변경을 작게 유지한다. 다음 상황에서는 현실적인 선택이다.
- 단일 노드 CPU나 memory만 부족하고 구조적 병목이 아직 작다.
- 운영팀이 multi-node 운영 준비가 되어 있지 않다.
- 단기간 이벤트를 넘겨야 하고 구조 변경 위험이 더 크다.
- DB instance class 상향으로 read/write 여유가 충분히 생긴다. 하지만 상한이 있다. 큰 장비는 비용이 비선형적으로 늘고, 장애 시 영향 범위가 계속 하나의 큰 노드에 집중된다.
Scale out이 적합한 경우
Scale out은 stateless 작업에 잘 맞는다. 예를 들어 이미지 리사이즈, JSON serialization, API aggregation처럼 app CPU가 병목이면 효과가 크다.
single_instance_capacity = 500 QPS
target_peak_qps = 3,000
headroom = 1.5
required_instances = 3,000 * 1.5 / 500 = 9이 계산은 app만 본 값이다. DB, Redis, external API capacity가 9개 instance의 부하를 받아야 한다. scale out 계산에는 downstream budget이 반드시 붙어야 한다.
Downstream budget
App을 늘릴 때 shared dependency 총량을 계산한다.
app_instances = 20
max_db_pool_per_instance = 20
max_possible_connections = 400
db_safe_connections = 250이 경우 pool size를 줄이거나 app instance 상한을 낮춰야 한다. 더 많은 app은 더 많은 동시 DB 요청을 만들 수 있다. Redis, Kafka, 결제 API, 검색 cluster도 같은 방식으로 budget을 둔다.
선택을 단계화한다
확장은 보통 한 번에 sharding으로 가지 않는다.
| 단계 | 선택 | 판단 |
|---|---|---|
| 1 | Query/cache/rate limit | 구조 변경 없이 부하를 낮춘다. |
| 2 | Scale up | 빠른 완화와 낮은 구조 변경 |
| 3 | App scale out | stateless compute 병목 분산 |
| 4 | Read replica/read model | read 부하 분산 |
| 5 | Partitioning | 큰 테이블 관리와 query 범위 축소 |
| 6 | Sharding | write/storage 한계를 여러 DB로 분산 |
| 앞 단계를 생략할 수도 있지만, 생략 이유가 숫자로 설명되어야 한다. |
Spring 설정 예시
App scale out 때는 pool과 thread를 함께 조정한다.
server:
tomcat:
threads:
max: 160
spring:
datasource:
hikari:
maximum-pool-size: 12
connection-timeout: 500Pod 수를 늘릴수록 maximum-pool-size 총합이 커진다.
scale out은 app 설정이 아니라 전체 시스템 설정이다.
장애 중 판단
장애 중에는 scale out이 안전한지 먼저 묻는다.
| 상황 | scale out 판단 |
|---|---|
| App CPU 포화, DB 여유 | 임시 scale out 가능 |
| DB lock wait 증가 | scale out 보류, 유입 제한 우선 |
| 외부 API timeout 증가 | scale out 보류, circuit/rate limit 우선 |
| queue consumer lag 증가 | downstream 여유가 있으면 consumer scale out |
| Redis memory/eviction 증가 | app scale out보다 cache policy 확인 |
개인 프로젝트 기준
- 느린 API가 app 병목인지 DB 병목인지 최소한 로그와 지표로 구분한다.
- scale up을 선택했다면 다음 전환 조건을 적는다.
- scale out을 선택했다면 session, file, local cache, scheduler 상태를 확인한다.
- DB pool 총합을 계산한다.
- 포트폴리오에서는 “서버 증설”보다 병목 지표와 선택 이유를 말한다.
기업 운영 기준
- capacity review는 app, DB, cache, queue, external API를 함께 본다.
- autoscaling 정책은 CPU뿐 아니라 latency, queue age, pool pending을 검토한다.
- scale up/down 작업에는 rollback과 비용 영향을 남긴다.
- scale out 상한은 downstream budget과 함께 정한다.
- 장애 중 scale out 허용 조건과 금지 조건을 runbook에 둔다.
위험 신호
- DB lock wait가 높은데 app instance를 먼저 늘린다.
- pool size를 키우면서 DB max connection 예산을 보지 않는다.
- CPU만 보고 memory, I/O, lock, quota를 무시한다.
- scale up을 임시 완화로 했지만 다음 전환 조건이 없다.
- autoscaling이 있으니 capacity planning이 필요 없다고 말한다.
- 성능 개선 후 비용과 장애 영향 범위를 다시 계산하지 않는다.
확인 질문
확인 질문
- 확인 질문: Scale up과 scale out 판단의 첫 질문은 무엇인가?
- 답변: 병목이 어느 계층의 어떤 지표에서 포화되는지 확인하는 것이다.
- 확인 질문: App scale out이 DB 장애를 키우는 이유는 무엇인가?
- 답변: app instance가 늘면 DB connection과 query 동시성도 늘어 기존 DB 병목을 더 압박할 수 있기 때문이다.
- 확인 질문: Scale up이 나쁜 선택인가?
- 답변: 아니다. 빠른 완화와 낮은 구조 변경이 장점이지만 상한, 비용, 단일 장애 영향 범위를 함께 봐야 한다.