- Authors
- Name
- VLM 서빙이 텍스트 전용 LLM 서빙과 다른 이유
- 주요 VLM 모델 비교
- 서빙 프레임워크 비교: vLLM vs SGLang vs LMDeploy
- vLLM으로 VLM 서빙하기: 단계별 구현
- 이미지 전처리 파이프라인 최적화
- VLM 양자화 전략
- ViT Data Parallel + LLM Tensor Parallel 하이브리드 전략
- 프로덕션 모니터링과 메트릭
- 장애 사례와 복구 절차
- 성능 벤치마크 가이드
- 운영 체크리스트
- 요약
- 참고 자료

VLM 서빙이 텍스트 전용 LLM 서빙과 다른 이유
비전-언어 모델(Vision-Language Model, VLM)은 이미지 인코더(ViT)와 언어 디코더(LLM)를 결합한 아키텍처다. 텍스트 전용 LLM 서빙에서는 토큰 시퀀스만 처리하면 되지만, VLM 서빙에서는 이미지 전처리, 비전 인코더 추론, 크로스모달 프로젝션, 언어 디코더 생성이라는 네 단계 파이프라인을 관리해야 한다.
이 구조적 차이가 서빙 엔지니어링에 미치는 영향은 크다.
- 메모리 이중 부담: ViT 인코더가 추가로 GPU 메모리를 소비한다. Qwen2.5-VL-72B의 경우 언어 디코더만 약 144GB(BF16)인데, ViT 인코더가 추가로 수 GB를 점유한다.
- TTFT(Time-To-First-Token) 증가: 이미지를 패치로 분할하고 인코더를 통과시키는 데 수백 ms가 소요되며, 이 지연이 언어 디코더의 prefill 이전에 발생한다.
- 배치 효율 저하: 이미지 해상도가 요청마다 다르면 패치 수가 달라져 배칭이 비효율적이다.
- KV Cache 크기 급증: 이미지 토큰이 수백~수천 개 추가되므로, 동일 컨텍스트 길이 대비 KV Cache 사용량이 크게 늘어난다.
이 글에서는 2025-2026년 기준 프로덕션 환경에서 VLM을 효율적으로 서빙하기 위한 아키텍처, 프레임워크 선택, 최적화 기법, 운영 패턴을 다룬다.
주요 VLM 모델 비교
서빙 전략은 모델 아키텍처에 따라 달라진다. 현재 프로덕션에서 주로 사용되는 오픈소스 VLM을 비교한다.
| 모델 | 파라미터 | 아키텍처 | 비전 인코더 | 최소 GPU 요구(BF16) | 특징 |
|---|---|---|---|---|---|
| Qwen2.5-VL-7B | 7B | Dense | ViT-600M | 1x A100 40GB | 동적 해상도, 비디오 지원 |
| Qwen2.5-VL-72B | 72B | Dense | ViT-600M | 4x A100 80GB | 고성능 범용, TP4 권장 |
| Qwen3-VL-235B-A22B | 235B(A22B) | MoE | ViT | 8x A100 80GB | MoE 기반, Expert Parallel 필요 |
| InternVL2.5-78B | 78B | Dense | InternViT-6B | 4x A100 80GB | 6B 대형 비전 인코더 |
| InternVL3 | 다양 | Dense/MoE | InternViT | 모델별 상이 | 최신 SOTA급 멀티모달 |
| LLaVA-OneVision | 7B/72B | Dense | SigLIP | 1~4x A100 | 멀티이미지, 비디오 지원 |
선택 기준은 명확하다. 단일 GPU로 빠르게 배포해야 하면 7B급, 품질이 최우선이면 72B+ Dense, 비용과 품질의 균형이 필요하면 MoE 모델을 선택한다.
서빙 프레임워크 비교: vLLM vs SGLang vs LMDeploy
VLM 서빙을 지원하는 주요 프레임워크 세 가지를 프로덕션 관점에서 비교한다.
| 기능 | vLLM (v0.8+) | SGLang (v0.4+) | LMDeploy (v0.7+) |
|---|---|---|---|
| 멀티모달 지원 | 이미지/비디오/오디오 | 이미지/비디오 | 이미지/비디오 |
| OpenAI API 호환 | 완전 지원 | 완전 지원 | 부분 지원 |
| 인코더 캐싱 | V1에서 GPU 캐시 | RadixAttention 활용 | TurboMind 엔진 |
| ViT DP + LLM TP | 지원 | 미지원 | 지원 |
| 양자화 | AWQ, GPTQ, FP8 | AWQ, GPTQ | W4A16, KV 양자화 |
| Continuous Batching | 지원 | 지원 | 지원(Persistent Batch) |
| 멀티턴 캐시 | Prefix Caching | RadixTree(자동) | 지원 |
| 커뮤니티/생태계 | 가장 넓음 | 빠르게 성장 | 중국 생태계 강점 |
권장 선택 기준:
- vLLM: 범용 프로덕션 환경, OpenAI API 드롭인 교체, ViT DP 최적화가 필요한 경우
- SGLang: 멀티턴 대화에서 KV Cache 재사용이 핵심인 경우, 구조화된 출력이 필요한 경우
- LMDeploy: InternVL 시리즈 모델의 최적 성능이 필요하거나 KV 양자화를 적극 활용하는 경우
vLLM으로 VLM 서빙하기: 단계별 구현
vLLM은 V1 아키텍처에서 멀티모달 추론 성능을 크게 개선했다. 인코더 캐시를 도입해 동일 이미지에 대한 비전 인코딩을 한 번만 수행하고, 인코더 인식 스케줄러가 멀티모달 임베딩 위치를 추적한다.
서버 실행
# Qwen2.5-VL-7B 단일 GPU 서빙
vllm serve Qwen/Qwen2.5-VL-7B-Instruct \
--host 0.0.0.0 \
--port 8000 \
--max-model-len 8192 \
--gpu-memory-utilization 0.92 \
--limit-mm-per-prompt '{"image": 4}' \
--dtype bfloat16 \
--enable-prefix-caching
# Qwen2.5-VL-72B 멀티 GPU 서빙 (ViT DP + LLM TP)
vllm serve Qwen/Qwen2.5-VL-72B-Instruct \
--host 0.0.0.0 \
--port 8000 \
--tensor-parallel-size 4 \
--mm-encoder-tp-mode data \
--max-model-len 16384 \
--gpu-memory-utilization 0.95 \
--limit-mm-per-prompt '{"image": 8}' \
--dtype bfloat16 \
--enable-prefix-caching
--mm-encoder-tp-mode data 옵션이 핵심이다. ViT 인코더는 파라미터가 작아 Tensor Parallel로 분할해도 통신 오버헤드만 증가한다. 대신 Data Parallel로 각 GPU에서 독립적으로 인코딩하면 TTFT가 극적으로 줄어든다. AMD ROCm 블로그에 따르면 이 한 줄 옵션만으로 멀티모달 추론 성능이 수배 향상되었다.
OpenAI 호환 API 클라이언트
from openai import OpenAI
import base64
from pathlib import Path
def encode_image_to_base64(image_path: str) -> str:
"""이미지 파일을 base64로 인코딩"""
with open(image_path, "rb") as f:
return base64.b64encode(f.read()).decode("utf-8")
client = OpenAI(
api_key="EMPTY",
base_url="http://localhost:8000/v1",
)
# URL 기반 이미지 입력
response = client.chat.completions.create(
model="Qwen/Qwen2.5-VL-7B-Instruct",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "이 이미지에서 텍스트를 추출해주세요."},
{
"type": "image_url",
"image_url": {
"url": "https://example.com/document.png",
"detail": "high",
},
},
],
}
],
max_tokens=2048,
temperature=0.1,
)
print(response.choices[0].message.content)
# base64 인코딩 이미지 입력
b64_image = encode_image_to_base64("/data/images/receipt.jpg")
response = client.chat.completions.create(
model="Qwen/Qwen2.5-VL-7B-Instruct",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "이 영수증의 총 금액은?"},
{
"type": "image_url",
"image_url": {
"url": f"data:image/jpeg;base64,{b64_image}",
},
},
],
}
],
max_tokens=512,
)
print(response.choices[0].message.content)
Qwen3-VL MoE 모델 서빙
Qwen3-VL-235B-A22B는 MoE 아키텍처로, Expert Parallel을 활용한 서빙이 필요하다.
# Qwen3-VL-235B-A22B MoE 서빙 (8 GPU 필수)
vllm serve Qwen/Qwen3-VL-235B-A22B-Instruct \
--host 0.0.0.0 \
--port 8000 \
--tensor-parallel-size 8 \
--mm-encoder-tp-mode data \
--enable-expert-parallel \
--max-model-len 32768 \
--gpu-memory-utilization 0.95 \
--limit-mm-per-prompt '{"image": 4, "video": 1}' \
--dtype bfloat16
--enable-expert-parallel 플래그는 MoE 레이어의 Expert를 GPU 간 분산 배치하여 메모리 효율을 높인다. 이 옵션 없이 TP8만 사용하면 Expert 중복 로드로 메모리가 부족해질 수 있다.
이미지 전처리 파이프라인 최적화
VLM 서빙에서 이미지 전처리는 예상보다 큰 병목이다. 고해상도 이미지를 매 요청마다 리사이즈하고 정규화하면 CPU 바운드로 전체 처리량이 제한된다.
전처리 워커 분리 아키텍처
# docker-compose.yml - 전처리 워커 + VLM 서버 분리
version: '3.8'
services:
image-preprocessor:
image: vlm-preprocessor:latest
deploy:
replicas: 4
environment:
- MAX_IMAGE_SIZE=2048
- OUTPUT_FORMAT=base64
- REDIS_URL=redis://redis:6379/0
volumes:
- /data/image-cache:/cache
cpus: '4'
mem_limit: 8g
vlm-server:
image: vllm/vllm-openai:latest
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 4
capabilities: [gpu]
command: >
--model Qwen/Qwen2.5-VL-72B-Instruct
--tensor-parallel-size 4
--mm-encoder-tp-mode data
--max-model-len 16384
--gpu-memory-utilization 0.95
ports:
- '8000:8000'
redis:
image: redis:7-alpine
ports:
- '6379:6379'
이미지 전처리 최적화 코드
import hashlib
from io import BytesIO
from PIL import Image
import redis
import base64
class ImagePreprocessor:
"""VLM 서빙을 위한 이미지 전처리 파이프라인"""
def __init__(
self,
max_size: int = 2048,
min_size: int = 28,
redis_url: str = "redis://localhost:6379/0",
):
self.max_size = max_size
self.min_size = min_size
self.cache = redis.from_url(redis_url)
self.cache_ttl = 3600 # 1시간
def _compute_hash(self, image_bytes: bytes) -> str:
return hashlib.sha256(image_bytes).hexdigest()
def _smart_resize(self, image: Image.Image) -> Image.Image:
"""해상도를 VLM 패치 크기에 맞게 조정 (28의 배수)"""
w, h = image.size
# 최대 크기 제한
if max(w, h) > self.max_size:
ratio = self.max_size / max(w, h)
w = int(w * ratio)
h = int(h * ratio)
# 28의 배수로 맞춤 (Qwen-VL 패치 크기)
w = max(self.min_size, (w // 28) * 28)
h = max(self.min_size, (h // 28) * 28)
return image.resize((w, h), Image.LANCZOS)
def process(self, image_bytes: bytes) -> str:
"""이미지를 전처리하고 캐시 적용, base64 반환"""
img_hash = self._compute_hash(image_bytes)
# 캐시 히트 확인
cached = self.cache.get(f"img:{img_hash}")
if cached:
return cached.decode("utf-8")
# 이미지 처리
image = Image.open(BytesIO(image_bytes)).convert("RGB")
image = self._smart_resize(image)
# JPEG 품질 85로 압축 (품질과 크기 균형)
buffer = BytesIO()
image.save(buffer, format="JPEG", quality=85)
b64_result = base64.b64encode(buffer.getvalue()).decode("utf-8")
# 캐시 저장
self.cache.setex(f"img:{img_hash}", self.cache_ttl, b64_result)
return b64_result
해상도를 28의 배수로 맞추는 이유는 Qwen-VL 계열의 ViT가 28x28 패치 크기를 사용하기 때문이다. 패치 크기의 배수가 아닌 해상도를 입력하면 내부적으로 패딩이 발생해 불필요한 연산이 추가된다. InternVL은 14x14 패치를 사용하므로 모델에 따라 조정해야 한다.
VLM 양자화 전략
VLM의 양자화는 텍스트 전용 LLM보다 복잡하다. 비전 인코더와 언어 디코더의 양자화 민감도가 다르기 때문이다. MBQ(Modality-Balanced Quantization, CVPR 2025) 연구에 따르면, 비전 토큰과 언어 토큰에 동일한 양자화를 적용하면 비전 이해 성능이 불균형하게 하락한다.
양자화 방법별 비교
| 양자화 방법 | 비트 수 | 메모리 절감 | 속도 향상 | 품질 영향 | 적용 대상 |
|---|---|---|---|---|---|
| BF16 (기준) | 16-bit | - | - | 없음 | 전체 모델 |
| FP8 (E4M3) | 8-bit | ~50% | ~1.5x | 매우 적음 | 언어 디코더 |
| AWQ (4-bit) | 4-bit | ~75% | ~2.0x | 소폭 하락 | 언어 디코더 |
| GPTQ (4-bit) | 4-bit | ~75% | ~1.8x | 소폭 하락 | 언어 디코더 |
| KV Cache INT8 | 8-bit | KV 50% | - | 미미 | KV Cache |
| Q-VLM (PTQ) | 4-bit | ~75% | ~1.4x | 최소화 | 전체 VLM |
권장 양자화 조합
프로덕션에서 검증된 양자화 조합은 다음과 같다.
고품질 요구 (문서 OCR, 의료 이미지 분석):
- 비전 인코더: BF16 유지 (양자화하지 않음)
- 언어 디코더: FP8 또는 BF16
- KV Cache: FP16
비용 최적화 (일반 이미지 설명, 챗봇):
- 비전 인코더: BF16 유지
- 언어 디코더: AWQ 4-bit
- KV Cache: INT8
핵심 원칙은 비전 인코더는 가능한 양자화하지 않는 것이다. ViT의 파라미터 수는 전체 모델의 1~5%에 불과하므로 양자화해도 메모리 절감이 미미하지만, 이미지 이해 품질은 크게 저하될 수 있다.
# AWQ 양자화 모델로 서빙 (비전 인코더는 BF16 유지)
vllm serve Qwen/Qwen2.5-VL-72B-Instruct-AWQ \
--host 0.0.0.0 \
--port 8000 \
--tensor-parallel-size 2 \
--mm-encoder-tp-mode data \
--max-model-len 8192 \
--quantization awq \
--gpu-memory-utilization 0.95 \
--kv-cache-dtype fp8_e5m2 \
--enable-prefix-caching
AWQ 4-bit 양자화를 적용하면 72B 모델이 2x A100 80GB에서 서빙 가능해진다. BF16에서 4x A100이 필요했던 것과 비교하면 GPU 비용이 절반으로 줄어든다.
ViT Data Parallel + LLM Tensor Parallel 하이브리드 전략
vLLM V1에서 도입된 가장 영향력 있는 VLM 최적화는 하이브리드 병렬 전략이다. 이 전략의 핵심 아이디어는 비전 인코더와 언어 디코더의 병렬화 방식을 분리하는 것이다.
기존 방식 (TP-Only): 4 GPU에서 TP4로 서빙하면 ViT도 4-way로 분할된다. ViT는 파라미터가 작아(600M~6B) 분할 효과는 미미한데, All-Reduce 통신이 매 레이어마다 발생해 오히려 느려진다.
하이브리드 방식 (ViT DP + LLM TP): 4 GPU에서 ViT는 각 GPU에 전체를 복제하고(DP4), LLM만 TP4로 분할한다. 배치 내 4개의 이미지를 각 GPU가 하나씩 독립적으로 인코딩하므로 통신 오버헤드가 제거된다.
성능 차이는 극적이다. Qwen2.5-VL-72B 기준으로 4 GPU에서 하이브리드 전략 적용 시 TTFT가 기존 대비 2~4배 개선된다. 특히 고해상도 이미지나 멀티이미지 입력에서 차이가 더 크다.
프로덕션 모니터링과 메트릭
VLM 서빙에서는 텍스트 전용 LLM 대비 추가 메트릭을 모니터링해야 한다.
핵심 모니터링 메트릭
from prometheus_client import Histogram, Counter, Gauge
# VLM 전용 메트릭 정의
vlm_image_preprocess_duration = Histogram(
"vlm_image_preprocess_seconds",
"이미지 전처리 소요 시간",
buckets=[0.01, 0.05, 0.1, 0.25, 0.5, 1.0, 2.0],
)
vlm_encoder_duration = Histogram(
"vlm_encoder_inference_seconds",
"비전 인코더 추론 시간",
buckets=[0.05, 0.1, 0.2, 0.5, 1.0, 2.0, 5.0],
)
vlm_total_image_tokens = Counter(
"vlm_total_image_tokens",
"처리된 총 이미지 토큰 수",
)
vlm_image_cache_hits = Counter(
"vlm_image_cache_hits_total",
"이미지 인코딩 캐시 히트 수",
)
vlm_image_cache_misses = Counter(
"vlm_image_cache_misses_total",
"이미지 인코딩 캐시 미스 수",
)
vlm_active_image_count = Gauge(
"vlm_active_image_count",
"현재 처리 중인 이미지 수",
)
vlm_kv_cache_image_tokens_ratio = Gauge(
"vlm_kv_cache_image_tokens_ratio",
"KV Cache 중 이미지 토큰 비율",
)
알림 설정 기준
| 메트릭 | 경고 임계값 | 위험 임계값 | 조치 |
|---|---|---|---|
| 인코더 추론 시간 | P99 500ms 초과 | P99 2s 초과 | 이미지 해상도 제한 확인 |
| TTFT | P99 3s 초과 | P99 10s 초과 | 배치 크기/이미지 수 제한 |
| KV Cache 사용률 | 85% 초과 | 95% 초과 | max-model-len 축소 또는 GPU 증설 |
| 이미지 캐시 히트율 | 50% 미만 | 30% 미만 | 캐시 TTL/크기 조정 |
| OOM 발생 횟수 | 1회/시간 | 3회/시간 | 즉시 이미지 수 제한 또는 max-model-len 축소 |
장애 사례와 복구 절차
사례 1: 고해상도 이미지로 인한 OOM
증상: 4K 이상 이미지 입력 시 GPU OOM 발생, 서버 프로세스 크래시
원인: 이미지 해상도에 비례해 패치 수가 급증한다. 4096x4096 이미지를 28x28 패치로 분할하면 약 21,000개 패치가 생성되고, 이 패치 임베딩이 GPU 메모리를 순간적으로 점유한다.
복구 절차:
--limit-mm-per-prompt옵션으로 요청당 이미지 수 제한- 전처리 단계에서 최대 해상도를 2048 이하로 강제 리사이즈
- vLLM의
--max-num-seqs를 낮춰 동시 처리 요청 수 제한 - 재발 방지를 위해 API 게이트웨이에서 이미지 크기 검증 미들웨어 추가
사례 2: 멀티이미지 요청에서 배칭 효율 급락
증상: 이미지 수가 요청마다 다를 때 처리량이 단일 이미지 대비 30% 이하로 떨어짐
원인: 배치 내 요청들의 이미지 토큰 수가 크게 다르면 패딩이 발생하거나 스케줄러가 보수적으로 배치 크기를 줄인다.
해결 방법:
- 이미지 수 기준으로 요청을 버킷팅 (0개, 1개, 2-4개, 5개 이상)
- 버킷별 별도 서빙 인스턴스 배포
- 로드밸런서에서 이미지 수 기반 라우팅 적용
사례 3: 인코더 캐시 메모리 누수
증상: 장시간 운영 시 GPU 메모리 사용량이 점진적으로 증가하다가 OOM 발생
원인: vLLM의 인코더 캐시가 만료 정책 없이 계속 쌓이는 경우 발생 가능
복구 절차:
- vLLM 서버의
--max-num-seqs값 조정으로 동시 캐시 엔트리 제한 - 주기적 서버 재시작 스케줄 설정 (graceful shutdown 후 rolling restart)
- GPU 메모리 모니터링 알림 설정으로 조기 감지
성능 벤치마크 가이드
VLM 서빙 성능을 정확하게 측정하려면 텍스트 전용 벤치마크와 다른 방법론이 필요하다.
import asyncio
import time
import statistics
from openai import AsyncOpenAI
async def benchmark_vlm_serving(
base_url: str,
model: str,
image_urls: list[str],
num_requests: int = 100,
concurrency: int = 10,
):
"""VLM 서빙 벤치마크: TTFT, 처리량, 이미지별 레이턴시 측정"""
client = AsyncOpenAI(api_key="EMPTY", base_url=base_url)
ttfts = []
total_latencies = []
semaphore = asyncio.Semaphore(concurrency)
async def single_request(image_url: str):
async with semaphore:
start = time.monotonic()
first_token_time = None
stream = await client.chat.completions.create(
model=model,
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "이 이미지를 설명해주세요."},
{
"type": "image_url",
"image_url": {"url": image_url},
},
],
}
],
max_tokens=256,
stream=True,
)
async for chunk in stream:
if first_token_time is None and chunk.choices[0].delta.content:
first_token_time = time.monotonic()
ttfts.append(first_token_time - start)
end = time.monotonic()
total_latencies.append(end - start)
# 벤치마크 실행
tasks = [
single_request(image_urls[i % len(image_urls)])
for i in range(num_requests)
]
bench_start = time.monotonic()
await asyncio.gather(*tasks)
bench_duration = time.monotonic() - bench_start
# 결과 출력
print(f"총 요청: {num_requests}, 동시성: {concurrency}")
print(f"총 소요시간: {bench_duration:.2f}s")
print(f"처리량: {num_requests / bench_duration:.2f} req/s")
print(f"TTFT P50: {statistics.median(ttfts)*1000:.0f}ms")
print(f"TTFT P99: {sorted(ttfts)[int(len(ttfts)*0.99)]*1000:.0f}ms")
print(f"총 레이턴시 P50: {statistics.median(total_latencies)*1000:.0f}ms")
print(f"총 레이턴시 P99: {sorted(total_latencies)[int(len(total_latencies)*0.99)]*1000:.0f}ms")
벤치마크 시 주의사항: 다양한 해상도의 이미지를 혼합해야 실제 프로덕션 워크로드를 반영할 수 있다. 동일 이미지만 반복하면 인코더 캐시로 인해 비현실적으로 좋은 결과가 나온다.
운영 체크리스트
배포 전 점검
- 모델 선택 근거 문서화 (벤치마크 결과, 비용 분석 포함)
- 입력 이미지 최대 해상도 제한 설정 확인
-
--limit-mm-per-prompt옵션으로 요청당 이미지/비디오 수 제한 - 전처리 파이프라인에서 지원하지 않는 이미지 포맷 거부 로직 확인
- GPU 메모리 사용률 95% 이하에서 안정적으로 동작하는지 부하 테스트 완료
- 양자화 적용 시 비전 인코더 BF16 유지 확인
- OOM 발생 시 자동 재시작 설정 (systemd/k8s liveness probe)
- OpenAI API 호환 엔드포인트 응답 형식 검증
운영 중 점검
- TTFT P99이 SLA 이내인지 주기적 확인
- KV Cache 사용률 트렌드 모니터링
- 인코더 캐시 히트율 확인 (50% 미만이면 캐시 전략 재검토)
- GPU 메모리 사용량 점진적 증가 여부 확인 (메모리 누수 징후)
- 입력 이미지 크기 분포 로깅 (비정상적 대용량 이미지 탐지)
- 에러율 모니터링 (특히 이미지 디코딩 실패, 타임아웃)
- 모델 업데이트 시 양자화 호환성 재검증
스케일링 판단 기준
- GPU 사용률이 지속적으로 85% 초과하면 인스턴스 추가
- 요청 큐 대기시간이 P99 5초 초과하면 스케일아웃
- KV Cache 부족으로 요청 거부가 발생하면 max-model-len 축소 또는 GPU 증설
- 멀티이미지 요청 비율이 50% 초과하면 이미지 수 기반 라우팅 도입 검토
요약
VLM 서빙은 텍스트 전용 LLM 서빙의 확장이 아니라 별도의 엔지니어링 도메인이다. 비전 인코더와 언어 디코더의 비대칭적 특성을 이해하고, 이에 맞는 병렬화 전략(ViT DP + LLM TP), 양자화 전략(인코더 BF16 유지, 디코더만 양자화), 캐싱 전략(인코더 캐시 + 이미지 전처리 캐시)을 적용해야 프로덕션 수준의 성능과 안정성을 달성할 수 있다.
핵심 세 가지를 기억하자.
- ViT는 양자화하지 말고, LLM만 양자화하라: 비전 인코더의 파라미터 비중은 작지만 이미지 이해 품질에 대한 영향은 크다.
- ViT DP + LLM TP 하이브리드 전략을 기본으로 사용하라: 멀티 GPU 환경에서 TTFT를 극적으로 개선하는 가장 효과적인 방법이다.
- 이미지 해상도를 반드시 제한하라: 제한 없는 해상도 입력은 OOM의 가장 흔한 원인이며, 전처리 파이프라인에서 강제해야 한다.
참고 자료
- vLLM Multimodal Inputs Documentation - vLLM 공식 멀티모달 입력 가이드
- vLLM V1: Accelerating Multimodal Inference - Red Hat Developer - vLLM V1 인코더 캐시 및 멀티모달 최적화 상세
- Qwen2.5-VL vLLM Usage Guide - Qwen2.5-VL 모델별 vLLM 배포 설정
- Qwen3-VL vLLM Usage Guide - Qwen3-VL MoE 서빙 설정 및 최적 구성
- Accelerating Multimodal Inference in vLLM - AMD ROCm Blog - ViT DP + LLM TP 하이브리드 전략 벤치마크
- MBQ: Modality-Balanced Quantization for Large VLMs (CVPR 2025) - VLM 양자화 시 모달리티 균형 연구
- SGLang - High-Performance Serving Framework - SGLang 멀티모달 서빙 지원
- LMDeploy - LLM Deployment Toolkit - InternVL 계열 최적 서빙 프레임워크