vLLM 문서를 보면 생성 모델뿐 아니라 pooling 모델을 별도 실행 대상으로 다룹니다. LLM(..., runner="generate")가 텍스트 생성을 위한 흐름이라면, LLM(..., runner="pooling")은 임베딩, 분류, 리랭킹처럼 입력을 벡터나 점수로 바꾸는 작업에 가깝습니다. RAG 시스템을 운영하는 개발자라면 이 구분이 꽤 중요합니다.
많은 팀이 LLM 서빙을 시작할 때 생성 모델 서버 하나에만 집중합니다. 하지만 실제 RAG 품질과 비용은 생성 모델보다 앞단 검색 파이프라인에서 더 많이 흔들립니다. 임베딩 모델, 리랭커, 쿼리 분류기, 안전 필터가 느리거나 불안정하면 좋은 생성 모델을 써도 답변 품질이 올라가지 않습니다. 이 글은 vLLM pooling 모델을 기준으로 임베딩/리랭킹 서버를 생성 모델과 분리해야 하는 이유와 운영 체크리스트를 정리합니다.
RAG 장애를 분석해보면 사용자는 “답변이 이상하다”고 말하지만 원인은 다양합니다. 검색어 재작성 실패, 임베딩 품질 저하, 리랭커 지연, 오래된 문서 검색, 너무 많은 청크 주입, 생성 모델의 환각이 섞입니다. 이때 모든 요청을 하나의 LLM 서버 관점으로 보면 원인을 분리하기 어렵습니다.
예를 들어 응답 시간이 8초라고 합시다. 생성 모델이 느린지, 리랭커가 느린지, 벡터 DB가 느린지 분리하지 않으면 튜닝 방향이 틀어집니다. 생성 모델을 더 비싼 모델로 바꾸는 것보다 리랭킹 후보 수를 100개에서 30개로 줄이는 편이 더 큰 효과를 낼 수 있습니다.
또 하나의 문제는 트래픽 패턴입니다. 생성 요청은 출력 토큰 수에 따라 시간이 길어집니다. 반면 임베딩과 리랭킹은 짧은 입력을 대량으로 처리하는 배치형 성격이 강합니다. 서로 다른 병목을 가진 작업을 같은 서버 운영 단위로 묶으면 GPU 활용률과 장애 대응이 모두 나빠집니다.
생성 모델은 autoregressive decoding을 합니다. 토큰을 하나씩 만들고, KV cache가 늘어나며, 요청마다 출력 길이가 달라집니다. 그래서 continuous batching, prefix cache, max tokens, stop sequence 같은 설정이 중요합니다.
반면 pooling 모델은 입력을 통과시켜 벡터나 점수를 얻는 방식입니다. 출력 토큰을 길게 생성하지 않습니다. 대신 짧은 요청을 많이 처리하고, 배치 크기와 입력 길이가 처리량에 큰 영향을 줍니다. 리랭커는 후보 문서 수가 늘어날수록 요청 폭이 커지고, 임베딩은 문서 적재 작업에서 대량 배치가 필요합니다.
이 차이를 무시하면 다음 문제가 생깁니다.
vLLM이 supported models 문서에서 generative models와 pooling models를 구분하는 것은 단순한 문서 분류가 아닙니다. 운영 단위도 다르게 잡으라는 신호로 볼 수 있습니다.
실무에서는 최소 세 계층으로 나누는 것을 권장합니다.
첫째, 임베딩 계층입니다. 문서 적재와 사용자 쿼리 임베딩을 담당합니다. 문서 적재는 배치 처리, 사용자 쿼리는 낮은 지연 시간이 중요합니다. 같은 모델을 쓰더라도 큐를 분리하는 편이 좋습니다.
둘째, 리랭킹 계층입니다. 벡터 검색으로 가져온 후보를 다시 정렬합니다. 리랭커는 품질 개선 효과가 크지만 후보 수에 따라 비용이 급격히 늘어납니다. 따라서 후보 수, 문서 길이, timeout을 강하게 제한해야 합니다.
셋째, 생성 계층입니다. 최종 컨텍스트를 받아 답변을 만듭니다. 여기서는 출력 토큰 수, 스트리밍, 도구 호출, 안전 정책이 중요합니다.
구조를 나누면 장애 격리가 쉬워집니다. 리랭커가 느려지면 임시로 리랭킹을 끄고 벡터 검색 상위 결과만으로 답변할 수 있습니다. 임베딩 재색인이 몰리면 사용자 쿼리 임베딩 큐를 우선 처리할 수 있습니다. 생성 모델이 바뀌어도 검색 품질 지표는 별도로 유지할 수 있습니다.
pooling 모델을 운영할 때는 생성 모델과 다른 지표를 봐야 합니다. 출력 토큰 속도보다 입력 처리량과 tail latency가 중요합니다.
권장 지표는 다음과 같습니다.
RAG 품질 지표도 같이 봐야 합니다. 검색 recall, 리랭킹 후 클릭률, 답변 신고율, “근거 없음” 응답 비율을 함께 보지 않으면 latency만 줄이고 품질을 망칠 수 있습니다.
예를 들어 리랭커 후보 수를 50개에서 20개로 줄였더니 p95 latency가 40% 줄었지만 답변 신고율이 15% 늘었다면 좋은 최적화가 아닙니다. 반대로 후보 수를 줄여도 신고율이 그대로라면 비용 절감 효과가 큽니다.
간단한 RAG 서비스라도 처음부터 URL과 큐를 분리하는 편이 좋습니다.
embedding-api: 쿼리 임베딩과 문서 임베딩 담당rerank-api: 후보 문서 재정렬 담당generation-api: 최종 답변 생성 담당각 API는 timeout과 retry 정책이 달라야 합니다. 임베딩은 사용자 요청 경로에서는 짧게 실패해야 하고, 문서 적재 경로에서는 재시도할 수 있습니다. 리랭킹은 timeout이 나면 fallback을 제공해야 합니다. 생성은 스트리밍을 통해 사용자가 대기 시간을 체감하지 않게 만들 수 있습니다.
캐시 전략도 다릅니다. 문서 임베딩은 content_hash 기준으로 캐시하면 됩니다. 사용자 쿼리 임베딩은 완전 동일 질의가 많지 않다면 캐시 효과가 낮을 수 있습니다. 리랭킹 결과는 query + candidate_ids 조합으로 짧게 캐시할 수 있습니다. 생성 답변 캐시는 개인정보나 최신성 문제 때문에 더 조심해야 합니다.
RAG 비용을 줄이고 싶다면 생성 모델만 보지 말고 후보 수를 먼저 보세요. 벡터 검색 top_k를 크게 잡고, 리랭커에 모든 후보를 넣고, 생성 모델에 긴 컨텍스트를 넘기면 비용은 세 번 증가합니다.
실무에서 자주 쓰는 기준은 다음과 같습니다.
이 기준은 서비스마다 달라질 수 있지만, “많이 넣으면 좋아진다”는 접근은 위험합니다. 컨텍스트가 길어질수록 모델이 핵심 근거를 놓칠 수 있고, 비용과 지연 시간은 확실히 증가합니다.
vLLM pooling 모델을 RAG 운영에 붙이기 전 아래 항목을 확인하세요.
vLLM pooling 모델 운영의 핵심은 “LLM 서버 하나 더 띄우기”가 아닙니다. 생성과 검색 보조 작업의 리소스 패턴을 분리해 RAG 시스템을 관측 가능하게 만드는 것입니다. 그래야 품질 문제와 비용 문제를 같은 로그 안에서 뒤섞지 않을 수 있습니다.