실행 프로그램과 확장

vLLM으로 로컬 서버 만들기: 빠른 답변과 많은 요청은 다릅니다

코딩 도구에 로컬 모델을 연결하려고 찾아보면 vLLM이라는 이름을 자주 만납니다. 그런데 소개에 나온 높은 tok/s와 내 화면의 속도가 다를 수 있습니다. 설치 전에 무엇을 빠르게 만들고 싶은지 나누고, 작은 서버 하나를 확인한 뒤 필요한 설정만 더해보겠습니다.

1. 내가 기다리는 시간부터 정합니다

혼자 코드를 작성하는 동안 로컬 모델에 질문한다고 가정해보겠습니다. 원하는 것은 질문 후 빨리 답변이 시작되고, 코드가 끊기지 않고 이어지는 일입니다. 반면 여러 문서를 밤새 처리하는 서버는 각 요청의 기다림이 조금 늘어도 전체 작업을 일찍 끝내는 편이 유리할 수 있습니다. 같은 엔진에서도 두 목표의 설정은 달라집니다.

vLLM은 여러 요청을 묶어 GPU를 활용하고, 답변을 만드는 동안 필요한 KV 캐시를 관리합니다. 그래서 여러 사용자의 출력 토큰을 합친 처리량이 높게 나올 수 있습니다. 그 수치를 내 대화창 한 개의 속도로 읽으면 기대가 어긋납니다. 비교할 때는 동시 요청 1개의 첫 토큰 시간과 생성 속도를 따로 남기세요.

2. 같은 NVIDIA라도 설치 파일은 다릅니다

이 글의 명령은 Linux와 호환되는 NVIDIA CUDA 환경에 vLLM이 설치된 경우를 다룹니다. 기존 작업 환경에 패키지를 덮어씌우기보다 별도 가상환경이나 해당 장비용 컨테이너를 준비하세요. PyTorch와 CUDA, GPU 드라이버의 조합이 맞아야 합니다. 설치가 끝났다는 메시지만으로 실제 GPU 연산까지 확인된 것은 아닙니다.

DGX Spark는 ARM64 CPU와 Blackwell GPU를 함께 확인해야 하므로 일반 x86 PC용 이미지를 그대로 가져오면 안 됩니다. Mac은 또 다른 경우입니다. macOS CPU 실행과 MLX를 사용하는 커뮤니티 vllm-metal 플러그인은 CUDA 실행 경로와 구분됩니다. Metal에서 실행된다는 설명만 보고 CUDA의 양자화나 MTP 옵션까지 같다고 판단하지 마세요.

3. 작은 모델로 연결만 확인합니다

처음부터 원하는 대형 모델과 가속 옵션을 함께 넣으면 실패 원인을 찾기 어렵습니다. 아래는 설치 확인용 Qwen2.5-1.5B-Instruct를 문맥 4,096토큰, 동시 요청 1개로 여는 시작 명령입니다. 최신 주사용 모델을 추천하는 예제가 아닙니다. 모델이 저장되어 있지 않다면 처음에 파일 다운로드가 필요하며, 준비 과정은 답변 속도 측정에서 제외합니다.

서버 준비 완료를 확인한 뒤 다른 터미널에서 짧은 질문을 보냅니다. 두 명령의 모델 이름과 포트가 일치해야 합니다. 127.0.0.1은 이 컴퓨터 안에서만 접속하는 주소입니다. 정상 답변이 오면 앱의 서버 주소를 http://127.0.0.1:8000/v1로 맞출 수 있습니다. 여기까지 되는 구성을 남겨두면 다음 설정이 실패해도 돌아올 곳이 생깁니다.

CUDA 환경의 연결 확인용 서버

vllm serve Qwen/Qwen2.5-1.5B-Instruct \
  --host 127.0.0.1 --port 8000 \
  --max-model-len 4096 --max-num-seqs 1

vLLM 설치 후 실행합니다. Spark는 ARM64·Blackwell 지원 빌드를 먼저 준비해야 합니다.

다른 터미널에서 질문 보내기

curl --fail-with-body http://127.0.0.1:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model":"Qwen/Qwen2.5-1.5B-Instruct","messages":[{"role":"user","content":"Explain what a local AI server does in two sentences."}],"max_tokens":64,"temperature":0}'

연결 확인용 질문입니다. 이 한 번의 응답을 벤치마크 기록으로 사용하지 않습니다.

4. 메모리를 다 쓰는 것이 목표는 아닙니다

주사용 모델로 바꾼 뒤에는 파일 이름, 양자화 형식, 입력 길이를 먼저 고정합니다. NVFP4와 GGUF Q4는 같은 4비트라는 이유로 바꿔 쓸 수 있는 설정이 아닙니다. GPU 세대와 모델 구조에 맞는 실행 지원이 필요합니다. 모델 가중치가 들어간 다음에도 KV 캐시와 계산용 공간이 남아야 긴 문서를 처리할 수 있습니다.

먼저 --max-model-len을 실제 필요한 길이로 두고 --max-num-seqs 1에서 확인하세요. 동시 요청을 늘리는 실험은 그다음입니다. --gpu-memory-utilization을 높이면 캐시에 쓸 공간이 늘 수 있지만 다른 프로세스의 여유는 줄어듭니다. 반복해서 요청이 중단·재계산된다면 숫자를 끝까지 올리기보다 문맥과 동시 요청부터 줄여 원인을 나눕니다.

5. MTP는 모델을 확인한 다음입니다

MTP는 다음 토큰 후보를 미리 만들고 확인하는 방식입니다. 대상 모델의 지원과 필요한 가중치, vLLM 버전이 맞아야 하며 모든 모델에 같은 옵션을 붙일 수는 없습니다. 현재 vLLM은 --speculative-config로 구성을 받습니다. 다른 엔진의 NEXTN이나 --spec-type을 옮겨 적기보다 사용할 모델의 레시피에서 지원 경로를 확인하세요.

가속을 끈 기준과 켠 결과를 같은 질문 길이·출력 길이로 비교합니다. 후보가 많이 통과하는 코드 작업과 자유로운 글쓰기의 결과는 다를 수 있습니다. 긴 입력 뒤 짧게 답하는 일이라면 디코드의 개선보다 앞쪽 기다림이 더 큽니다. 첫 입력과 캐시가 남은 반복 입력도 나누어야 가속 효과를 엉뚱하게 읽지 않습니다.

6. 실패했을 때 돌아갈 구성을 남깁니다

로드 중 메모리가 부족하면 먼저 모델 파일 크기와 다른 GPU 프로세스를 확인합니다. 요청을 보낸 뒤에만 실패하면 문맥·동시 요청을 줄이고, MTP를 더한 직후라면 가속을 빼고 재확인합니다. 컴파일이나 CUDA graph 단계에서만 문제가 나면 --enforce-eager를 임시 진단에 사용할 수 있지만, 해결 후 그대로 두면 평상시 생성 성능이 달라질 수 있습니다.

정상 동작한 버전과 모델 revision, 시작 명령을 함께 보관하세요. 업데이트할 때 기존 환경을 지우지 않고 새 환경에서 짧은 질문과 평소의 긴 문서를 확인하면 복구가 쉽습니다. 혼자 쓰는 속도가 이미 충분하다면 복잡한 다중 GPU 구성으로 넘어갈 필요는 없습니다. 더 필요한 메모리인지, 여러 작업을 동시에 받을 능력인지부터 정하고 장비를 비교하면 됩니다.

수정 내역

사이트의 안내가 바뀐 기록입니다. 설치된 엔진·모델 버전을 자동으로 확인한 결과는 아닙니다.

  1. vLLM 실행 조건·요청 처리 안내 추가

    CUDA 환경의 짧은 서버·API 예제와 함께 일반 PC, ARM64 Spark, Mac의 실행 경로를 구분했습니다. 한 요청의 생성 속도와 서버 총처리량을 나누고, 모델별 양자화·MTP 지원을 확인하도록 설명했습니다.