vLLM LoRA 어댑터 운영, 기본 모델과 런타임 교체를 안전하게 나누는 법

무브랜드 GPU 서버와 여러 개의 평범한 저장장치, 한 대의 모니터에 흐릿한 추론 작업 화면이 놓인 실험실 책상

AI를 활용하여 생성한 이미지입니다.

vLLM에 LoRA 어댑터를 붙이면 같은 기본 모델을 여러 업무에 맞게 나누어 쓸 수 있어요. 하지만 어댑터를 많이 올리면 모델이 자동으로 더 똑똑해지는 것은 아니고, 각 요청이 어떤 모델 이름으로 들어갔는지와 GPU 메모리·동시성 설정이 운영 결과를 좌우합니다. 기본 모델, 어댑터, 요청 라우팅을 별개의 구성요소로 보고 시작하는 게 안전해요.[1]

LoRA는 새 기본 모델이 아니에요

LoRA는 기본 모델 위에 작은 가중치 묶음을 적용하는 방식이에요. vLLM은 LoRA를 지원하는 모델에서 어댑터를 서비스할 수 있고, 서버 시작 때 이름과 경로를 지정한 뒤 API 요청의 model 값으로 어댑터를 선택합니다.[1] 따라서 클라이언트는 “어떤 파일을 읽을까”가 아니라 “어떤 공개 모델 이름을 요청할까”를 알아야 해요.

구성 운영에서 정할 것 실패할 때 보이는 모습
기본 모델 모델 파일, 최대 컨텍스트, 지원 아키텍처 모든 어댑터 요청이 함께 실패해요.
LoRA 어댑터 이름, 경로, rank, 동시 로딩 수 특정 업무 모델만 로딩 오류나 품질 저하가 생겨요.
API 라우팅 허용 모델명, 인증, 요청별 제한 기본 모델로 잘못 보내거나 존재하지 않는 모델 오류가 나요.

어댑터가 바뀌었다고 기본 모델의 토크나이저나 채팅 템플릿까지 자동으로 바뀐다고 생각하면 안 됩니다. 학습 때 사용한 토큰화, 프롬프트 형식, 대상 모델과 실제 서비스 기본 모델이 맞는지 먼저 확인하세요.

서버를 시작할 때 이름을 고정해요

정적인 구성이라면 서버 시작 명령에 --enable-lora와 --lora-modules 이름=경로를 명시하는 방식이 이해하기 쉬워요.[1] 예시는 다음과 같은 모양입니다.

vllm serve BASE_MODEL   --enable-lora   --lora-modules support=./adapters/support   --max-lora-rank 64

실제 서버에서는 경로가 컨테이너 안에서 보이는지, 어댑터 디렉터리에 필요한 파일이 모두 있는지, 기본 모델과 어댑터가 같은 대상 구조를 쓰는지 확인해야 해요. 공개 API에서 모델 이름을 그대로 노출할지, 내부 이름을 별도 매핑할지도 정하세요. 사용자 입력을 저장 위치로 연결하면 임의 어댑터 로딩 같은 보안 문제가 생길 수 있으니 허용 목록을 두는 편이 낫습니다.

동적 로딩은 편하지만 경계를 먼저 만들어요

vLLM은 런타임에 LoRA 어댑터를 구성하는 API와 플러그인 경로도 제공해요. 배포 중 서버를 다시 시작하지 않고 교체할 수 있다는 장점이 있지만, 요청을 받은 뒤 새 파일을 탐색하거나 로딩하는 과정이 첫 요청 지연으로 나타날 수 있습니다. 런타임 업데이트를 쓸 때는 어댑터 저장 위치, 허용할 이름, 캐시 용량, 실패 시 제거 방법을 문서로 남겨야 해요.[1]

특히 외부 저장소에서 어댑터를 받아오는 구조라면 “파일이 존재한다”와 “신뢰할 수 있는 어댑터다”는 다른 문제예요. 다운로드 주체와 검증 해시, 롤백할 이전 버전, 요청별 접근 권한을 분리하세요. 운영 중에는 새 어댑터를 먼저 별도 인스턴스에서 호출해 결과 형식과 지연을 확인한 뒤 트래픽을 넘기는 방식이 안전합니다.

메모리 문제를 어댑터 탓으로만 보지 않아요

같은 긴 시스템 프롬프트나 문서 접두사가 반복되는 서비스라면 vLLM의 Automatic Prefix Caching이 공통 접두사의 KV cache 계산을 재사용할 수 있어요. 긴 문서를 반복 질의하는 작업이나 대화 이력이 이어지는 작업에서 계산을 줄일 여지가 있지만, 프롬프트가 조금만 달라져도 재사용 범위가 줄어듭니다.[2]

컨텍스트를 늘리고 동시 요청을 높인 상태에서 LoRA까지 여러 개 겹치면 GPU 메모리가 빠르게 줄어들어요. 이때 무조건 배치 크기를 올리기보다 다음 세 가지를 분리해 측정하세요.

  • 기본 모델만 올렸을 때의 기준 메모리와 첫 토큰 지연
  • 어댑터 하나와 여러 어댑터를 각각 요청했을 때의 추가 메모리
  • 컨텍스트 길이와 동시 요청 수를 바꿨을 때의 KV cache 사용량

FP8 KV cache는 더 많은 토큰을 메모리에 둘 수 있도록 메모리 사용량을 줄이는 선택지예요. vLLM 문서에는 보정 없이 쓰는 방식과 데이터셋으로 보정하는 방식을 구분해 설명하고, 지원 백엔드와 스케일 방식에 따라 조건이 달라진다고 적혀 있습니다.[3] 품질이 중요한 업무라면 긴 문서·짧은 답변·도구 호출처럼 실제 트래픽을 나눠 비교해야 해요.

요청 모델명과 결과를 함께 기록해요

어댑터 운영에서 자주 놓치는 부분은 메트릭에 기본 모델만 남는 경우예요. 요청마다 공개 모델명, 기본 모델, 어댑터 버전, 응답 지연, 입력·출력 토큰을 함께 기록해야 특정 어댑터만 느려지는지 알 수 있습니다. 사용자에게 모델 선택권을 열어 둔다면 허용된 이름과 실제 라우팅 결과가 같은지 샘플링해서 확인하세요.

  1. 서버의 /v1/models에서 노출 모델명을 저장해요.
  2. 어댑터별 정상 요청 하나와 잘못된 모델명 요청 하나를 테스트해요.
  3. 첫 요청과 워밍업 이후 요청의 TTFT를 따로 기록해요.
  4. 컨텍스트 길이와 동시 요청 수를 고정한 상태에서 어댑터 간 결과를 비교해요.
  5. 새 어댑터가 문제를 일으키면 라우팅을 이전 이름으로 되돌리고 파일을 격리해요.

vLLM의 구조화 출력이나 KV cache를 이미 쓰고 있다면 어댑터 추가 전후의 스키마 오류와 메모리 여유도 같이 확인하세요. TTFT·TPOT·KV 캐시 점검 글의 지표 구분이 출발점이 될 수 있어요.

운영 기준을 짧게 정리하면

LoRA는 기본 모델을 교체하지 않고 업무별 동작을 분리하는 방법이에요. 서버 시작 시 고정할지 런타임에 바꿀지 결정한 뒤, 이름과 경로를 허용 목록으로 제한하고, 메모리·지연·품질을 어댑터별로 측정하세요. APC와 KV cache 양자화는 도움이 될 수 있지만 실제 프롬프트와 백엔드 조건을 벗어난 일반화는 위험합니다. 새 어댑터를 추가할 때마다 독립된 테스트 인스턴스와 되돌릴 이름을 남겨 두면 장애 때 판단이 빨라져요.

Sources

  1. [1] LoRA Adapters | vLLM
  2. [2] Automatic Prefix Caching | vLLM
  3. [3] Quantized KV Cache | vLLM

함께 읽을 글