본문 바로가기

01. 학습된 모델에서 추론 서버까지

핵심 질문
  • 디스크에 놓인 가중치 파일 하나가 어떻게 "요청을 받아 답을 내놓는 서버"가 되는가?
  • 그 사이에 어떤 컴포넌트들이 끼어들고, 각자 무엇을 책임지는가?

목표
  • 모델 아티팩트(가중치)와 서빙 컴포넌트(API·스케줄러·워커·실행자·가속기)를 구분한다.
  • 안내서 전체의 척추가 될 하나의 요청 여정 지도를 그린다.

먼저: '추론(inference)'이 뭔가요?

추론(inference)은 이미 학습이 끝난 모델에게 입력을 주고 출력을 받는 과정입니다. 학습(training)이 가중치를 바꾸는 일이라면, 추론은 가중치를 고정한 채 쓰는 일입니다. 이 안내서는 오직 추론만 다룹니다.

일상 비유로 시작합시다. 학습된 모델 파일은 완공되어 불 꺼진 식당 주방과 같습니다. 레시피(가중치)는 다 갖춰졌지만, 그 자체로는 아무 요리도 나오지 않습니다. 손님(요청)을 받아 주문을 정리하고, 재료를 준비하고, 불 앞에 서서 한 접시씩 내보내는 운영 체계가 붙어야 비로소 "서버"가 됩니다. 이 장은 그 운영 체계의 지도입니다.

두 세계: 모델 아티팩트 vs 서빙 컴포넌트

추론 시스템을 이해하려면 성격이 다른 두 덩어리를 먼저 갈라야 합니다.

모델 아티팩트(model artifact) — 학습의 산출물입니다.

  • 가중치 파일(weights): 행렬 형태의 학습된 파라미터. dtype(자료형, 예: FP16)에 따라 파일 크기가 결정됩니다.
  • 설정(config): 레이어 수, hidden 차원, attention head 수, 어휘 크기 등 구조를 적은 메타데이터.
  • tokenizer: 텍스트를 토큰 id로, 다시 텍스트로 바꾸는 규칙(어휘·병합 규칙 등).

이들은 정적(static)입니다. 디스크에 놓여 있고, 요청이 와도 스스로 바뀌지 않습니다.

서빙 컴포넌트(serving components) — 아티팩트를 살아 움직이게 하는 실행 계층입니다. 이름은 프레임워크마다 다르지만, 책임은 대체로 이렇게 나뉩니다.

컴포넌트한 줄 책임비유 (주방)
API 서버요청 수신, 인증, 응답 스트리밍홀 — 주문 받고 접시 내보내기
tokenizer/detokenizer텍스트↔토큰 변환주문서를 주방 용어로 번역
스케줄러(scheduler)어떤 요청을, 언제, 얼마나 처리할지 결정주방장 — 화구 배정
실행자(executor)워커들에 작업 분배(분산 실행 조율)라인 총괄
워커(worker)가중치를 GPU에 올리고 forward pass 실행각 화구의 요리사
모델 러너(model runner)입력 텐서 준비·모델 호출요리사의 손
가속기(GPU 등)실제 행렬 연산 수행
🔎 약어 풀이
  • API(Application Programming Interface): 프로그램끼리 대화하는 규격. 여기서는 "HTTP로 요청을 받는 창구".
  • GPU(Graphics Processing Unit): 대규모 병렬 행렬 연산에 특화된 가속기.
  • dtype(data type, 자료형): 숫자 하나를 몇 bit로 표현하는지. FP16이면 16 bit. → 05·11장에서 다시 다룸.
  • forward pass: 입력을 넣어 출력을 계산하는 한 번의 신경망 통과. 학습의 backward(역전파)와 대비되는 개념.

요청의 여정 — 큰 그림

이제 하나의 요청이 두 세계를 어떻게 가로지르는지 봅시다. 이 그림이 안내서 전체의 지도입니다.

flowchart TB
    subgraph 제어경로 [제어·데이터 경로]
        U[사용자: 프롬프트]:::req --> API[API 서버]:::ctrl
        API --> TOK[tokenizer<br/>텍스트→토큰 id]:::comp
        TOK --> ENG[엔진 코어]:::ctrl
        ENG --> SCHED{스케줄러<br/>지금 처리할까?}:::ctrl
    end

    subgraph 실행 [실행 계층]
        SCHED -->|배치에 포함| EXEC[실행자]:::ctrl
        EXEC --> WK[워커 + 모델 러너]:::comp
        WK --> GPU[가속기<br/>forward pass]:::comp
        GPU --> KV[(KV 캐시 읽기/쓰기)]:::mem
    end

    GPU --> OUTP[출력 처리<br/>detokenize]:::comp
    OUTP -->|토큰 하나씩| API
    API -.streaming.-> U

    classDef req fill:#fff3bf,stroke:#f59f00,color:#000;
    classDef comp fill:#d0ebff,stroke:#1971c2,color:#000;
    classDef mem fill:#e5dbff,stroke:#7048e8,color:#000;
    classDef ctrl fill:#c3fae8,stroke:#0ca678,color:#000;

핵심은 제어 경로(control path)와 데이터 경로(data path)가 분리된다는 점입니다. 스케줄러는 "무엇을 언제 할지"를 결정하는 제어 역할이고, 워커·가속기는 "실제 숫자를 계산하는" 데이터 역할입니다. 이 분리가 왜 중요한지는 07~08장(배칭)에서 본격적으로 드러납니다.

사례로 보기: vLLM V1의 컴포넌트 경계

추상적 역할을 실제 이름에 붙여봅시다. 단, 이것은 vLLM V1 아키텍처(2025-01 재설계 이후, 확인일 2026-07-20) 기준의 한 사례일 뿐이며, 컴포넌트 명칭은 버전마다 바뀝니다. 다른 엔진(SGLang, TensorRT-LLM 등)은 이름도 경계도 다릅니다.

vLLM V1은 요청 처리와 모델 실행을 여러 프로세스로 분리한 구조로 알려져 있습니다.

  • API 서버 / AsyncLLM: HTTP 요청을 받고 tokenization·detokenization·스트리밍을 담당.
  • EngineCore: 스케줄러와 실행자를 관리하는 "내부 실행 루프". CPU 작업(토큰화 등)과 GPU 실행 루프를 겹치게 해 throughput을 높이는 것이 설계 의도로 설명됩니다.
  • Scheduler: 요청을 배치로 묶고 토큰 단위 스케줄링을 수행.
  • Executor / Worker / ModelRunner: 실행자가 워커들에 분산하고, 각 워커(GPU 1개당 1 워커 프로세스로 설명됨)가 가중치를 올려 forward pass를 실행.
🔬 증거 읽기 (주장 유형: vendor-reported)
위 컴포넌트 구조는 vLLM 공식 블로그·문서·저장소(PRIMARY 출처)에 근거합니다. 다만 "owner 공개가 곧 독립 검증은 아님"을 기억하세요. 공식 문서는 설계 의도와 명칭의 근거로는 충분하지만, "이 구조가 다른 엔진보다 빠르다"는 성능 비교 주장의 근거로는 부족합니다 — 그건 조건이 명시된 measured 근거가 따로 필요합니다.
⚠️ 흔한 실수
흔한 오해
"vLLM V1은 prefill과 decode phase를 없앴다"는 말을 종종 봅니다. 정확히는, V1 스케줄러가 프롬프트 토큰과 생성 토큰을 스케줄링 관점에서 균일하게 다루도록 바꿨다는 뜻이지(스케줄링 결정을 {request_id: 토큰 수}처럼 표현), 계산 phase로서의 prefill/decode 구분 자체가 사라진 것은 아닙니다. 이 둘의 차이는 다음 장의 주제입니다.

📌 핵심

  • 추론 시스템 = 정적 모델 아티팩트(가중치·config·tokenizer) + 동적 서빙 컴포넌트(API·스케줄러·실행자·워커·가속기).
  • 하나의 요청은 API → tokenize → 스케줄러 → 실행자/워커/GPU → KV → 출력 처리 → 스트리밍의 여정을 지난다.
  • 제어 경로(무엇을 언제)와 데이터 경로(실제 연산)는 분리된다.
  • 컴포넌트 역할은 안정적이지만 이름은 프레임워크·버전마다 다르다.

🔎 이 장의 '지지하지 않는 결론'

  • 이 장은 컴포넌트 역할과 경계만 그렸을 뿐, "어떤 엔진이 더 빠르다/좋다"는 어떤 결론도 지지하지 않습니다.
  • vLLM 컴포넌트 이름을 소개했지만, 이것이 "vLLM을 써야 한다"는 권고는 아닙니다. 사례일 뿐입니다.

✍️ 확인 문제

  1. 모델 아티팩트에 속하는 것과 서빙 컴포넌트에 속하는 것을 각각 두 개씩 드세요. 둘을 가르는 기준은 무엇입니까?
  2. (조건 유형) "vLLM 컴포넌트 구조는 공식 문서에 나오니 그 성능도 믿을 수 있다"는 추론의 어디가 잘못됐습니까? '출처 등급'과 '주장 유형' 개념을 써서 설명하세요.
  3. 제어 경로와 데이터 경로를 분리하면 어떤 이점이 생길 수 있을지, 주방 비유로 한 문장 추측해 보세요. (정답이 아니라 직관을 확인하는 문제입니다.)
다음 장: 02 · tokenization, prefill, decode — 여정의 첫 계산 구간을 확대합니다.