vLLM OpenAI 호환 서버 운영, API 키·모델 이름·프록시 경계를 나누는 법
AI를 활용하여 생성한 이미지입니다.
vLLM을 로컬이나 사내 서버에서 OpenAI 호환 API로 열면, 기존 SDK와 클라이언트를 그대로 연결하기 쉬워요.[1] 다만 --api-key를 붙였다고 서버 전체가 잠기는 것은 아닙니다.[1] vLLM 공식 문서는 API 키가 일부 경로에만 적용되고, 같은 서버의 다른 경로에는 인증이 없을 수 있다고 명시해요.[1] 중급자라면 실행 명령보다 모델 이름, 엔드포인트, 인증 범위, 프록시 경계를 먼저 설계해야 합니다.[1]
먼저 정할 네 가지
첫째는 실제 모델 경로예요.[1] vLLM의 --model은 Hugging Face 모델 이름이나 로컬 경로가 될 수 있고, 별도 이름을 지정하지 않으면 메트릭의 모델 이름에도 사용됩니다.[2]
둘째는 클라이언트가 보낼 모델 이름입니다.[1] 서버가 실제 디렉터리 이름을 그대로 노출하면 클라이언트 설정과 배포 경로가 묶여요.[1] --served-model-name으로 외부에서 사용할 안정적인 이름을 정하면 모델 파일을 교체할 때 클라이언트 설정을 덜 건드릴 수 있습니다.[1] 이 이름은 요청 JSON의 model 값과 맞아야 해요.[1]
셋째는 바인딩 주소예요. 같은 PC의 앱만 쓸 때 127.0.0.1에 묶으면 LAN에서 직접 접근할 수 없습니다.[1] 다른 PC나 컨테이너에서 호출해야 한다면 0.0.0.0을 고려할 수 있지만, 그 순간 방화벽과 역방향 프록시가 보안 경계가 됩니다.[1]
넷째는 인증 위치예요. vLLM 프로세스의 API 키는 애플리케이션 계층의 한 겹일 뿐이고, 공개 인터넷에 포트를 바로 열어 주는 방화벽 규칙을 대신하지 못합니다.[1]
가장 작은 단일 호스트 구성
테스트용으로는 외부에 노출하지 않고 로컬에서만 확인하세요.[1] 아래 명령은 예시이며 모델 이름과 경로는 실제 설치 환경에 맞춰 바꿔야 해요.[1]
vllm serve /models/my-instruct-model \
--host 127.0.0.1 \
--port 8000 \
--served-model-name local-instruct \
--api-key "$VLLM_API_KEY"
공식 서버는 OpenAI Completions API와 Chat Completions API를 포함한 HTTP 인터페이스를 제공합니다.[1] Chat Completions는 채팅 템플릿이 있는 텍스트 생성 모델에 적용되므로, 모델에 템플릿이 없는데 /v1/chat/completions부터 호출하면 모델 로딩이 아니라 요청 형식에서 막힐 수 있어요.[1]
서버가 뜬 뒤에는 먼저 모델 목록을 확인하세요.[1]
curl -sS http://127.0.0.1:8000/v1/models \
-H "Authorization: Bearer $VLLM_API_KEY"
응답에서 id가 local-instruct인지 확인한 다음, 그 값을 그대로 요청에 넣습니다.[1]
curl -sS http://127.0.0.1:8000/v1/chat/completions \
-H "Authorization: Bearer $VLLM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "local-instruct",
"messages": [{"role": "user", "content": "짧게 자기소개해 주세요."}],
"temperature": 0.2,
"max_tokens": 128
}'
여기서 확인할 것은 응답 문장보다 먼저 HTTP 상태, model 값, 오류의 위치예요.[1] 401이면 키나 헤더 문제이고, 404면 경로·포트·프록시 문제일 가능성이 큽니다.[1] 400이면서 채팅 템플릿이나 모델 이름을 언급하면 서버는 살아 있지만 요청 계약이 맞지 않는 상황이에요.[1]
API 키의 보호 범위를 오해하지 않기
vLLM 문서의 현재 안내에서 --api-key 또는 VLLM_API_KEY는 /v1, /v2, /inference 경로 아래 요청을 인증하지만, 같은 HTTP 서버의 다른 엔드포인트는 인증되지 않을 수 있습니다.[1] 특히 /invocations가 같은 추론 능력을 노출할 수 있으므로 API 키만으로 서버 전체를 보호한다고 보면 안 돼요.[1]
따라서 서버를 다른 장치에서 쓸 때는 다음처럼 역할을 나누세요.[1]
- vLLM은 사설 인터페이스에만 바인딩하거나 내부 네트워크에 둬요.
- 외부에서 들어오는 TLS, IP 제한, 사용자 인증은 역방향 프록시에서 처리해요.
- 프록시가 허용할 경로를
/v1/처럼 필요한 범위로 제한해요. /metrics,/health,/invocations처럼 운영에 필요한 경로도 인증·접근 허용 범위를 따로 정해요.- API 키를 셸 히스토리나 저장소에 직접 적지 말고 환경 변수와 시크릿 저장소를 사용해요.
공식 문서도 API 키의 제한을 설명하면서 역방향 프록시 뒤에 배치하는 방식 같은 추가 보강을 권고합니다.[1] 회사 내부 서버라도 사내망이면 안전하다고 단정하지 마세요.[1] 로그와 프록시 설정에 Authorization 헤더가 남지 않는지도 확인해야 해요.[1]
모델 이름을 고정하는 이유
모델을 /models/llama-3.1-8b에서 /models/llama-3.1-8b-instruct-q8로 교체하면, 클라이언트가 실제 경로를 모델 이름으로 사용하던 구성은 함께 깨집니다.[1] 외부 계약을 local-instruct처럼 짧게 두면 파일 경로와 API 계약을 분리할 수 있어요.[1]
다만 같은 서버에서 여러 모델을 제공하려고 이름만 여러 개로 만들 수 있다고 생각하면 곤란합니다.[1] 서버가 실제로 로드한 모델과 요청의 model 값이 어떻게 매핑되는지 확인해야 하고, 모델별 토크나이저와 채팅 템플릿이 다르면 같은 프롬프트가 같은 결과 형식을 보장하지 않을 수 있어요.[1] vLLM 공식 옵션 문서도 --model이 모델 설정의 중심이 되고, 별도 served_model_name이 없을 때 모델 이름으로 사용된다고 설명합니다.[2]
장애를 빠르게 나누는 점검 순서
1. 프로세스와 포트
curl -i http://127.0.0.1:8000/health
lsof -nP -iTCP:8000 -sTCP:LISTEN
포트가 열렸는지부터 확인하세요. 모델 로딩이 끝나지 않았는데 클라이언트 재시도만 늘리면 GPU 메모리와 로그가 더 복잡해집니다.[1]
2. 인증과 경로
/v1/models에 키를 넣었을 때 200, 키를 빼면 401인지 확인합니다.[1] 두 요청이 똑같이 200이면 프록시나 서버 설정이 인증 헤더를 전달하지 않거나, 호출한 경로가 인증 대상이 아닐 수 있어요.[1] 키가 맞는데 401이라면 환경 변수가 vLLM 프로세스에 실제로 전달됐는지 확인하세요.[1]
3. 모델 계약
/v1/models의 id와 요청 JSON의 model이 같은지 확인합니다.[1] 모델 이름이 다르면 GPU 추론까지 가지 않고 요청 검증에서 끝납니다.[1] Chat Completions를 쓸 때는 모델의 chat template 지원 여부도 같이 확인해야 해요.[1]
4. 응답 형식과 도구 호출
vLLM 문서에 따르면 parallel_tool_calls를 false로 설정하면 요청당 도구 호출을 0개 또는 1개로 제한할 수 있고, true여도 모델에 따라 여러 호출이 보장되지는 않습니다.[1] 도구 호출을 쓰는 앱이라면 이 값을 모델 능력과 함께 테스트하세요.[1] API가 OpenAI 형식이라는 말이 모든 옵션의 의미와 동작까지 완전히 같다는 뜻은 아닙니다.[1]
프록시 뒤에 둘 때의 최소 설계
프록시와 vLLM을 한 서버에 두더라도 포트를 두 개로 나누면 확인이 쉬워요.[1] vLLM은 127.0.0.1:8000, 프록시는 TLS가 적용된 외부 포트에서 받고, 프록시가 Authorization을 내부 upstream에 전달합니다.[1] 외부에서는 /v1/models와 필요한 추론 경로만 열고, 관리·진단 경로는 내부 IP나 별도 인증으로 제한하세요.[1]
프록시를 추가한 뒤에는 내부 포트와 외부 포트를 각각 테스트해야 합니다.[1] 내부에서는 vLLM 키가 작동하는지, 외부에서는 프록시의 사용자 인증과 업스트림 전달이 모두 작동하는지 분리해 보면 401의 위치를 빨리 찾을 수 있어요.[1]
운영 전에 남겨 둘 체크리스트
- 모델 경로와 외부 모델 이름을 문서에 분리해 적어요.
- 로컬 테스트는
127.0.0.1로 시작하고, LAN 노출은 필요한 경우에만 켜요. /v1/models에서 서버가 실제로 광고하는id를 읽어 요청에 사용해요.--api-key가 모든 경로를 보호하지 않는다는 전제로 프록시와 방화벽을 구성해요.- Chat Completions를 쓴다면 chat template과 도구 호출 동작을 별도로 검증해요.
- 키가 로그·셸 히스토리·클라이언트 오류 화면에 남지 않는지 확인해요.
vLLM을 OpenAI 호환 서버로 쓰는 핵심은 명령 한 줄을 외우는 데 있지 않아요.[1] 모델 경로, 외부 이름, 요청 경로, 인증 경계를 각각 확인해야 모델을 바꾸거나 클라이언트를 늘릴 때 문제가 줄어듭니다.[1]
Sources
[1] https://docs.vllm.ai/en/latest/serving/online_serving/openai_compatible_server — vLLM OpenAI-Compatible Server [2] https://docs.vllm.ai/en/latest/configuration/engine_args — vLLM engine arguments
[…] OpenAI 호환 API를 운영할 때의 모델·키 경계도 함께 보면 연구 결과를 실제 서비스에 적용할 때 무엇을 별도로 점검해야 하는지 감을 잡을 수 있어요.[1] […]