광고
~ / posts / developer

LLM 서빙 배칭 방식 고르기, 청크 프리필 토큰 예산과 GPU 비용 계산

H100 한 장에 8B 모델을 올려 직접 계산하면 출력 100만 토큰당 GPU 비용이 요청 하나씩 처리할 때 5.91달러, 정적 배칭 1.28달러, 연속 배칭 64개 동시 0.17달러예요. 토큰 예산별 TTFT·ITL 변화와 상황별 설정, 도입 체크리스트를 정리했어요.

자체 모델을 vLLM이나 TGI로 띄우기로 했다면 다음 질문은 "배칭을 어떻게 걸고, max_num_batched_tokens는 얼마로 두고, 프리필과 디코드를 나눠야 하나"예요. 결론부터 말하면 사람이 기다리는 서비스라면 연속 배칭과 청크 프리필은 켜 두는 게 기본이고, 실제로 고를 건 한 스텝의 토큰 예산 하나예요. 예산을 작게 잡으면 다른 사용자의 글자가 멈칫하는 시간(ITL)이 줄고, 크게 잡으면 처리량과 첫 토큰 시간(TTFT)이 유리해요. 비용은 배칭 방식보다 GPU를 얼마나 꽉 채우느냐가 더 크게 좌우해요.

스케줄러 내부는 알고 있다고 보고, 이 글은 고르는 데 필요한 숫자만 다뤄요. H100 한 장과 8B 모델로 스텝 시간을 직접 계산하고 공식 가격표 단가로 토큰당 비용을 냈어요. 이론 상한이라 실측은 이보다 나쁘지만, 방식끼리의 차이와 방향은 그대로 읽을 수 있어요.

광고

비교 기준: H100 한 장과 8B 모델로 직접 계산

계산에 쓴 값은 모두 공개 자료에서 가져왔어요. NVIDIA H100 제품 페이지의 H100 SXM 메모리 대역폭은 3.35TB/s, BF16 텐서 코어 성능은 1,979 TFLOPS인데 이 값은 희소성(sparsity)을 가정한 숫자라 일반 행렬곱 기준인 절반, 약 989 TFLOPS를 썼어요. GPU 단가는 Lambda 가격표의 H100 SXM 1장 인스턴스 시간당 4.29달러(2026-10-28 확인)예요. 한 달은 730시간으로 잡아 월 3,132달러예요.

모델은 Qwen3-8B(약 8.2B, bf16 가중치 약 16.4GB, 토큰당 KV 144KiB), 요청의 평균 문맥(프롬프트 + 생성한 토큰)은 1,500토큰으로 두었어요. KV 크기와 한 장에 담기는 동시 요청 수는 vLLM KV 캐시 용량 계산에 정리해 두었어요.

디코드 한 스텝 시간은 이렇게 잡았어요.

스텝 시간 = max((가중치 바이트 + 동시 요청 수 × 문맥 토큰 × 토큰당 KV 바이트) ÷ 대역폭, 동시 요청 수 × 2 × 파라미터 수 ÷ 연산 성능)

앞쪽이 메모리 읽기, 뒤쪽이 계산 시간이에요. 계산 쪽이 따라잡으려면 한 스텝에 토큰이 약 300개(989 ÷ 3.35 ≈ 295)는 들어가야 해서, 요청당 토큰이 1개인 디코드는 거의 늘 메모리에 묶여요. 아래 비교는 모두 여기서 출발해요.

동시 요청 수별 처리량·지연·토큰당 비용

동시 요청 수스텝 시간(=ITL)사용자 1명이 보는 속도GPU 전체 출력출력 100만 토큰당 GPU 비용
14.96ms초당 202토큰초당 202토큰5.91달러
85.42ms초당 185토큰초당 1,477토큰0.81달러
327.00ms초당 143토큰초당 4,570토큰0.26달러
649.12ms초당 110토큰초당 7,021토큰0.17달러
12813.34ms초당 75토큰초당 9,595토큰0.12달러
25621.79ms초당 46토큰초당 11,747토큰0.10달러
동시 요청 수별 출력 100만 토큰당 GPU 비용 (이론 상한 · 8B bf16 · H100)
1개1개 · 5.9달러5.9달러8개8개 · 0.81달러0.81달러32개32개 · 0.26달러0.26달러64개64개 · 0.17달러0.17달러128개128개 · 0.12달러0.12달러256개256개 · 0.1달러0.1달러

대역폭을 100% 쓴다고 본 하한이에요. 실측 비용은 이보다 높게 나와요.

단위: 달러 · 자료: NVIDIA H100 SXM 대역폭 3.35TB/s, BF16 밀집 989 TFLOPS, Lambda H100 시간당 4.29달러(2026-10-28 확인)로 직접 계산. 평균 문맥 1,500토큰
표로 보기
구분100만 토큰당 비용
1개5.9
8개0.81
32개0.26
64개0.17
128개0.12
256개0.1

1개에서 32개로 가면 사용자 속도는 29%만 줄고 GPU 전체 출력은 23배가 돼요. 배칭 없는 서빙은 GPU 대여료를 거의 그대로 버리는 셈이에요.

64개를 넘으면 이득이 빠르게 줄어요. 요청 하나가 스텝마다 KV 캐시 약 221MB를 읽어서, 동시 64개면 그 합(14.2GB)이 가중치와 비슷해지고 요청이 늘수록 스텝도 길어져요. 128개에서 256개로 늘려도 비용은 약 18%만 내려가고 사용자 속도는 초당 75토큰에서 46토큰으로 떨어져요.

문맥이 길수록 비싸요. 평균 문맥 8,000토큰이면 동시 32개의 비용이 100만 토큰당 0.60달러로 2.3배이고, KV 용량 때문에 동시 64개는 한 장에 들어가지도 않아요.

입력 토큰은 프리필에서 한꺼번에 계산돼 연산에 묶이고, 같은 식으로 초당 약 5만 9천 토큰, 100만 토큰당 약 0.02달러예요. 출력보다 약 5~13배 싸요. 반복되는 긴 프롬프트를 아예 다시 계산하지 않는 방법은 프롬프트 캐싱 비용 계산에서 비교했어요.

정적 배칭 vs 연속 배칭, 출력 길이 분포가 비용을 가른다

transformers의 generate()에 요청을 묶어 넣는 방식이 정적 배칭이에요. 묶음 안에서 가장 긴 답이 끝날 때까지 다른 칸은 놀아요. 얼마나 노는지는 출력 길이 분포로 계산할 수 있어요. 예시로 출력이 100토큰 50%, 300토큰 30%, 800토큰 15%, 2,000토큰 5%인 서비스를 두면 평균은 360토큰이에요. 묶음 크기가 B일 때 가장 긴 답의 기댓값을 구해 평균으로 나누면 칸 활용률이 나와요.

묶음 크기가장 긴 답의 기댓값칸 활용률출력 100만 토큰당 비용
정적 81,119토큰32.2%2.51달러
정적 321,767토큰20.4%1.28달러
연속 32—거의 100%0.26달러

묶음을 키울수록 긴 답이 끼어들 확률이 높아져 활용률이 오히려 떨어져요. 32칸이면 1 − 0.95^32 ≈ 81%의 묶음에 2,000토큰 답이 하나 이상 들어 있어요. 연속 배칭은 끝난 칸을 바로 채우니 대기열만 차 있으면 활용률이 1에 가까워요.

방식별 출력 100만 토큰당 GPU 비용 (예시 출력 분포 · 평균 360토큰)
0123456요청 하나씩 · 100만 토큰당 비용 5.9달러5.9요청 하나씩정적 배칭 8 · 100만 토큰당 비용 2.5달러2.5정적 배칭 8정적 배칭 32 · 100만 토큰당 비용 1.3달러1.3정적 배칭 32연속 배칭 32 · 100만 토큰당 비용 0.26달러0.26연속 배칭 32연속 배칭 64 · 100만 토큰당 비용 0.17달러0.17연속 배칭 64
단위: 달러 · 자료: 위 이론 스텝 시간 × 칸 활용률로 직접 계산(정적은 끝난 칸도 스텝 시간을 그대로 쓴다고 가정)
표로 보기
구분100만 토큰당 비용
요청 하나씩5.9
정적 배칭 82.5
정적 배칭 321.3
연속 배칭 320.26
연속 배칭 640.17

공개된 측정도 방향이 같아요. Anyscale의 2023년 벤치마크(OPT-13B, A100 40GB 한 장)는 단순 정적 배칭 대비 연속 배칭만으로 처리량 8배, vLLM의 메모리 관리까지 더해 최대 23배를 보고했어요. Orca 논문(OSDI '22)은 GPT-3 175B에서 같은 지연 수준일 때 FasterTransformer 대비 처리량 36.9배를 냈고요. 둘 다 당시 버전과 저자 조건의 숫자라 내 서비스에서는 실제 길이 분포로 다시 재야 해요. 출력 길이가 거의 일정한 작업(분류 라벨 같은)이면 차이가 크게 줄어요.

청크 프리필 토큰 예산 고르기: TTFT와 ITL 사이

청크 프리필은 긴 프롬프트를 토큰 예산(max_num_batched_tokens)만큼 잘라 여러 스텝에 나눠 넣어요. 얼마로 자를지 보려고, 디코드 요청 64개가 도는 중에 16,000토큰 프롬프트가 들어오는 상황을 프리필 어텐션 연산까지 넣어 계산했어요.

토큰 예산(청크 크기)나눠지는 스텝 수그 프롬프트의 프리필 시간다른 사용자의 최악 ITL
51232382ms14.4ms
1,02416359ms27.1ms
2,0488350ms51.3ms
4,0964346ms94.0ms
8,1922344ms186.8ms
자르지 않음1342ms342.4ms
토큰 예산별 긴 프롬프트의 프리필 시간과 다른 요청의 최악 ITL (16,000토큰 · 디코드 64개 동시)
프롬프트 프리필 시간다른 요청 최악 ITL
0100200300400512 · 프롬프트 프리필 시간 382ms512 · 다른 요청 최악 ITL 14.4ms5121024 · 프롬프트 프리필 시간 359ms1024 · 다른 요청 최악 ITL 27.1ms10242048 · 프롬프트 프리필 시간 350ms2048 · 다른 요청 최악 ITL 51.3ms20484096 · 프롬프트 프리필 시간 346ms4096 · 다른 요청 최악 ITL 94ms40968192 · 프롬프트 프리필 시간 344ms8192 · 다른 요청 최악 ITL 187ms8192자르지 않음 · 프롬프트 프리필 시간 342ms자르지 않음 · 다른 요청 최악 ITL 342ms자르지 않음

프리필은 연산에 묶여서 잘게 잘라도 총 시간이 거의 그대로예요. 바뀌는 건 다른 사용자가 겪는 멈칫함이에요.

단위: ms · 자료: H100 SXM 공식 대역폭·연산 성능으로 직접 계산한 이론값(8B bf16, 디코드 문맥 1,500토큰)
표로 보기
구분프롬프트 프리필 시간다른 요청 최악 ITL
51238214.4
102435927.1
204835051.3
409634694
8192344187
자르지 않음342342

잘게 자를수록 긴 프롬프트 자신은 손해를 거의 안 보고(최대 12%), 다른 사용자의 ITL은 크게 좋아져요. 512 아래로 내려가면 스텝의 토큰이 300개 언저리로 줄어 다시 메모리에 묶이면서 손해가 커지기 시작해요.

그런데도 vLLM 최적화 문서는 예산을 키울수록 TTFT가 좋아지고, 처리량이 목적이면 8192보다 크게 두라고 권해요(특히 큰 GPU의 작은 모델). 위 표에 없는 두 가지 때문이에요. 문서상 스케줄러는 디코드를 모두 넣은 뒤 남은 예산으로 프리필을 넣어서, 동시 디코드가 256개면 예산 2048 중 프리필 몫은 1,792토큰뿐이에요. 프롬프트가 몰리면 대기열이 길어져 TTFT가 늘어요. 또 스텝마다 붙는 고정 비용(스케줄링 등)이 스텝 수만큼 쌓여요.

그래서 실용적인 출발점은 이렇게 잡아요.

문서는 청크 프리필을 끈다면 예산이 max_model_len보다 커야 하고, 작으면 서버가 시작할 때 멈출 수 있다고 경고해요. 또 예산을 max_model_len과 같게 두면 예전(V0) 기본 스케줄링과 거의 같아진다고 적고 있어요. 긴 프롬프트 몇 개가 짧은 요청을 계속 밀어내는 게 문제라면 엔진 인자 문서의 --long-prefill-token-threshold로 긴 프롬프트의 한 스텝 몫에 상한을 둘 수 있어요(기본 0은 상한 없음).

프리필·디코드 분리는 언제 값을 하나

DistServe 논문은 프리필과 디코드를 다른 GPU에 두면 TTFT·TPOT 목표 안에서 처리하는 요청이 최대 7.4배, 지킬 수 있는 목표는 12.6배 엄격해진다고 보고했어요. 다만 조건을 따지면 대상이 좁아요.

vLLM 분리 프리필 문서는 이 기능을 실험 단계로 표시하고, 분리 프리필은 처리량을 늘리지 않는다고 분명히 적어요. 얻는 건 TTFT와 ITL을 따로 조정할 수 있다는 점과 ITL 꼬리 지연을 확실하게 누를 수 있다는 점이에요. 청크 프리필로도 같은 목적을 이룰 수 있지만 맞는 청크 크기를 찾기 어려워서, 분리가 더 확실한 방법이라는 설명이에요.

분리하려면 인스턴스가 최소 2개라 H100 기준 월 3,132달러가 6,263달러가 되고, KV 캐시를 옮길 고속 연결도 필요해요. 반면 Sarathi-Serve 논문은 GPU를 나누지 않는 청크 프리필만으로 꼬리 지연 제약 아래 vLLM(당시 버전) 대비 서빙 용량을 Mistral-7B·A100 한 장에서 2.6배 늘렸어요. GPU 한두 장이면 청크 예산 조정이 먼저고, 수십 장 규모에서 ITL p99를 엄격히 지켜야 할 때 분리를 검토하세요.

방식별 비교표

방식출력 100만 토큰당 비용(이 글 계산)ITLTTFT품질 영향필요한 것
요청 하나씩5.91달러가장 짧음(5ms)대기열 길면 매우 김없음없음
정적 배칭1.28~2.51달러짧음묶음이 끝나야 다음 차례없음묶음 크기 결정
연속 배칭, 큰 예산0.17달러긴 프롬프트 때 수백 ms 튐유리배치 구성에 따라 미세한 출력 차이vLLM·TGI 등 추론 서버
연속 배칭 + 작은 예산거의 같음고르게 짧음프롬프트가 몰리면 늘어남위와 같음예산 튜닝
프리필·디코드 분리같은 처리량에 GPU 2배 이상가장 안정적따로 조정위와 같음다중 GPU, 고속 연결, 실험 기능

품질 칸의 "미세한 출력 차이"는 묶이는 요청이 매번 달라 부동소수점 계산 순서가 바뀌면서 생겨요. 정확도 저하는 아니지만 temperature 0에서도 답이 가끔 달라져요. 재현성이 필요하면 vLLM 배치 불변성 문서의 VLLM_BATCH_INVARIANT=1 설정을 볼 수 있어요. 문서상 아직 베타이고 지원 GPU 조건(NVIDIA는 compute capability 8.0 이상)이 있어서, 켜기 전후로 처리량을 함께 재 봐야 해요.

광고
광고

상황별 추천

응답을 사람이 기다리는지, 하루 출력이 GPU 한 장을 채우는지, 수천 토큰 입력이 섞이는지, ITL 목표가 빡빡하고 GPU가 여러 장인지를 차례로 물어 오프라인 엔진·관리형 API·연속 배칭 기본값·프리필 디코드 분리·청크 예산 2048~4096 중 하나로 안내하는 순서도
대부분의 온라인 서비스는 맨 아래 칸, 연속 배칭 + 청크 프리필에서 끝나요

트래픽이 적은 사내 도구. 배칭 방식보다 유휴 시간이 비용을 정해요. 하루 출력 1,000만 토큰이면 한 달 약 3억 400만 토큰인데, H100 한 장 월 3,132달러를 나누면 100만 토큰당 10.30달러예요. 이론 최저인 0.17달러의 60배예요. 이 규모라면 관리형 API나 더 작은 GPU를 먼저 따져 보세요.

채팅형 서비스, 피크 동시 수십~수백 명. 연속 배칭 + 청크 프리필(vLLM V1은 가능하면 기본으로 켜요), 예산 2048~4096에서 시작해요. max_num_seqs를 KV 캐시에 담기는 동시 수보다 크게 잡으면 선점이 생겨 이미 만든 토큰을 다시 계산해요.

RAG·긴 대화 기록처럼 입력이 긴 서비스. 청크 프리필 효과가 가장 커요. 예산을 작게 두되 프롬프트가 몰리는 시간대의 TTFT p99를 같이 보고, 공통 앞부분이 길면 접두사 캐싱도 켜요.

밤새 도는 요약·분류·데이터 생성. 오프라인 엔진(LLM.generate에 목록 전체를 넣기)으로 예산을 크게 잡고 처리량만 봐요. 직접 묶음을 짜는 것보다 엔진에 맡기는 쪽이 싸요.

출력 토큰을 더 빠르게 내야 하는데 동시 요청이 적음. 배칭으로는 얻을 게 없는 구간이에요. 이때는 초안 모델로 토큰을 여러 개씩 검증하는 투기적 디코딩이 사용자 속도를 올리는 쪽이에요.

설정을 정하기 전에 해 볼 계산과 부하 시험

위 표를 내 모델과 GPU로 다시 내려면 다음 정도의 스크립트로 충분해요. 공식 사양서의 대역폭·연산 성능과 config.json의 값만 넣으면 돼요.

def decode_cost(params_b, kv_bytes_per_token, ctx, concurrency,
                bw_tbs=3.35, tflops=989, usd_per_hour=4.29):
    weights = params_b * 1e9 * 2                       # bf16 2바이트
    read_s = (weights + concurrency * ctx * kv_bytes_per_token) / (bw_tbs * 1e12)
    math_s = concurrency * 2 * params_b * 1e9 / (tflops * 1e12)
    step = max(read_s, math_s)
    tok_per_s = concurrency / step
    return step * 1000, tok_per_s, usd_per_hour / (tok_per_s * 3600) * 1e6

for n in (1, 32, 64, 128):
    ms, tps, usd = decode_cost(8.19, 147456, 1500, n)
    print(f"{n:4d}개  ITL {ms:5.2f}ms  초당 {tps:7.0f}토큰  100만 토큰당 {usd:.2f}달러")

계산값은 상한이니 실제 서버에서 다시 재요. vllm bench serve 문서의 --request-rate로 초당 요청 수를, --max-concurrency로 동시 상한을 정하고, --goodput에 ttft:500 tpot:50처럼 목표(ms)를 주면 목표 안에 든 요청만 센 처리량이 나와요. 예산 2048과 8192를 같은 부하로 한 번씩 돌려 goodput이 높은 쪽을 고르면 돼요. 데이터셋은 실제 길이 분포에 맞춰야 해요. 고정 길이로 재면 배칭과 청크 프리필의 효과가 실제보다 작게 나와요.

도입 체크리스트

띄우기 전(입력·출력 길이 분포, 피크 동시 요청 수, TTFT·ITL p99 목표, 월 출력 토큰 추정), 부하 시험(실제 길이 분포, 예산 2048과 8192 비교, goodput 판정, 선점 횟수 0 확인), 운영 지표(대기 요청 수, KV 캐시 사용률, TTFT를 대기와 처리로 나누기, 클라이언트 동시 전송)를 세 칸으로 나눈 체크리스트
왼쪽 칸 숫자가 없으면 가운데 칸 결과를 판단할 기준이 없어요
  1. 입력·출력 길이 분포를 평균과 p95로 적어요. 배칭 손해, 청크 필요성, KV 용량이 모두 여기서 나와요.
  2. 피크 동시 요청 수(초당 요청 × 평균 처리 시간)와 월 출력 토큰을 추정해요. 월 출력 ÷ 이론 처리량으로 낸 사용률이 10%도 안 되면 자체 호스팅부터 다시 따져요.
  3. TTFT·ITL 목표를 p99로 정해요. p50에는 긴 프롬프트가 만드는 멈칫함이 숨어요.
  4. 예산 두 값으로 부하 시험을 하고 goodput으로 고르세요. 다른 설정은 고정하고 하나만 바꿔요.
  5. 운영 지표를 걸어 둬요. vLLM 지표 문서의 vllm:num_requests_waiting(대기 요청), vllm:kv_cache_usage_perc(KV 사용률), vllm:num_preemptions(선점), vllm:request_queue_time_seconds(대기 시간), vllm:time_to_first_token_seconds, vllm:inter_token_latency_seconds를 대시보드에 올려요. TTFT가 나쁠 때 대기 시간이 대부분이면 증설, 처리 시간이 대부분이면 예산 조정이 답이에요.
  6. 클라이언트는 요청을 모으지 말고 생기는 대로 동시에 보내요. 서버가 스텝마다 묶으니 클라이언트에서 10개씩 모으면 대기 시간만 늘어요.
광고
광고

자주 묻는 질문

max_num_batched_tokens를 얼마로 시작하면 되나요?

글자가 흘러나오는 채팅 화면이면 2048~4096, 응답을 한꺼번에 받는 백엔드면 8192 이상, 오프라인 일괄 처리면 16384 이상에서 시작하는 게 무난해요. 2048이면 16,000토큰 프롬프트가 들어와도 다른 사용자의 최악 ITL이 약 51ms예요(이 글 계산). 최종 값은 부하 시험의 goodput으로 정하세요.

동시 요청을 늘릴수록 무조건 싸지나요?

내려가는 폭이 줄고 사용자 속도는 떨어져요. 128개에서 256개로 늘리면 비용은 약 18%만 내려가고 사용자 속도는 초당 75토큰에서 46토큰이 돼요. KV 캐시에 다 안 들어가면 선점이 생겨 처리량이 오히려 떨어져요.

청크 프리필을 켜면 긴 프롬프트의 첫 토큰이 많이 늦어지나요?

연산에 묶인 프리필은 잘게 나눠도 총 계산량이 거의 같아서, 이 글 계산에서는 16,000토큰 프롬프트를 512씩 잘라도 342ms가 382ms로 12% 늘었을 뿐이에요. TTFT가 크게 늘어나는 건 디코드가 예산을 먼저 가져가거나 프롬프트가 몰려 대기열이 길어질 때라, 대기 시간과 처리 시간을 나눠 봐야 해요.

프리필과 디코드를 다른 GPU로 나누면 더 많이 처리할 수 있나요?

vLLM 문서는 분리 프리필이 처리량을 늘리지 않는다고 적고 있어요. 얻는 건 TTFT와 ITL을 따로 조정하는 자유와 ITL 꼬리 지연의 안정성이에요. 최소 두 인스턴스가 필요해 GPU 비용이 늘고 기능도 실험 단계라, GPU 여러 장에서 엄격한 ITL 목표를 지켜야 할 때 검토하세요.

트래픽이 적은데 자체 호스팅이 API보다 쌀 수 있나요?

GPU는 놀아도 요금이 나가서 사용률이 낮으면 배칭 이득이 사라져요. 하루 출력 1,000만 토큰이면 H100 한 장 기준 100만 토큰당 10.30달러로 꽉 채운 이론값의 60배예요. 사용률부터 계산해 보세요.

정리

더 깊이 읽기

이 글은 실무에서 판단할 때 필요한 것 위주로 정리했어요. 같은 주제의 내부 동작 원리는 devboi 기술 블로그의 LLM 추론 서버 원리 — 연속 배칭·KV 캐시·청크 프리필에서 도식과 코드로 단계별로 풀었어요.

참고한 자료

#LLM 서빙 배칭#연속 배칭 비용#청크 프리필 설정#max_num_batched_tokens 값#vLLM TTFT ITL 튜닝#LLM 추론 GPU 비용 계산#프리필 디코드 분리#LLM 자체 호스팅 비용
← 이전 글코딩 에이전트 비용 계산, 한 번 생성·고정 파이프라인·도구 루프 고르는 법다음 글 →NestJS 프로바이더 스코프 고르기, 요청 스코프 비용과 DI 에러 점검 순서
광고

더 둘러보기

💻 개발자 다른 도구

🔥 많이 찾는 도구

🔮 재미로 한 번 더

📝 읽어 볼 만한 글

글 전체 보기 →