서빙 용량 산정 — 어떤 모델을, 어떤 GPU로, 몇 명에게
「우리 서비스에 GPU가 몇 장 필요한가?」 이 질문에 답하려면 모델 크기, GPU 종류, 사용자 수, 서비스 종류, SLO 다섯 가지를 하나의 계산으로 엮어야 한다. 이 장은 그 계산을 처음부터 끝까지 손으로 해 보는 장이다. 앞의 열세 장이 「무엇이 왜 그렇게 생겼는가」였다면, 이 장은 「그래서 몇 대를 사야 하는가」다.
이 장을 마치면
- 모델 가중치와 KV 캐시의 메모리 요구량을 파라미터·구성에서 직접 계산할 수 있다.
- 오픈 웨이트 모델과 상용 API 모델을 같은 기준으로 비교·산정할 수 있다.
- 사용자 수를 동시 요청 수로 환산하고, 서비스 종류에 따라 그 값이 어떻게 달라지는지 설명할 수 있다.
- 목표 SLO와 활용률을 반영해 필요한 GPU 수를 산출하고, 그 결과를 실측으로 검증할 수 있다.
- 산정 결과의 민감도를 분석해 어떤 가정이 결론을 지배하는지 지목할 수 있다.
왜 용량 산정이 어려운가 — 변수가 다섯 개다
「H100 한 장으로 몇 명을 서비스할 수 있나요?」라는 질문에는 답할 수 없다. 질문에 빠진 것이 너무 많기 때문이다. 실제로 답을 결정하는 변수는 다섯 개이고, 그중 하나만 바뀌어도 결과가 열 배씩 달라진다.
| 변수 | 무엇을 정해야 하나 | 결과를 얼마나 바꾸는가 |
|---|---|---|
| ① 모델 | 파라미터 수 · 구조(MoE/dense) · 정밀도 | 8B와 70B는 메모리가 9배, 디코드 속도가 9배 차이 |
| ② GPU 시스템 | 메모리 용량 · 대역폭 · 몇 장을 묶는가 | L40S와 H200은 대역폭이 5배 이상 차이 |
| ③ 사용자 수 | 가입자가 아니라 동시 요청 수 | 가입자 1만 명이 동시 요청 30건일 수도, 300건일 수도 있다 |
| ④ 서비스 종류 | 입력·출력 토큰 길이 · 요청 패턴 | 챗봇과 RAG는 프리필 부하가 4배 이상 차이 |
| ⑤ SLO | TTFT·TPOT 목표 · 목표 활용률 | 지연 목표를 절반으로 조이면 GPU가 두 배 필요할 수 있다 |
용량 산정은 두 개의 상한 중 낮은 쪽으로 결정된다.
- 메모리 상한 — 모델 가중치와 동시 요청들의 KV 캐시가 HBM에 들어가는가. 안 들어가면 그 요청은 아예 못 받는다.
- 처리량 상한 — 초당 필요한 토큰을 GPU가 SLO 안에 만들어 낼 수 있는가. 들어가긴 하는데 느리면 사용자가 기다린다.
둘 중 어느 쪽이 먼저 막히는지는 서비스에 따라 다르다. 긴 컨텍스트 RAG는 대개 메모리가, 짧은 대화형 챗봇은 대개 처리량이 먼저 막힌다.
이 장에 나오는 숫자는 계산 구조를 보이기 위한 대표값이다. 모델 구성(레이어 수, KV 헤드 수)과 GPU 사양은 버전마다 다르므로, 실제 산정에서는 반드시 해당 모델의 config.json 과 GPU 공식 사양표에서 확인해 넣어야 한다.
① 메모리 예산 — 무엇이 HBM을 차지하는가
GPU 한 장의 메모리는 네 몫으로 나뉜다. 이 중 KV 캐시 몫이 곧 동시 사용자 수다.
가중치는 서비스가 시작되기 전에 이미 정해진 고정비다. 오버헤드도 마찬가지다. 설계자가 조절할 수 있는 것은 남는 자리를 KV 캐시에 얼마나 줄 것인가뿐이고, 그 자리가 곧 동시에 받을 수 있는 요청 수가 된다.
그래서 「이 GPU에 이 모델이 올라가는가」는 잘못된 질문이다. 올바른 질문은 「올리고 나서 몇 명분의 KV 캐시가 남는가」다. 70 GB 모델을 80 GB GPU에 올리면 가중치는 들어가지만 남는 10 GB로는 동시 사용자를 몇 명 못 받는다.
직접 제작 도해 · 자유 사용가중치 — 계산이 가장 단순한 부분
가중치 크기 (GB) = 파라미터 수(B) × 정밀도 바이트
FP16 / BF16 → 2 바이트
FP8 → 1 바이트
FP4 (NVFP4) → 0.5 바이트 (+ 블록 스케일 오버헤드 약 3~6%)
예) 70B 모델을 FP8 로 서빙 → 70 × 1 = 70 GBMoE 모델은 「활성 파라미터가 37B니까 37 GB만 있으면 된다」고 생각하기 쉽다. 아니다. 어느 전문가가 호출될지 미리 알 수 없으므로 전체 파라미터를 전부 메모리에 올려 두어야 한다.
MoE가 절약하는 것은 연산량이지 메모리가 아니다. 671B MoE 모델은 활성 파라미터가 37B라도 FP8 기준 671 GB의 자리를 차지한다. 1장의 루프라인으로 말하면, MoE는 연산 강도를 낮추는 대신 메모리 요구는 그대로 두고 통신을 추가한 셈이다(12장의 EP).
KV 캐시 — 사용자 수에 비례하는 부분
KV 캐시는 「이미 읽은 토큰들의 Key·Value를 저장해 두는 것」이다. 토큰 하나가 늘어날 때마다 정해진 크기만큼 커지고, 요청이 하나 늘어날 때마다 그만큼 또 늘어난다.
요청 1건 · 토큰 1개당 KV 바이트
= 2 × 레이어 수 × KV 헤드 수 × 헤드 차원 × 정밀도 바이트
↑ Key 와 Value 두 벌
요청 1건의 총 KV
= 위 값 × (입력 토큰 + 생성된 출력 토큰)
동시 요청 N건의 총 KV
= 위 값 × N여기서 KV 헤드 수가 핵심이다. 최근 모델은 대부분 GQA(Grouped Query Attention)를 써서 쿼리 헤드는 많지만 KV 헤드는 적게 둔다. KV 헤드가 8개면 64개일 때보다 캐시가 8분의 1이다. 모델 선택이 곧 서빙 용량 선택이라는 말이 여기서 나온다.
| 모델 규모 | 대표 구성 (레이어 / KV헤드 / 헤드차원) | 토큰 1개당 KV FP16 | 8K 컨텍스트 1건 | 32K 컨텍스트 1건 |
|---|---|---|---|---|
| 8 B | 32 / 8 / 128 | 128 KB | 1.0 GB | 4.0 GB |
| 32 B | 64 / 8 / 128 | 256 KB | 2.0 GB | 8.0 GB |
| 70 B | 80 / 8 / 128 | 320 KB | 2.6 GB | 10.5 GB |
| 405 B | 126 / 16 / 128 | 1,008 KB | 8.3 GB | 33 GB |
| 671 B MoE | 61 / MLA 압축 | 약 70 KB | 약 0.6 GB | 약 2.3 GB |
671B 모델이 70B 모델보다 KV 캐시가 작다. MLA(Multi-head Latent Attention)처럼 KV를 압축해 저장하는 구조를 썼기 때문이다.
즉 모델이 크다고 서빙이 항상 더 어려운 것이 아니다. 가중치는 크지만 KV가 작으면, 큰 GPU 여러 장을 묶었을 때 오히려 동시 사용자를 더 많이 받을 수 있다. 모델을 고를 때 파라미터 수만 보면 이 차이를 놓친다.
KV 캐시를 FP8로 양자화하면 위 표의 값이 절반이 된다. 정확도 손실이 가중치 양자화보다 작다고 알려져 있어 실무에서 자주 쓰인다. 10장의 오프로딩과 함께, 「KV를 어떻게 다룰 것인가」가 서빙 용량의 핵심 손잡이다.
② 모델 지형 — 오픈 웨이트와 상용 API
서빙할 모델을 고르는 것은 성능만의 문제가 아니다. 어떤 모델을 고르느냐가 필요한 하드웨어를 결정하고, 그것이 곧 예산이다.
모델 크기와 GPU 시스템의 적재 가능 여부. FP8 가중치만 본 것이므로 실제로는 한 단계 빡빡하다.
「여유」는 가중치를 올리고도 KV 캐시 자리가 넉넉하다는 뜻이고, 「빠듯」은 가중치는 들어가지만 동시 사용자를 몇 명 못 받는다는 뜻이다. 「여러 장」은 텐서 병렬로 GPU 여러 장에 나눠 올려야 한다는 뜻이며, 이 경우 8장에서 본 scale-up 대역폭이 성능을 좌우한다.
표에서 읽어야 할 실무적 결론은 이것이다 — 「빠듯」 칸은 사실상 쓸 수 없는 조합이다. 가중치가 겨우 들어가는 구성은 동시 사용자가 몇 명만 붙어도 OOM이 나거나 요청을 큐에 쌓아 두게 되어, 결국 GPU를 더 사는 것보다 비싸진다.
직접 제작 도해 · 자유 사용오픈 웨이트 모델 — 계산이 가능한 쪽
가중치가 공개된 모델은 파라미터 수, 레이어 수, KV 헤드 수를 모두 알 수 있으므로 위의 계산을 그대로 적용할 수 있다. 산정의 출발점으로 삼기 좋다.
| 규모 | 성격 | FP8 가중치 | 필요 GPU (예시) | 이 규모를 고르는 이유 |
|---|---|---|---|---|
| 8 B 급 | dense | 8 GB | L40S 1장 · Spark 1대 | 분류·추출·간단한 요약. 지연이 짧고 매우 싸다 |
| 32 B 급 | dense | 32 GB | A100/H100 1장 | 일반 대화·요약의 실용 하한선. 가성비 구간 |
| 70 B 급 | dense | 70 GB | H200 1장 · H100 2장 | 품질이 눈에 띄게 오르는 구간. 사내 서비스의 주력 |
| 120 B 급 MoE | 활성 ~5 B | 120 GB | H200 1장 · B200 1장 | 활성 파라미터가 작아 디코드가 빠르다. 메모리만 감당되면 유리 |
| 235 B 급 MoE | 활성 ~22 B | 235 GB | MI355X 1장 · H200 2장 | 고품질 서비스. 메모리 큰 장비가 전제 |
| 405 B dense | dense | 405 GB | H200 4장 이상 | 최상위 품질. 다만 KV 캐시도 커서 동시 사용자 비용이 높다 |
| 671 B 급 MoE | 활성 ~37 B | 671 GB | H200 8장 · NVL72 일부 | 활성 파라미터와 KV가 작아 의외로 서빙 효율이 좋다 |
상용 API 모델 — 파라미터를 모를 때
상용 API 모델은 파라미터 수도 구조도 공개되지 않는다. 그렇다면 용량 산정을 할 수 없는가? 다른 방식으로 한다.
| 알 수 없는 것 | 대신 알 수 있는 것 | 어떻게 산정에 쓰는가 |
|---|---|---|
| 파라미터 수 | 벤치마크 성능 | 비슷한 점수의 오픈 모델을 등가 모델로 놓고 하드웨어를 추정 |
| 메모리 요구 | 가격 (백만 토큰당) | 자체 운영 비용과 직접 비교. 15장의 tokens/$ 계산 |
| 처리량 | 공개된 rate limit · 실측 지연 | 부하 테스트로 실효 처리량을 직접 잰다 |
| 가용성 | SLA 문서 | 자체 운영의 목표 가용성 설계에 반영 |
대부분의 조직은 둘 중 하나가 아니라 둘 다 쓴다. 기준은 대체로 이렇다.
- 상용 API가 유리한 경우 — 트래픽이 적거나 들쭉날쭉할 때, 최상위 품질이 필요할 때, 운영 인력이 없을 때. 쓴 만큼만 내므로 15장에서 볼 「가동률」 문제가 아예 없다.
- 자체 운영이 유리한 경우 — 트래픽이 꾸준하고 예측 가능할 때, 데이터가 밖으로 나가면 안 될 때, 특정 도메인에 맞춰 파인튜닝해야 할 때.
- 손익분기 — 15장에서 계산한다. 대략 「자체 장비를 목표 가동률로 채울 수 있는가」가 갈림길이다.
③ GPU 시스템 지형 — 무엇이 얼마를 감당하는가
2장에서 「용량 · 대역폭 · SRAM」의 트레이드오프를 봤다. 서빙 관점에서 다시 정리하면, 용량은 「몇 명을 받을 수 있는가」를, 대역폭은 「얼마나 빨리 답하는가」를 결정한다.
| 시스템 | 메모리 | 메모리 대역폭 | 성격 | 적합한 용도 |
|---|---|---|---|---|
| DGX Spark (GB10) | 128 GB 통합 LPDDR5X | 약 273 GB/s | 용량은 크고 대역폭은 낮다 | 개발·실습·큰 모델 기능 검증 |
| L40S | 48 GB GDDR6 | 864 GB/s | 저렴한 추론 카드 | 8~32 B 모델 · 다수 동시 배치 |
| A100 80GB | 80 GB HBM2e | 2.0 TB/s | 여전히 현역 | 32~70 B · 중간 규모 서비스 |
| H100 SXM | 80 GB HBM3 | 3.35 TB/s | 학습·추론 겸용 표준 | 70 B 급 · 프리필 중심 워크로드 |
| H200 | 141 GB HBM3e | 4.8 TB/s | 용량이 늘어 서빙에 유리 | 70~120 B 를 한 장에 · 긴 컨텍스트 |
| B200 | 192 GB HBM3e | 약 8 TB/s | 대역폭 도약 | 디코드 처리량이 필요한 서비스 |
| MI300X / MI355X | 192 / 288 GB HBM | 5.3 / 약 8 TB/s | 용량 우위 | 큰 모델을 적은 장수로 |
| GB200 NVL72 | 랙 총 13 TB 이상 | 랙 총 수백 TB/s | 랙이 곧 한 대 | 최대 규모 · P/D 분리 서빙 |
- 가중치를 몇 장에 나눠 담아야 하는가? 한 장에 들어가면 텐서 병렬이 필요 없어 통신 오버헤드가 사라진다. 이것만으로 처리량이 20~30% 차이 나기도 한다.
- 남는 자리로 동시 요청 몇 건을 받을 수 있는가? 같은 70 B 모델이라도 H100(80 GB)에서는 10 GB만 남지만 H200(141 GB)에서는 71 GB가 남아 동시 사용자가 7배가 된다.
두 번째 항목이 첫 번째보다 훨씬 중요한데도 자주 무시된다. 「이 모델이 이 GPU에 돌아간다」는 데모와 「이 GPU로 500명을 서비스한다」는 운영은 다른 문제다.

실습 장비 DGX Spark — 「용량은 크고 대역폭은 낮은」 쪽의 전형
통합 메모리 128 GB에 70 B 모델(FP8 70 GB)이 올라간다. 그런데 대역폭이 약 273 GB/s이므로 1장의 계산을 적용하면 디코드 상한이 70 GB ÷ 273 GB/s ≈ 0.26초, 즉 초당 약 4토큰이다. 「돌아간다」와 「서비스할 수 있다」의 차이를 이보다 잘 보여주는 예가 없다. 이 장비는 기능 검증과 실습용이지 서빙용이 아니라는 결론이 계산에서 바로 나온다.
출처: Daniel Lu (User:dllu)CC BY-SA 4.0
반대쪽 — HBM을 다이 옆에 붙여 대역폭을 확보한 패키지
가운데 큰 다이가 연산부, 주위의 작은 사각형들이 HBM 스택이다. 이 물리적 배치가 곧 「대역폭을 사는 방법」이며, 패키지 면적과 인터포저 비용이 그 대가다. 서빙에서 대역폭이 왜 비싼 자원인지가 이 사진 한 장에 들어 있다.
출처: en.wikipedia.org© en.wikipedia.org (교육 목적 인용)④ 서비스 종류 — 같은 사용자 수, 다른 부하
서비스 종류별 입출력 토큰 길이와 프리필·디코드 비중.
오른쪽 막대가 이 표의 핵심이다. 챗봇은 디코드가, RAG는 프리필이 부하의 대부분을 차지한다. 1장의 루프라인으로 옮기면, 챗봇은 메모리 대역폭 한계 영역에서 살고 RAG는 연산 한계 영역에서 산다는 뜻이다.
그래서 같은 GPU라도 잘하는 서비스가 다르다. 대역폭이 큰 B200은 챗봇에 유리하고, 연산이 강한 구성은 RAG 프리필에 유리하다. 13장의 P/D 분리가 「하나의 GPU로 둘 다 잘하려 하지 말라」는 답이었던 이유가 여기 있다.
에이전트 워크로드의 「×N」 표기에 주의하자. 도구를 호출하고 결과를 다시 넣는 왕복이 N번 일어나므로, 사용자 한 명의 한 번 요청이 실제로는 요청 N건이 된다. 에이전트 서비스의 용량 산정에서 가장 흔한 실수가 이 N을 1로 잡는 것이다.
직접 제작 도해 · 자유 사용토큰 사용량을 추정하는 법
서비스가 아직 없어서 실측이 불가능하다면, 다음 순서로 추정한다.
- 전형적인 요청 하나를 직접 만들어 본다. 시스템 프롬프트, 사용자 입력, 검색 결과, 대화 이력을 모두 포함해서.
- 토크나이저로 실제 토큰 수를 센다. 한글은 영어보다 토큰이 1.5~2배 더 나오므로 영어 기준 추정치를 그대로 쓰면 안 된다.
- 출력 길이는 실제로 답을 몇 개 뽑아 평균을 낸다. 「보통 500자」 같은 감이 아니라 분포(중앙값과 p95)를 봐야 한다.
- 대화가 누적되는 서비스라면 세션 평균 길이를 반영한다. 10턴 대화의 마지막 요청은 첫 요청보다 입력이 훨씬 길다.
같은 내용이라도 한글은 영어보다 토큰이 많이 나온다. 모델과 토크나이저에 따라 다르지만 대체로 1.5~2배로 본다.
이것은 세 곳에서 동시에 비용을 올린다 — ① 프리필 연산량, ② KV 캐시 용량, ③ 상용 API를 쓴다면 요금. 영어 기준 벤치마크나 해외 사례의 토큰 수치를 그대로 가져오면 30~50% 과소 산정된다.
⑤ 사용자 수를 동시 요청 수로 바꾸기
GPU가 실제로 상대하는 것은 가입자 수가 아니다. 같은 순간에 살아 있는 요청의 개수다. 이 환산이 용량 산정에서 가장 자주 틀리는 지점이다.
가입자에서 동시 요청 수까지의 환산 단계.
마지막 단계에 쓰인 것이 Little's Law다. 대기행렬 이론의 가장 기본 식으로, 「시스템 안에 평균 몇 개가 들어 있는가 = 도착률 × 머무는 시간」이다. 초당 2.5건이 들어오고 각 요청이 평균 12초 머문다면, 항상 30건이 시스템 안에 있다.
각 단계의 비율은 서비스마다 크게 다르므로 반드시 자기 서비스의 값을 넣어야 한다. 특히 「피크 집중률」이 중요한데, 사내 서비스는 업무 시간에 몰려 30~40%가 되지만 대외 서비스는 훨씬 완만하다. 수업용 서비스라면 강의 시간에 극단적으로 몰릴 수 있다.
그리고 평균 응답 시간이 길어지면 동시 요청 수도 함께 늘어난다는 점에 주의하자. GPU가 부족해 응답이 느려지면 → 동시 요청이 쌓이고 → KV 캐시가 더 필요해지고 → 더 느려지는 악순환이 생긴다. 그래서 용량은 넉넉히 잡아야 한다.
직접 제작 도해 · 자유 사용활용률과 응답 시간의 관계. 100%에 가까워질수록 대기 시간이 발산한다.
이것이 「목표 활용률로 나눈다」는 규칙의 근거다. GPU를 100% 채우도록 용량을 잡으면 요청이 조금만 몰려도 응답이 무너진다. 지연이 중요한 서비스는 50~70%, 배치성 작업은 85~95%를 목표로 잡는다.
곡선의 모양은 M/M/c 대기행렬의 성질에서 나온다. 정확한 값은 요청 도착 패턴과 처리 시간 분포에 따라 달라지지만, 「활용률이 올라갈수록 대기가 비선형으로 급증한다」는 성질은 항상 성립한다.
실무에서는 이 곡선을 부하 테스트로 직접 그려 본다. 동시 요청 수를 서서히 올리면서 p99 지연을 기록하면 어느 지점에서 꺾이는지가 보이고, 그 지점의 80% 정도를 운영 목표로 잡는다.
직접 제작 도해 · 자유 사용산정 절차 — 일곱 단계
앞의 다섯 변수를 순서대로 넣으면 답이 나온다. 이 절차를 그대로 따라 하면 된다.
[1] 서비스 정의
모델 · 정밀도 · 서비스 종류 · 목표 SLO(TTFT, TPOT)
[2] 요청 프로파일
평균 입력 토큰 I
평균 출력 토큰 O
요청당 왕복 횟수 R (에이전트가 아니면 1)
[3] 동시 요청 수
QPS = DAU × 피크집중률 × 세션당요청 ÷ 피크시간(초)
평균 응답 = TTFT + O × TPOT
동시요청 N = QPS × 평균 응답 × R ← Little's Law
[4] 메모리 상한 검사
가중치 = 파라미터 × 정밀도바이트
요청당 KV = 2 × 레이어 × KV헤드 × 헤드차원 × (I+O) × 바이트
필요 메모리 = 가중치 + 요청당KV × N + 오버헤드(약 10%)
→ GPU 메모리에 들어가는가? 안 들어가면 GPU를 늘리거나 N을 줄인다
[5] 처리량 상한 검사
필요 출력 토큰/초 = QPS × O
GPU 1대 실효 처리량 = (실측 또는 추정) tok/s
필요 GPU 수(처리량) = 필요 토큰/초 ÷ GPU 1대 처리량
[6] 목표 활용률 반영
최종 GPU 수 = max(메모리 기준, 처리량 기준) ÷ 목표활용률
( 지연 중시 0.6 · 처리량 중시 0.9 )
[7] 여유와 검증
+ 장애 대비 여유 (N+1)
+ 성장 여유 (6~12개월)
→ 부하 테스트로 실측 검증워크 예제 ① — 학과 챗봇 (학생 500명)
| 단계 | 값 | 근거 |
|---|---|---|
| 모델 · 정밀도 | 32 B · FP8 (가중치 32 GB) | 일반 대화 품질의 실용 하한 |
| SLO | TTFT 1 s · TPOT 40 ms | 대화형 체감 기준 |
| 요청 프로파일 | 입력 800 · 출력 500 토큰 | 한글 보정 반영 |
| DAU | 150 명 (500명 × 30%) | 수업 관련 이용 |
| 피크 집중 | 40% → 60 명 | 강의 시간 집중 |
| QPS | 약 0.5 건/초 | 세션당 6요청 ÷ 1시간 |
| 평균 응답 | 1 + 500×0.04 = 21 초 | TTFT + 출력×TPOT |
| 동시 요청 N | 약 11 건 | 0.5 × 21 |
| 요청당 KV (8K) | 약 0.33 GB | 입력+출력 1,300 토큰 기준 |
| 필요 메모리 | 32 + 0.33×11 + 여유 ≈ 40 GB | |
| 결론 | A100 80GB 1장으로 충분 | 메모리·처리량 모두 여유 |
워크 예제 ② — 사내 코딩 어시스턴트 (개발자 2,000명)
| 단계 | 값 | 근거 |
|---|---|---|
| 모델 · 정밀도 | 70 B · FP8 (가중치 70 GB) | 코드 품질이 중요 |
| 요청 프로파일 | 입력 16,000 · 출력 200 토큰 | 저장소 맥락을 크게 넣음 |
| DAU | 1,200 명 | 개발자는 활성률이 높다 |
| 피크 집중 | 35% → 420 명 | 업무 시간 |
| QPS | 약 2.3 건/초 | 시간당 20회 자동완성 요청 |
| 평균 응답 | 2 + 200×0.03 = 8 초 | |
| 동시 요청 N | 약 19 건 | |
| 요청당 KV (16.2K) | 약 5.2 GB | 입력이 길어 KV가 폭증 |
| 필요 메모리 | 70 + 5.2×19 + 여유 ≈ 185 GB | |
| 결론 | H200 2장 또는 MI355X 1장 | 메모리가 먼저 막힌다 |
사용자 수는 4배 차이인데 필요 메모리는 4.6배다. 그런데 그 이유가 사용자 수가 아니다. 입력 토큰이 20배(800 → 16,000)라서 KV 캐시가 폭증했기 때문이다.
만약 예제 ②에서 「사용자가 4배니까 GPU도 4배」로 산정했다면 크게 빗나갔을 것이다. 용량은 사용자 수가 아니라 「동시 요청 수 × 요청당 컨텍스트 길이」에 비례한다.
워크 예제 ③ — 공공 RAG 문서 서비스 (동시 접속 200)
| 단계 | 값 | 메모 |
|---|---|---|
| 모델 | 120 B MoE · FP8 (가중치 120 GB) | 활성 파라미터가 작아 디코드가 빠름 |
| 요청 프로파일 | 입력 32,000 · 출력 800 | 검색 문서를 통째로 투입 |
| 동시 요청 N | 200 건 | 주어짐 |
| 요청당 KV | 약 4.5 GB | MoE 구조에 따라 크게 달라짐 |
| 필요 메모리 | 120 + 4.5×200 = 1,020 GB | KV가 가중치의 7배 이상 |
| 결론 | H200 8장 또는 그 이상 | 명백히 메모리 지배 |
| 대안 검토 | KV FP8 양자화 → 약 570 GB | GPU 수를 절반 가까이 줄일 수 있다 |
| 대안 검토 | 프리픽스 재사용 | 같은 문서를 보는 요청이 많다면 큰 절감 |
예제 ③에서 보듯, 긴 컨텍스트 서비스는 KV 캐시가 가중치보다 훨씬 큰 몫을 차지한다. 이런 서비스에서는 「어떤 모델을 쓸까」보다 「KV를 어떻게 줄일까」가 예산을 결정한다. 10장의 오프로딩·프리픽스 재사용, 그리고 KV 양자화가 여기서 실제 돈이 된다.
시뮬레이션과 검증 — 계산은 시작일 뿐
위 계산은 출발점이지 답이 아니다. 실제 성능은 엔진 구현, 스케줄링, 요청 분포에 따라 계산값의 절반이 나올 수도 있다. 반드시 실측으로 검증해야 한다.
검증 절차
- 단일 요청 기준선 — 동시 요청 1건으로 TTFT·TPOT을 잰다. 이것이 그 GPU·모델 조합의 최선이며, 여기서부터만 나빠진다.
- 포화점 찾기 — 동시 요청 수를 1, 2, 4, 8, 16, 32… 로 올리며 처리량과 p99 지연을 기록한다. 처리량이 더 이상 안 늘고 지연만 늘기 시작하는 지점이 포화점이다.
- SLO 경계 찾기 — p99 지연이 목표 SLO를 넘는 동시 요청 수를 찾는다. 이것이 그 GPU 한 대의 실제 용량이다.
- 계산값과 비교 — 계산에서 나온 N과 실측 용량의 비율을 구한다. 이 비율이 여러분 환경의 보정 계수이며, 이후 산정에 그대로 쓸 수 있다.
- 장시간 부하 — 30분 이상 돌려 메모리 단편화, 성능 저하, 스로틀링이 없는지 확인한다.

포화점을 찾는다는 것은 이 곡선 위에서 점을 고르는 일이다
가로축이 처리량, 세로축이 사용자 체감 응답성이다. 오른쪽으로 갈수록 GPU를 많이 쓰지만 개별 사용자는 느려진다. 어느 점을 고를지는 SLO가 정한다. 부하 테스트로 이 곡선을 직접 그리고, SLO 선과 만나는 지점의 처리량이 여러분 시스템의 실제 용량이다.
출처: developer.nvidia.com© developer.nvidia.com (교육 목적 인용)
부하가 시간대에 따라 변하면 용량도 고정일 필요가 없다
13장에서 본 플래너는 프리필 풀과 디코드 풀의 비율을 실시간으로 조정한다. 낮에는 대화형 요청이, 밤에는 배치 작업이 많다면 같은 하드웨어로 두 가지 용량 프로파일을 오갈 수 있다. 용량 산정을 「최대 부하 기준 고정」이 아니라 「시간대별 프로파일」로 하면 필요 장비 수가 줄어든다.
출처: developer.nvidia.com© developer.nvidia.com (교육 목적 인용)자주 나오는 함정
| 함정 | 무슨 일이 생기나 | 어떻게 피하나 |
|---|---|---|
| 평균으로만 산정 | p99 요청이 SLO를 깨고, 그 요청들이 큐를 막는다 | 입력·출력 길이의 분포로 산정한다 |
| 최대 컨텍스트로 KV 계산 | 실제보다 몇 배 과대 산정 → 장비 낭비 | 실제 평균 컨텍스트로 계산하고, PagedAttention이 낭비를 줄인다는 점을 반영 |
| 단일 요청 벤치마크로 외삽 | 동시 요청이 늘면 배치 효과로 오히려 처리량이 늘어난다 | 반드시 동시 요청 상태에서 측정 |
| 활용률 100% 가정 | 실제로는 응답이 무너진다 | 목표 활용률로 나눈다 (위 곡선) |
| 성장 무시 | 6개월 뒤 증설을 못 한다 | 리드타임(수개월)을 고려해 성장 여유를 미리 잡는다 |
| 에이전트 왕복 무시 | 요청 수가 예상의 N배 | 요청당 왕복 횟수 R을 실측한다 |
실습 — 우리 조건으로 산정하고 실측으로 검증하기
목표: 스스로 정한 서비스 시나리오에 대해 필요한 GPU 수를 계산으로 산출하고, DGX Spark에서 실측해 계산값과의 차이를 설명한다. 17장 설계 프로젝트의 용량 산정 근거가 된다.
1단계 — 산정 워크시트 채우기
| 구분 | 항목 | 값 | 근거 |
|---|---|---|---|
| 서비스 | 대상 사용자 수 | ||
| 서비스 종류 | |||
| 목표 TTFT / TPOT | |||
| 모델 | 이름 · 파라미터 · 정밀도 | config.json 확인 | |
| 레이어 / KV헤드 / 헤드차원 | config.json 확인 | ||
| 요청 | 평균 입력 토큰 (한글 보정) | 토크나이저로 실측 | |
| 평균 출력 토큰 | |||
| 요청당 왕복 R | |||
| 부하 | DAU · 피크 집중률 | ||
| QPS | |||
| 동시 요청 N (Little's Law) | |||
| 메모리 | 가중치 GB | ||
| 요청당 KV GB | |||
| 필요 총 메모리 | |||
| 결과 | 메모리 기준 GPU 수 | ||
| 처리량 기준 GPU 수 | |||
| 목표 활용률 | |||
| 최종 GPU 수 |
2단계 — 실측
# 모델을 띄우고 동시 요청 수를 올려 가며 측정
vllm serve <model> --max-model-len 8192
# 동시성 1 → 2 → 4 → 8 → 16 → 32 …
# 기록: 처리량(tok/s), TTFT p50/p99, TPOT p50/p99, GPU 메모리 사용량
# KV 캐시 사용량 확인 (엔진 로그 또는 메트릭)
# - 할당된 KV 블록 수
# - 요청당 실제 KV 점유량| 동시 요청 | 처리량 (tok/s) | TTFT p99 (ms) | TPOT p99 (ms) | KV 사용 (GB) | SLO 충족? |
|---|---|---|---|---|---|
| 1 | |||||
| 2 | |||||
| 4 | |||||
| 8 | |||||
| 16 | |||||
| 32 |
3단계 — 대조와 보정
- 계산한 요청당 KV 값과 실측 KV 점유량이 얼마나 맞는가? 차이가 난다면 원인은 무엇인가? (PagedAttention의 블록 단위 할당, 프리픽스 공유 등)
- SLO를 만족하는 최대 동시 요청 수는 몇인가? 계산값 N과 비교하라. 그 비율이 여러분의 보정 계수다.
- 처리량이 포화되는 지점은 어디인가? 그 지점에서 GPU 활용률은 얼마인가?
- 1장에서 계산한 이론 상한(대역폭 ÷ 가중치)과 실측 처리량의 비율은? 그 격차를 어떤 항목들이 설명하는가?
4단계 — 민감도 분석
아래 항목을 각각 바꿔 최종 GPU 수가 몇 % 움직이는지 표로 만들어라. 가장 민감한 항목이 여러분이 가장 신중하게 정해야 할 값이다.
- 평균 입력 토큰 ±50%
- 동시 요청 수 ±50%
- 목표 TPOT ±50%
- 정밀도 FP16 → FP8 → FP4
- KV 캐시 양자화 적용 여부
- 목표 활용률 0.6 → 0.9
제출물
산정 워크시트(수식이 살아 있는 스프레드시트) + 실측표 + 보정 계수 + 민감도 표 + 「우리 서비스에는 무엇을 몇 대」 결론 (A4 4장 이내).
DGX Spark의 대역폭 한계 때문에 큰 모델은 실측이 어려울 수 있다. 그럴 때는 작은 모델로 방법론을 검증하고, 큰 모델은 계산과 공개된 벤치마크로 추정하되 그 한계를 명시할 것. 「측정할 수 없는 것을 측정한 척하지 않는 것」이 이 실습의 숨은 목표다.
- 상용 API와 자체 운영의 손익분기를 어떻게 계산하겠는가? 토큰 단가 외에 무엇을 넣어야 공정한 비교가 되는가?
- 동시 사용자가 예측보다 3배 몰렸을 때 시스템은 어떻게 반응해야 하는가? (요청 거절 · 큐 대기 · 품질 저하 · 자동 확장 중 무엇을?)
- 긴 컨텍스트를 지원한다고 광고하면서 실제로는 몇 명만 동시에 쓸 수 있는 서비스가 흔하다. 왜 그런 일이 생기는가? 이 장의 계산으로 설명해 보라.
- 모델을 하나 더 큰 것으로 바꾸는 것과, GPU를 하나 더 사는 것 중 무엇이 먼저인가? 어떤 기준으로 판단하겠는가?
참고 자료
- 각 오픈 웨이트 모델의
config.json— 레이어 수·KV 헤드 수·헤드 차원의 1차 출처 - Kwon et al., PagedAttention (SOSP 2023) — KV 캐시 관리가 동시 처리 수를 어떻게 바꾸는가
- vLLM · SGLang 벤치마크 문서 — 부하 테스트 방법
- Little, A Proof for the Queuing Formula L = λW (1961) — 동시 요청 수 환산의 근거
- NVIDIA Dynamo AIConfigurator 문서 — SLO 기반 구성 탐색 도구