LLM 추론의 핵심 엔진인 vLLM과 Text Generation Inference를 아키텍처, 성능, 기능 측면에서 심층 비교하고 적합한 선택 기준을 제시합니다.
Hugging Face Transformers 라이브러리로 모델을 로드하고 model.generate()를 호출하면 추론 자체는 가능합니다. 그러나 이 방식으로 프로덕션 서비스를 운영하면 심각한 문제에 직면하게 됩니다.
첫째, 요청을 하나씩 순차적으로 처리하므로 GPU 활용률이 극히 낮습니다. 최신 GPU는 수천 개의 CUDA 코어를 보유하고 있지만, 단일 요청을 처리할 때는 이 코어의 일부만 활용됩니다. 둘째, KV 캐시 관리가 비효율적입니다. 기본 Transformers 구현은 각 요청에 대해 연속된 메모리 블록을 할당하며, 이는 심각한 메모리 단편화를 초래합니다. 셋째, HTTP 서버, 요청 큐, 스트리밍 응답 등 서비스 운영에 필요한 인프라가 전혀 제공되지 않습니다.
모델 서빙 프레임워크는 이러한 문제를 해결하기 위해 설계된 전문 소프트웨어입니다. 추론 엔진 최적화, 요청 스케줄링, API 서버, 모니터링 등을 통합적으로 제공합니다.
vLLM(Virtual Large Language Model)은 UC Berkeley에서 개발한 오픈소스 LLM 서빙 엔진입니다. 2023년 PagedAttention 논문과 함께 공개되었으며, 높은 처리량과 효율적인 메모리 관리를 핵심 강점으로 내세웁니다.
vLLM의 핵심 혁신은 PagedAttention입니다. 운영체제의 가상 메모리(Virtual Memory)와 페이징(Paging) 기법에서 영감을 받은 이 방식은, KV 캐시를 고정 크기의 블록으로 나누어 비연속적으로 저장합니다.
기존 방식에서는 각 요청의 KV 캐시가 연속된 메모리 공간을 차지해야 했습니다. 최대 출력 길이에 맞춰 메모리를 사전 할당하므로, 실제 사용량보다 훨씬 많은 메모리가 낭비되었습니다. 예를 들어 최대 2048 토큰을 지원하는 서비스에서 실제 출력이 100 토큰이라면, 나머지 1948 토큰에 해당하는 메모리는 완전히 낭비됩니다.
기존 KV 캐시 할당 (연속 메모리):
요청1: [###-------] (30% 사용, 70% 낭비)
요청2: [######----] (60% 사용, 40% 낭비)
요청3: [할당 불가 - 연속 공간 부족]
PagedAttention (블록 단위):
요청1: [블록1][블록2][블록3]
요청2: [블록4][블록5][블록6][블록7][블록8]
요청3: [블록9][블록10] <-- 비연속 공간도 활용 가능PagedAttention은 이 낭비를 거의 제거합니다. 각 블록은 독립적으로 할당되고 해제되므로, 메모리 단편화가 발생하지 않습니다. vLLM 팀의 벤치마크에 따르면, 이 기법만으로 기존 대비 2~4배 높은 처리량을 달성할 수 있습니다.
vLLM은 다음과 같은 핵심 기능을 제공합니다.
연속 배칭(Continuous Batching): 생성이 완료된 요청을 즉시 배치에서 제거하고 대기 중인 요청을 투입합니다. 정적 배칭 대비 처리량이 크게 향상됩니다.
텐서 병렬 처리(Tensor Parallelism): 단일 모델을 여러 GPU에 분산하여 대규모 모델을 서빙할 수 있습니다. --tensor-parallel-size 옵션으로 간단하게 설정 가능합니다.
OpenAI 호환 API: /v1/chat/completions, /v1/completions 등 OpenAI API와 동일한 인터페이스를 제공합니다. 기존 OpenAI SDK 코드를 수정 없이 사용할 수 있습니다.
다양한 양자화 지원: GPTQ, AWQ, SqueezeLLM, FP8 등 주요 양자화 포맷을 모두 지원합니다.
vLLM의 설치와 실행은 매우 직관적입니다.
pip install vllmvllm serve meta-llama/Llama-3.1-8B-Instruct \
--host 0.0.0.0 \
--port 8000 \
--max-model-len 4096 \
--gpu-memory-utilization 0.9 \
--dtype auto서버가 시작되면 OpenAI 호환 API로 요청을 보낼 수 있습니다.
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:8000/v1",
api_key="not-needed",
)
response = client.chat.completions.create(
model="meta-llama/Llama-3.1-8B-Instruct",
messages=[
{"role": "user", "content": "Kubernetes란 무엇인가요?"}
],
max_tokens=512,
temperature=0.7,
stream=True,
)
for chunk in response:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="")vllm serve meta-llama/Llama-3.1-70B-Instruct \
--host 0.0.0.0 \
--port 8000 \
--tensor-parallel-size 4 \
--max-model-len 8192 \
--gpu-memory-utilization 0.92 \
--max-num-seqs 256 \
--max-num-batched-tokens 8192 \
--enable-prefix-caching \
--disable-log-requests \
--dtype bfloat16각 옵션의 의미를 살펴보겠습니다.
--tensor-parallel-size 4: 모델을 4개 GPU에 분산합니다. 70B 모델은 최소 4x A100 80GB가 필요합니다.--max-model-len 8192: 최대 컨텍스트 길이를 제한합니다. 더 긴 컨텍스트는 더 많은 메모리를 소비합니다.--gpu-memory-utilization 0.92: GPU 메모리의 92%를 사용합니다. 나머지 8%는 안전 마진으로 남깁니다.--max-num-seqs 256: 동시에 처리할 수 있는 최대 시퀀스 수입니다.--enable-prefix-caching: 동일한 시스템 프롬프트를 공유하는 요청의 KV 캐시를 재사용합니다.Text Generation Inference(TGI)는 Hugging Face에서 개발한 LLM 서빙 프레임워크입니다. Rust와 Python을 결합하여 구현되었으며, Hugging Face 생태계와의 긴밀한 통합이 특징입니다.
TGI는 Rust로 작성된 고성능 HTTP 서버와 Python으로 작성된 모델 추론 엔진으로 구성됩니다. Rust 서버가 요청 수신, 토큰화, 스케줄링을 담당하고, Python 엔진이 실제 GPU 추론을 수행합니다.
TGI 내부 아키텍처:
[gRPC/HTTP 요청]
|
v
[Rust 라우터/서버]
|
+---> 토큰화 (Rust)
+---> 요청 검증
+---> 배칭 스케줄러
|
v
[Python 추론 엔진]
|
+---> Flash Attention
+---> 연속 배칭
+---> 양자화 지원
|
v
[스트리밍 응답 (SSE)]TGI도 연속 배칭을 지원하며, Flash Attention 2를 기본으로 사용합니다. PagedAttention과는 다른 접근 방식이지만, 유사한 수준의 메모리 효율성을 달성합니다.
Flash Attention 2: 메모리 효율적인 어텐션 연산을 제공하여 긴 시퀀스의 추론 속도를 크게 향상시킵니다.
토큰 스트리밍: SSE(Server-Sent Events)를 통한 실시간 토큰 스트리밍을 기본 지원합니다.
워터마킹: 생성된 텍스트에 보이지 않는 워터마크를 삽입하여 AI 생성 텍스트를 식별할 수 있습니다.
구조화된 출력: JSON Schema를 지정하면 해당 스키마에 맞는 출력만 생성하도록 제약할 수 있습니다.
Hugging Face Hub 통합: 모델 ID만 지정하면 자동으로 모델을 다운로드하고 최적 설정을 적용합니다.
TGI는 Docker 이미지를 통한 실행이 권장됩니다.
docker run --gpus all --shm-size 1g \
-p 8080:80 \
-v $HOME/.cache/huggingface:/data \
ghcr.io/huggingface/text-generation-inference:latest \
--model-id meta-llama/Llama-3.1-8B-Instruct \
--max-input-tokens 4096 \
--max-total-tokens 8192 \
--max-batch-prefill-tokens 4096TGI API는 OpenAI 호환 엔드포인트와 자체 엔드포인트를 모두 제공합니다.
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:8080/v1",
api_key="not-needed",
)
response = client.chat.completions.create(
model="meta-llama/Llama-3.1-8B-Instruct",
messages=[
{"role": "user", "content": "Docker 컨테이너의 장점은?"}
],
max_tokens=512,
stream=True,
)import requests
response = requests.post(
"http://localhost:8080/generate",
json={
"inputs": "Kubernetes의 핵심 구성 요소를 설명해주세요.",
"parameters": {
"max_new_tokens": 512,
"temperature": 0.7,
"top_p": 0.95,
}
}
)
print(response.json()["generated_text"])docker run --gpus all --shm-size 4g \
-p 8080:80 \
-v /models:/data \
ghcr.io/huggingface/text-generation-inference:latest \
--model-id meta-llama/Llama-3.1-70B-Instruct \
--num-shard 4 \
--max-input-tokens 4096 \
--max-total-tokens 8192 \
--max-batch-prefill-tokens 8192 \
--max-concurrent-requests 128 \
--quantize gptq \
--dtype bfloat16--num-shard 4: 모델을 4개 GPU에 샤딩합니다 (텐서 병렬 처리).--max-concurrent-requests 128: 동시 처리 가능한 최대 요청 수입니다.--quantize gptq: GPTQ 양자화를 적용합니다.--shm-size 4g: 공유 메모리 크기를 설정합니다. 멀티 GPU 통신에 필요합니다.두 프레임워크의 특성을 항목별로 비교해 보겠습니다.
처리량(Throughput) 측면에서 vLLM은 PagedAttention 덕분에 일반적으로 우위를 보입니다. 특히 동시 요청이 많은 환경에서 메모리 효율성의 차이가 두드러집니다. 최근 벤치마크에서 vLLM은 TGI 대비 약 1.3~1.8배 높은 처리량을 보여주었습니다.
지연 시간(Latency) 측면에서는 두 프레임워크의 차이가 크지 않습니다. 단일 요청의 TTFT(Time To First Token)와 TPOT(Time Per Output Token)는 유사한 수준입니다.
벤치마크 결과 (Llama-3.1-8B, A100 80GB, 동시 요청 32):
처리량(tok/s) TTFT(ms) TPOT(ms)
vLLM 2,840 45 28
TGI 2,150 52 31
* 실제 성능은 모델, 하드웨어, 워크로드 패턴에 따라 달라집니다.vLLM은 Llama, Mistral, Qwen, Gemma, Phi, Falcon 등 대부분의 인기 모델을 지원합니다. TGI 역시 유사한 범위의 모델을 지원하며, Hugging Face Hub에 등록된 모델과의 호환성이 뛰어납니다.
멀티모달(Multimodal) 모델 지원에서는 vLLM이 더 빠르게 새로운 모델을 지원하는 경향이 있습니다. LLaVA, Qwen-VL 등의 비전-언어 모델을 vLLM에서 서빙할 수 있습니다.
TGI는 Docker 기반 배포가 기본이며, Hugging Face 인프라와의 통합이 용이합니다. Hugging Face Inference Endpoints를 사용하면 TGI 기반의 서빙을 클릭 몇 번으로 설정할 수 있습니다.
vLLM은 pip 설치를 통한 직접 실행과 Docker 배포 모두 지원합니다. API 서버의 설정 옵션이 더 세밀하며, 커스터마이징 여지가 넓습니다.
vLLM은 활발한 오픈소스 커뮤니티와 빠른 개발 속도를 자랑합니다. GitHub Star 수와 컨트리뷰터 수 모두 빠르게 성장하고 있으며, 새로운 최적화 기법과 모델 지원이 신속하게 추가됩니다.
TGI는 Hugging Face라는 강력한 기업의 지원을 받으며, 안정성과 엔터프라이즈 지원에 강점이 있습니다.
2025년 기준으로 vLLM이 LLM 서빙 분야의 사실상 표준으로 자리잡아가고 있습니다. 그러나 TGI도 꾸준히 개선되고 있으며, 특히 Hugging Face 생태계를 깊이 사용하는 팀에게는 여전히 좋은 선택입니다.
vLLM과 TGI 외에도 주목할 만한 서빙 프레임워크들이 있습니다.
NVIDIA가 개발한 범용 추론 서버입니다. LLM뿐만 아니라 컴퓨터 비전, 음성 인식 등 다양한 모델을 서빙할 수 있습니다. TensorRT-LLM 백엔드를 통해 LLM 서빙을 지원하며, NVIDIA GPU에서 최적의 성능을 발휘합니다. 다만 설정이 복잡하고 학습 곡선이 가파릅니다.
SGLang은 효율적인 LLM 프로그래밍을 위한 프레임워크입니다. RadixAttention이라는 독자적인 KV 캐시 재사용 기법을 도입하여, 공통 프리픽스(Prefix)를 가진 요청들의 처리 속도를 크게 향상시켰습니다. 구조화된 출력 생성에도 강점이 있습니다.
로컬 환경에서 LLM을 간편하게 실행하기 위한 도구입니다. 프로덕션 서빙보다는 개발과 테스트 용도에 적합합니다. ollama run llama3.1과 같은 간단한 명령으로 모델을 실행할 수 있으며, Docker와 유사한 모델 레지스트리를 제공합니다.
프레임워크 선택은 다음 기준에 따라 결정하는 것을 권장합니다.
vLLM을 선택하는 경우:
TGI를 선택하는 경우:
Triton + TensorRT-LLM을 선택하는 경우:
모델 서빙 프레임워크는 AI 서비스 배포 파이프라인의 핵심 엔진입니다. vLLM의 PagedAttention과 TGI의 Flash Attention은 각각 다른 접근 방식으로 LLM 추론의 효율성을 극대화합니다.
이 시리즈에서는 vLLM을 기본 서빙 프레임워크로 사용하되, 각 장에서 TGI 설정도 함께 안내하겠습니다. 다음 장에서는 모델 자체를 최적화하는 기법인 양자화, 배칭 전략, KV 캐시 튜닝을 자세히 다루겠습니다.
이 글이 도움이 되셨나요?
LLM 추론 성능을 극대화하기 위한 양자화 기법, 배칭 전략, KV 캐시 튜닝 방법을 실전 예제와 함께 체계적으로 다룹니다.
AI 모델을 프로덕션에 배포하기 위한 전체 파이프라인을 조망하고, 전통적 웹 서비스와 다른 AI 서비스만의 고유한 배포 과제를 분석합니다.
GPU 지원 Docker 컨테이너로 AI 서비스를 패키징하는 방법을 다루며, NVIDIA Container Toolkit 설정부터 멀티 스테이지 빌드까지 실전 기법을 소개합니다.