수요를 가정으로 세우자 쌓아 둔 실측이 용량 모델로 읽혔다
목차
공급 실측은 쌓여 있었습니다. 모델 서버 처리량, DB 읽기·쓰기 무릎, 앱 홈 경로, 과부하에서 마르는 자원까지 문서에 숫자로 남아 있었습니다. 수요 모델이 없었습니다. 목표 수요가 없으면 그 실측이 몇 배 모자란지, 증설이 언제 필요한지 말할 수 없습니다. 그래서 MAU 10만 · 30만 · 100만을 가정으로 세우고 peak RPS를 유도해 기존 실측과 대조했습니다. 첫 병목은 모델 서버였습니다. 1대 9.34/s는 MAU 약 7.5만에서 홈 수요가 넘어섭니다. 모델을 믿을 수 있는지 잠금 직렬 상한과 Little’s Law로 먼저 검증했고(실측과 2% 안) 수평 확장 예측은 측정 전에 커밋했습니다. 2대 실측 15.15/s는 예측 범위(16~19/s) 밖이었습니다. 법칙은 맞았습니다. 틀린 것은 서비스 시간을 상수로 둔 가정이었습니다.
개요
이 프로젝트는 커머스 백엔드(주문 · 결제 · 정산)에 개인화 모델 서버를 붙여 왔습니다. 홈 페이지의 줄 구성을 생성 모델과 순위 모델 점수를 합쳐 만드는 방식이 기본값이 되면서(ch64) 홈 요청마다 모델 서버를 한 번씩 부릅니다. 성능 측정은 그동안 자원별로 따로 했습니다. 모델 서버의 과부하, DB의 읽기 · 쓰기 무릎, 앱 홈 경로의 처리량이 각각 다른 문서에 있었고 이것들을 하나의 질문으로 묶은 적이 없었습니다. 이 트래픽 가정에서 무엇이 먼저 모자라는가 하는 질문입니다.
원칙을 둘 정했습니다. 수요 수치는 가정이고 공급 수치는 실측이며 표마다 어느 쪽인지 구분 열로 밝힙니다. 실측이 없는 자원은 미측정으로 적고 가정으로 채우지 않습니다.
이 글의 공급 수치는 맥 한 대에서 부하 도구 · 앱 · 모델 서버가 CPU를 나눠 쓴 로컬 실측입니다. AWS에서 실측한 적은 없고 비용은 환산 추정입니다.
수요: MAU에서 peak RPS까지
유도 체인은 MAU → DAU → 일 요청 → 평균 RPS → peak RPS입니다. DAU/MAU 0.25, 사용자당 일 요청 36(세션 1.5 × 페이지 8 × API 3), peak/평균 8배를 가정하면 peak RPS는 MAU/1200으로 줄어듭니다.
| MAU | 평균 RPS | peak RPS |
|---|---|---|
| 10만 | 10.42 | 83.33 |
| 30만 | 31.25 | 250.00 |
| 100만 | 104.17 | 833.33 |
API 믹스는 앱의 실제 엔드포인트와 부하 스크립트가 나눠 둔 표면을 보고 가정했습니다. 홈(모델 호출)이 15%, 읽기 전체가 97%, 결제 승인이 1%입니다. 요청 하나가 잡는 자원(홈 요청마다 모델 호출 1회, 결제 승인마다 PG 호출 1회)은 실측에서 끌어왔고 읽기 요청당 DB 1조회만 가정입니다.
대조: 첫 병목은 모델 서버다
각 자원의 수요를 공급으로 나눴습니다. 1을 넘으면 모자랍니다.
| 자원 | 공급(실측) | 10만 | 30만 | 100만 |
|---|---|---|---|---|
| 모델 서버 1대(결합 방식, 동시성 4) | 9.34/s | 1.34 | 4.01 | 13.38 |
| 앱 홈 2쪽 경로(결합 방식) | 10.2/s | 0.41 | 1.23 | 4.08 |
| DB 읽기 | 1,800/s | 0.04 | 0.13 | 0.45 |
| DB 쓰기(결제 경로) | 약 120/s | 0.02 | 0.06 | 0.21 |
모델 서버는 MAU 10만에서 이미 1.34배 모자랍니다. 홈 요청 전체 기준으로 MAU 약 7.5만에서 수요가 1대 상한을 넘어섭니다. DB는 MAU 100만에서도 읽기 무릎의 45%라 여유가 있습니다. PG는 실제 응답시간 분포가 없어 처리율을 환산할 수 없으므로 대조에서 뺐습니다. 미측정을 가정으로 채우면 표가 전부 같은 무게로 보이기 때문입니다.
법칙으로 모델을 검증했다
대조를 믿으려면 모델이 기존 실측을 다시 계산해 맞히는지 봐야 합니다. 세 가지를 확인했습니다.
| 법칙 | 예측 | 실측 | 오차 |
|---|---|---|---|
| 잠금 직렬 상한 X = 1/S | 1 ÷ 0.107s = 9.35/s | 9.34/s(동시성 4) | +0.09% |
| Little’s Law W = N/X | 4 ÷ 9.34 = 428ms | 왕복 p50 421ms | +1.8% |
| 자리 점유율 합(추천 + 2쪽) | 붕괴 경계 12.18/s | 8/s 생존 · 16/s 붕괴 | 경계가 구간 안 |
모델 서버는 추론에 잠금 하나를 쓰므로 처리량 상한이 평균 추론 시간의 역수입니다. 동시성을 4에서 올려도 처리량이 늘지 않는 기존 관측이 이 구조와 맞았고 대기는 왕복 지연으로만 쌓였습니다.
확장 예측을 측정 전에 커밋했다
수평 확장은 측정해 본 적이 없었습니다. 예측을 먼저 적어 커밋하고 그 커밋 뒤에 측정했습니다. 측정 후에 예측 절은 고치지 않고 보정 절을 따로 적었습니다. 측정을 보고 예측을 고치면 맞은 것처럼 보이기 때문입니다.
| 조건 | 예측 | 실측 | 판정 |
|---|---|---|---|
| 1대 동시성 8 | 9.3/s 유지 · 왕복 860ms | 7.95/s · 왕복 1,003ms | 벗어남(처리량 −15%) |
| 2대 동시성 4 | 16~19/s | 15.15/s | 범위 밖(최저 예측보다 4.6% 낮음) |
| 2대 동시성 8 | 2대 상한 유지 | 15.27/s | 일치 |
빗나간 두 건의 원인은 하나였습니다. 서비스 시간이 상수라는 가정입니다. 동시성 8에서 추론 p50이 105ms에서 127ms로 늘었고 1 ÷ 0.127 ≈ 7.9/s는 실측 7.95/s와 맞습니다. 왕복도 W = 8 ÷ 7.95 = 1,006ms로 실측 1,003ms와 0.3% 안에서 맞습니다. 2대가 같은 호스트에서 돌면 프로세스당 추론이 105ms에서 131ms로 늘었고 2 × (1 ÷ 0.1325) ≈ 15.1/s가 실측 15.15/s와 맞습니다. 법칙은 두 경우 모두 1% 안에서 실측을 설명했습니다. 같은 호스트의 2프로세스 확장 배율은 1.59배였고 호스트를 분리했을 때의 배율은 이 측정으로는 모릅니다.
비용 환산과 성장 마일스톤
비용은 3단 추정입니다. 로컬 실측 처리량을 인스턴스 스펙으로 환산하고 온디맨드 단가를 곱합니다. 각 단의 오차가 곱해지므로 결과의 오차는 어느 한 단보다 큽니다. 단가만 AWS 공식 가격 목록(서울 리전 JSON)에서 받은 값이고 환산과 대수는 추정입니다.
| MAU | 월 비용(환산 추정) | 지배 품목 |
|---|---|---|
| 10만 | $902.53 | RDS $385.40(42.7%) |
| 30만 | $1,121.65 | RDS $385.40(34.4%) |
| 100만 | $1,792.37 | 모델 서버 14대 $833.95(46.5%) |
10만 단계에서는 대수와 무관한 RDS 고정비가 비용을 정하고 100만 단계에서는 모델 서버 대수가 정합니다. 그래서 성장 마일스톤의 첫 줄은 모델 서버입니다. MAU 약 7.5만에서 증설 신호(입장 제한 거절율, 추론 p95)가 켜지고 선택지는 수평 증설과 미리 계산 페이지 전환(캐시 경로 941/s 실측)입니다. DB 읽기 리플리카는 MAU 100만에서도 무릎의 45%라 그보다 뒤입니다.
정리
- 수요 가정을 세우기 전에는 공급 실측이 각자 따로 있는 숫자였습니다. peak RPS = MAU/1200 하나를 세우자 같은 숫자들이 “MAU 7.5만에서 모델 서버가 먼저 모자란다”로 읽혔습니다
- 잠금 직렬 상한과 Little’s Law는 실측을 2% 안에서 설명했습니다. 빗나간 확장 예측도 법칙이 틀린 것이 아니고 서비스 시간 상수 가정이 틀린 것이었습니다. 보정은 예측 절을 고치지 않고 따로 적었습니다
- 수치의 구분(실측 · 가정 · 환산 · 미측정)을 표마다 밝혔습니다. PG처럼 분포가 없는 자원은 대조에서 빼는 쪽을 골랐습니다
- 재계산 절차를 코드(
tools/capacity_model.py --check, 검증 48건)로 남겼습니다. 가정을 바꾸면 표가 통째로 바뀌므로 문서의 모든 수치가 식에서 다시 나오는지 기계로 확인합니다
근거 문서: 저장소의 docs/40-capacity-model.md(수요 유도 · 대조 · 법칙 검증 · 확장 예측과 보정), docs/41-capacity-cost-and-milestones.md(단가 출처 · 월 비용 · 마일스톤), 실측 원자료 personalization/docs/runs/20261005-c2-usl/.
댓글
댓글 수정/삭제는 GitHub Discussions에서 가능합니다.