TT Lab
블로그

한국어

시작하기
블로그

블로그

vLLM 기능 지도: 무엇이 있고, 언제 이득이며, 판마다 무엇이 바뀌었나

상태: 초안 (2026-10-27), 일부 실측. 기능 목록과 옵션은 vLLM 0.32.0 의 공식 문서(저장소 docs/)와 0.8.0 부터 0.32.0 까지의 릴리스 노트를 2026-10-27 에 직접 열어 확인했습니다. 실측은 0.31.0(2026-10-05 출시) 공식 컨테이너로 했습니다. 0.32.0 이미지는 새로 내려받아야 해서 쓰지 않았고, 두 판의 문서가 다른 곳은 글마다 적었습니다. 2026-10-27 추가. 승인을 받아 vLLM 0.32.0 이미지와 Qwen3-0.6B·Qwen3-0.6B-GPTQ-Int8·Qwen3-4B-AWQ·Qwen3-VL-2B-Instruct 를 받아 다시 쟀습니다. 3-1절에 두 판의 비교를, 각 편에 「2026-10-27 재측정」 절을 더했습니다. 0.31.0 수치는 지우지 않았습니다. 작성 규칙: 실측 데이터가 기본이고, 못 잰 것은 「미실측」, 확인하지 못한 것은 「미확인」으로 표시합니다.

목차

1. 이 시리즈가 다루는 것

vLLM 은 언어 모델을 서빙하는 엔진입니다. PagedAttention(Kwon 외, SOSP 2023)으로 시작했지만, 지금은 스케줄러, 캐시, 디코딩 가속, 출력 강제, 양자화, 여러 GPU, 운영 도구까지 기능이 아주 많습니다. 이 사이트에는 이미 vLLM 을 다룬 글이 여럿 있습니다.

이 시리즈는 그 글들이 다루지 않은 기능을 채우는 데 집중합니다. 겹치는 기능은 짧게 정리하고 이전 글로 잇습니다.

편 다루는 기능 실측
1 기능 지도, 판별 변화 요약
2 연속 배칭, chunked prefill, 접두사 캐시, cache_salt 반복 측정, 기능을 끈 기준선
3 추측 디코딩(n-gram, EAGLE, MTP, suffix) n-gram 두 구현, 제안 길이, 동시성
4 구조화 출력(xgrammar, guidance) 올바름, 첫 요청 비용, 토큰당 비용
5 도구 호출(파서, tool_choice, strict) 스키마 준수율
6 양자화(FP8, AWQ, GPTQ, KV FP8) 온라인 FP8, 퍼플렉서티
7 KV 오프로딩과 분리 서빙 CPU 오프로딩
8 잠자기 모드, 기동 시간, /metrics, 인증 잠자기, 컴파일 캐시, 경로별 인증
9 병렬화, 멀티모달, 풀링, LoRA 임베딩·재순위만

2. 기능 지도

「아끼는 것」은 그 기능이 줄이는 비용, 「이득 조건」은 실측이나 문서에서 효과가 난 조건입니다.

기능 원리(논문) 켜는 옵션(0.31·0.32) 기본 아끼는 것 이득 조건 이득이 없는 조건
PagedAttention KV 를 블록으로(Kwon 외, SOSP 2023) 항상 켜짐 KV 메모리 낭비 요청 길이가 제각각일 때 해당 없음
연속 배칭 걸음 단위 스케줄(Yu 외, OSDI 2022) --max-num-seqs 256 빈 배치 자리 동시 요청이 많을 때 요청이 하나뿐일 때
chunked prefill 프리필을 나눠 디코드와 섞음(Sarathi) --max-num-batched-tokens 켜짐, 2,048(70GB 미만 GPU 의 서버) 디코드 정지 시간 긴 입력과 디코드가 섞일 때 짧은 입력만 올 때
접두사 캐시 블록 해시로 KV 재사용 --enable-prefix-caching 켜짐 프리필 계산 공통 앞부분이 길고 자주 올 때 앞부분이 매번 다를 때
cache_salt 첫 블록 해시에 소금 요청의 cache_salt 없음 테넌트 사이 타이밍 누출 여러 고객이 한 엔진을 쓸 때 단일 사용자
추측 디코딩 초안을 한 번에 검증(Leviathan 외, ICML 2023) --speculative-config 꺼짐 디코드 걸음 수 동시성이 낮고 출력이 예측 가능할 때 높은 동시성, 무작위 출력
구조화 출력 토큰 마스크(XGrammar, MLSys 2025) response_format, structured_outputs auto 형식 오류 기계가 읽을 출력 자유 글
도구 호출 파서 + 구조 태그 --enable-auto-tool-choice --tool-call-parser 꺼짐 호출 파싱 오류 에이전트 도구를 모르는 모델
가중치 양자화 FP8, AWQ, GPTQ --quantization 없음 가중치 메모리·읽기 동시성이 낮을 때, 큰 모델 큰 배치
KV 양자화 KV FP8 --kv-cache-dtype fp8 auto(모델 정밀도) KV 메모리 KV 가 모자랄 때 KV 가 넉넉할 때
멀티 LoRA 어댑터 묶음 계산(Punica, S-LoRA) --enable-lora --max-loras 꺼짐 모델 벌 수 어댑터가 여럿일 때 어댑터가 하나일 때
KV 오프로딩 KV 커넥터, CPU 계층 --kv-offloading-size 꺼짐 밀려난 접두사의 재계산 GPU KV 가 모자라고 재사용이 있을 때 재사용이 없을 때
분리 서빙 프리필·디코드 분리(DistServe, OSDI 2024) --kv-transfer-config(NIXL 등) 꺼짐 꼬리 ITL 빠른 GPU 간 연결 느린 연결, 처리량 목표
병렬화 TP·PP·DP·EP Megatron-LM 등 --tensor-parallel-size 등 1 GPU 한 장의 한계 모델이 안 들어갈 때 모델이 들어갈 때
잠자기 모드 CuMem 할당기 --enable-sleep-mode + 개발 모드 꺼짐 재기동 시간 GPU 를 번갈아 쓸 때 상시 서빙
멀티모달·풀링 인코더, LAST/CLS 풀링 모델에 따름, --runner pooling 모델에 따름 별도 서버 같은 엔진으로 통일 특화 엔진이 더 빠를 때

OpenAI 호환 API(/v1/completions, /v1/chat/completions, /v1/embeddings, /v1/responses 등)와 /metrics 는 기능이라기보다 이 모든 것의 입구라서 표에서 뺐습니다. 이 시리즈의 모든 측정이 이 API 로 했고, 지표는 8편에 모았습니다.

기능끼리 함께 못 쓰는 경우도 있습니다. 0.32.0 문서의 호환 표에서 추측 디코딩은 LoRA, 풀링, 프롬프트 임베딩 입력과 함께 쓸 수 없습니다(❌). 실측 중에도 0.31.0 은 n-gram 추측 디코딩을 켜면 「비동기 스케줄을 끈다」, 「Model Runner V2 가 아직 ngram 을 지원하지 않아 V1 실행기로 돌아간다」는 경고를 냈습니다.

3. 직접 잰 값 요약

모두 8GB급 노트북 GPU(Ada 세대) 한 장, vLLM 0.31.0, Qwen3-Reranker-0.6B(bf16, 재순위용으로 미세 조정된 0.6B 인과 언어 모델), 컨테이너 메모리 한도 4GiB 또는 4.5GiB 에서 쟀습니다. 같은 조건을 서너 번 반복해 중앙값을 쓰고, 서버를 띄운 뒤의 첫 묶음은 예열로 따로 뗐습니다.

기능 조건 결과(중앙값)
연속 배칭 동시 16, 입력 256·출력 128 한 번에 하나 174.6 tok/s → 기본 1,683.1 tok/s(9.6배)
chunked prefill 디코드 중 3,700토큰 입력 디코드 최대 정지 512토큰 청크 35.6ms, 기본 109.8ms, 청크 끔 197.6ms
접두사 캐시 3,200토큰 공통 첫 토큰 174.7ms → 18.9ms, 끄면 173.8ms
cache_salt 같은 접두사, 다른 소금 다른 소금은 캐시 0토큰, 173.7ms
n-gram 추측 디코딩 동시 1, 글 베끼기 176.4 → 704.1 tok/s(제안 4개, 4.0배), 제안 8개 1,117.0 tok/s(6.3배), 수락률 96% 이상
n-gram 추측 디코딩 동시 1, 무작위 출력 프롬프트 셋 중 수락률 낮은 하나는 10% 느려짐(171.4 → 153.6 tok/s). 동시 32 에서는 처리량 14% 감소
구조화 출력 JSON 스키마, 동시 16 올바른 JSON 46/48(틀린 2개는 길이 초과), 없으면 0/48. 첫 요청 446ms(xgrammar)
도구 호출 required, strict 없음/있음 스키마 준수 0/5 → 5/5, 값은 엉뚱함
FP8 온라인 양자화 동시 1/16/64 처리량 1.36/1.24/1.08배, 가중치 1.12 → 0.71GiB
KV CPU 오프로딩 밀려난 1,600토큰 접두사 다시 계산 77.3ms → CPU 에서 35.1ms(GPU 적중 14.0ms)
잠자기 모드 2단계, 1단계 2단계: GPU 6,168 → 606MiB, 깨우기 0.39초(재기동 32초), 출력 동일. 1단계: 컨테이너 OOM 두 번
기동 시간 같은 설정 재기동 65초 → 32초(컴파일 캐시)
인증 --api-key /v1/* 401, /invocations 200(생성 실행)
임베딩·재순위 64문장, 32문서 371.8ms, 33.9ms

재지 못한 것은 텐서·파이프라인·데이터·전문가 병렬(GPU 한 장), 분리 서빙(같은 이유), EAGLE·MTP·suffix 추측 디코딩입니다. EAGLE 은 초안 가중치(피클 형식에 자체 라이선스), suffix 는 추가 패키지가 필요해 받지 않기로 했습니다. 처음 판에서 미실측이던 멀티모달 입력과 AWQ·GPTQ 는 3-1절의 재측정에서 쟀습니다.

3-1. 2026-10-27 재측정: 0.32.0 과 대화 모델

기능 2026-10-27 0.31.0 측정(재순위 0.6B) 0.32.0 재측정
연속 배칭·청크·접두사 캐시 9.6배, 109.8ms, 174.7 → 18.9ms 같은 모델로 1.5% 안에서 같음(1,683.6 tok/s, 108.2ms, 175.2 → 18.9ms)
인증(/invocations) 키 없이 200 키 없이 200(그대로)
잠자기 2단계·1단계 깨우기 0.39초, 1단계 컨테이너 OOM 깨우기 0.41초, 1단계 다시 OOM
n-gram 추측 디코딩 베끼기 4.0배, 탐욕 출력 10/12 같음, KV 23% 감소 Qwen3-0.6B: 베끼기 3.7배, 코드 돌려주기 3.1배, 설명하기 0.97배(수락 3%), 탐욕 출력 12/12 같음, KV 2% 감소(V2 실행기)
구조화 출력 강제 없으면 올바른 JSON 0/48 Qwen3-0.6B: 강제 없어도 값은 18/18 맞았지만 코드 울타리 때문에 바로 읽힘 0/18, 강제하면 18/18
도구 호출 strict 없으면 스키마 준수 0/5 Qwen3-0.6B·GPTQ·4B AWQ: auto 를 포함해 36/36 모두 맞는 도시·단위
양자화 FP8 1.36배 Qwen3-0.6B: FP8 1.37배, GPTQ 8비트 1.40배(퍼플렉서티 -1.4%·+1.6%). 4B AWQ 는 8GB 에서 초당 80토큰
멀티모달 미실측 VL-2B 기본 설정은 KV -0.07GiB 로 기동 실패, 크기 힌트로 KV 2.13GiB. 896px 이미지 808토큰·첫 토큰 238ms, 같은 이미지 다시 32.7ms. 기본 설정은 내부 주소를 실제로 받아 옴

이 측정의 한계

4. 판마다 바뀐 것

vLLM 은 대략 2주마다 판을 냅니다. 이전 글을 읽거나 예전 설정을 옮길 때 걸리는 변화만 골랐습니다(릴리스 노트에서 확인).

판 바뀐 것
0.8.0 V1 엔진이 기본이 됨
0.10.0 V0 엔진 코드 정리 시작(V0 의 추측 디코딩 작업자 등 제거)
0.11.0 V0 엔진 완전 제거. CPU KV 오프로딩(LRU) 도입. 접두사 캐시 해시 기본이 sha256(문서 기준)
0.12.0 guided_json 등 guided_* 요청 필드 제거, structured_outputs 로 통일
0.14.0 비동기 스케줄(엔진의 스케줄과 GPU 실행을 겹침)이 기본
0.19.0 범용 CPU KV 오프로딩(정책 교체 가능)
0.21.0 xgrammar 구조 태그로 strict 도구 호출
0.28.0 큰 GPU 의 max_num_batched_tokens 기본 8,192 → 16,384
0.29.0 Model Runner V2 가 모든 모델의 기본
0.31.0 온라인 양자화 --quantization fp8 이 fp8_per_tensor 로 넘어감(실측에서 경고 확인)
0.32.0 max_tokens 를 문맥에서 미리 빼지 않음(긴 프롬프트가 더는 거절되지 않음). 기본 CORS 가 「허용 없음」. 캐스케이드 어텐션 제거. Python 3.10 지원 종료. 64단계 넘게 중첩된 JSON 스키마 거절. MRV2 에 GPU n-gram 제안기

V0 에서 V1 으로 오면서 사라진 기능도 있습니다. 0.32.0 의 V1 안내서는 best_of, 요청별 로짓 처리기, GPU↔CPU KV 교환(선점 시 스왑), 요청별 구조화 출력 백엔드를 「제거됨」으로 적습니다. V1 의 선점은 스왑이 아니라 다시 계산(RECOMPUTE)이 기본입니다.

5. 어디서부터 볼까

참고

로그인하면 좋아요를 누를 수 있습니다

댓글

아직 댓글이 없습니다.

로그인하면 댓글을 쓸 수 있습니다