[LLMSO] LLM 서빙 입문: CH1 모델 서빙과 최적화

xgro·2026년 8월 8일

LLMSO

목록 보기
1/10
post-thumbnail

📌 Notice

LLM Serving and Optimization Study (=LLMSO)
직접 실습을 통해 LLM 서비스 제공 및 최적화에 대한 지식에 대한 학습 및 실습 내용을 정리한 블로그입니다.

CloudNet@에서 스터디를 진행하고 있습니다.

EKS 관련 이전 스터디 내용은 아래 링크를 통해 확인할 수 있습니다.

이번 글에서는 첫 번째 주제인 CH1. Introduction to Model Serving and Optimization을 정리합니다.

아직 LLM을 깊게 다뤄보지 않은 입장에서, “모델을 학습하면 바로 서비스할 수 있을까?”라는 질문에서 출발해 모델 서빙의 기본 개념을 이해하고 정리합니다.



📌 Overview

LLM을 학습하거나 이미 만들어진 모델을 내려받는 것과, 사용자가 실제로 호출할 수 있는 서비스로 제공하는 것은 서로 다른 문제입니다.

모델 서빙은 학습이 완료된 모델을 실행 환경에 올리고, 사용자 요청을 받아 추론을 수행한 뒤 결과를 안정적으로 반환하는 과정을 의미합니다. 이때 단순히 정답을 반환하는 것만으로는 충분하지 않습니다.

실제 서비스에서는 다음 질문에 답할 수 있어야 합니다.

  • 요청이 들어왔을 때 얼마나 빠르게 응답할 수 있는가?
  • 동시에 얼마나 많은 요청을 처리할 수 있는가?
  • GPU 메모리를 얼마나 사용하는가?
  • 서비스 운영 비용은 어느 정도인가?
  • 트래픽이 증가했을 때 안정적으로 확장할 수 있는가?

이번 글에서는 모델의 구성 요소와 생명주기, 서빙의 기본 흐름, 최적화가 필요한 이유, 대표적인 서빙 방식, 그리고 vLLM을 살펴봅니다.



📌 Introduction to Model Serving and Optimization

👉 Step 01. 학습된 모델은 바로 서비스가 될까?

💡 핵심
모델을 학습했다는 것과 모델을 서비스한다는 것은 서로 다른 문제다.

학습 데이터
   ↓
모델 학습
   ↓
모델 산출물 패키징
   ↓
서빙 엔진에 로딩
   ↓
API 요청 처리
   ↓
모니터링 및 업데이트

처음에는 모델 파일만 있으면 곧바로 서비스를 만들 수 있다고 생각했습니다. 하지만 실제로 모델을 실행하려면 가중치 외에도 모델 구조를 해석하고 계산을 수행할 실행 환경이 필요합니다.

모델을 서비스로 제공한다는 것은 다음 과정을 포함합니다.

모델 준비 → 실행 환경 구성 → 요청 수신 → 추론 수행 → 결과 반환 → 운영 및 모니터링

즉, 모델 서빙은 모델을 한 번 실행해보는 것보다 더 넓은 범위의 시스템 문제입니다.

학습(training)은 데이터를 이용해 모델의 파라미터를 업데이트하는 과정이고, 추론(inference)은 학습이 끝난 모델에 입력을 전달해 결과를 생성하는 과정입니다. 서빙은 이 추론을 사용자의 요청에 맞춰 반복적이고 안정적으로 수행할 수 있도록 만드는 일이라고 이해했습니다.


👉 Step 02. 모델은 무엇으로 구성되는가?

💡 핵심
모델은 가중치 파일 하나가 아니라, 데이터·구조·실행 코드가 함께 있어야 실행 가능한 소프트웨어가 된다.

my-llm/
├── config.json
├── generation_config.json
├── model.safetensors
├── tokenizer.json
├── tokenizer_config.json
└── special_tokens_map.json
from transformers import AutoTokenizer, AutoModelForCausalLM

model_id = '<model-id>'
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    device_map='auto'
)
model.eval()

inputs = tokenizer('모델 서빙이란?', return_tensors='pt')
outputs = model.generate(**inputs, max_new_tokens=32)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))

📌 이 코드에서 중요한 점
가중치만 로드하는 것이 아니라 tokenizer, 모델 구조, 실행 코드가 함께 동작해야 한다.

CH1에서는 모델을 다음 세 가지 구성 요소의 결합으로 설명합니다.

1. Model Data

학습을 통해 만들어진 가중치와 파라미터입니다. 모델의 지식과 동작 특성이 저장되어 있지만, 이 데이터만으로는 모델을 실행할 수 없습니다.

2. Model Architecture

가중치를 어떤 구조와 계산 순서로 사용할지 정의합니다. LLM에서는 Transformer 구조가 핵심적인 역할을 합니다.

3. Model Execution Code

입력을 받아 토큰화하고, 모델 계산을 실행하고, 결과를 다시 사람이 읽을 수 있는 형태로 변환하는 코드입니다. 실제 서빙에서는 이 실행 코드와 프레임워크의 선택이 성능과 운영 방식에 영향을 줍니다.

따라서 모델을 배포할 때는 가중치 파일만 복사하는 것이 아니라, 모델 구조와 실행 코드, 그리고 이를 동작시킬 라이브러리와 하드웨어까지 함께 고려해야 합니다.


👉 Step 03. 모델 생명주기

💡 학습 단계의 관심사
정확도, loss, 학습 시간, 데이터 품질

💡 서빙 단계의 관심사
latency, throughput, GPU memory, 비용, 안정성

model:
  name: <model-name>
  version: v1
  framework: transformers
  precision: fp16

lifecycle:
  trained: true
  evaluated: true
  packaged: true
  deployed: false
  monitored: false

모델은 학습 단계에서 끝나지 않고 서비스 운영 단계까지 이어지는 생명주기를 가집니다.

데이터 준비
   ↓
모델 학습 또는 파인튜닝
   ↓
모델 저장 및 검증
   ↓
서빙 엔진에 모델 로딩
   ↓
추론 API 제공
   ↓
성능·오류·자원 사용량 모니터링
   ↓
모델 또는 실행 환경 업데이트

이 흐름에서 모델 서빙은 모델 로딩 이후부터 사용자 요청에 응답하는 구간에 해당하지만, 실제 운영에서는 모니터링과 업데이트까지 함께 고려해야 합니다.

예를 들어 모델의 응답 품질이 좋아도 GPU 메모리가 부족하거나, 요청이 몰렸을 때 응답 지연시간이 급격히 증가한다면 서비스로 사용하기 어렵습니다.


👉 Step 04. LLM 서빙의 기본 요청 흐름

사용자의 문장은 어떤 과정을 거쳐 GPU에서 처리되고, 다시 응답 문장으로 변환될까?

POST /v1/chat/completions
Content-Type: application/json
{
  "model": "<model-name>",
  "messages": [
    {"role": "user", "content": "LLM 서빙이란 무엇인가?"}
  ],
  "max_tokens": 64
}
문자열 입력
→ Tokenizer
→ Token IDs
→ 모델 추론
→ 생성 Token IDs
→ 문자열 응답

LLM 서빙은 다음과 같은 흐름으로 동작합니다.

사용자 요청
   ↓
입력 전처리 및 토큰화
   ↓
모델 추론
   ↓
토큰 생성 및 디코딩
   ↓
응답 후처리
   ↓
사용자에게 응답 반환

각 단계가 모두 중요하지만, LLM에서는 특히 모델 추론 단계가 많은 연산과 메모리를 사용합니다.

실제 서빙 엔진은 여러 요청을 효율적으로 처리하기 위해 요청을 모아 실행하거나, 실행 순서를 조정하거나, GPU 메모리를 재사용합니다. 따라서 같은 모델이라도 어떤 서빙 엔진과 설정을 사용하는지에 따라 성능이 달라질 수 있습니다.


👉 Step 05. 왜 LLM 서빙 최적화가 필요한가?

Latency    = 하나의 요청이 완료될 때까지 걸린 시간
Throughput = 일정 시간 동안 처리한 요청 또는 토큰의 양
TTFT       = 요청 후 첫 토큰이 생성될 때까지 걸린 시간
GPU Memory = 모델과 요청 처리에 사용된 GPU 메모리

⚠️ 주의
빠르다는 결론만으로는 부족하다. 어떤 GPU, 모델, 입력 길이, 출력 길이, 동시 요청 수에서 측정했는지 함께 기록해야 한다.

모델의 정확도가 높더라도 실제 서비스에서 다음과 같은 문제가 발생할 수 있습니다.

  • 첫 응답이 늦어 사용자가 기다리는 시간이 길어짐
  • 생성 속도가 느려 전체 응답 시간이 증가함
  • 동시에 처리할 수 있는 요청 수가 적음
  • 모델과 요청이 사용하는 GPU 메모리가 너무 큼
  • 트래픽이 증가하면 오류나 대기 요청이 급증함
  • 필요한 GPU 수가 많아져 운영 비용이 높아짐

서빙 성능을 볼 때는 하나의 숫자만 확인해서는 안 됩니다.

지표의미
Latency하나의 요청이 응답을 받기까지 걸린 시간
Throughput일정 시간 동안 처리할 수 있는 요청 또는 토큰의 양
GPU Memory Usage모델과 요청 처리에 사용되는 GPU 메모리
Cost같은 품질과 트래픽을 처리하기 위해 필요한 운영 비용

응답을 빠르게 만드는 것이 항상 최선은 아닙니다. 단일 사용자에게 가장 빠른 시스템과, 많은 사용자의 요청을 효율적으로 처리하는 시스템은 서로 다른 설정을 가질 수 있습니다.

결국 모델, 트래픽 패턴, GPU 자원, 응답 목표에 맞춰 latency와 throughput, 메모리와 비용 사이의 균형을 찾아야 합니다.


👉 Step 06. 모델 서빙 방식 비교

개인정보와 오프라인 실행이 중요한가?
 ├─ Yes → On-device
 └─ No
     ├─ 모델 하나의 성능이 중요한가? → Single-model
     ├─ 모델 수가 많고 트래픽이 낮은가? → Multi-model
     └─ 여러 서비스와 운영 자동화가 필요한가? → Serving platform

💡 정답은 하나가 아니다
모델 크기, 트래픽 규모, 보안 요구사항, 하드웨어와 비용을 함께 보고 서빙 방식을 선택해야 한다.

CH1에서는 모델을 제공하는 방식을 네 가지로 구분합니다.

1. On-Device 또는 Edge Serving

서버가 아니라 사용자의 PC, 스마트폰, 임베디드 장치 등에서 모델을 직접 실행하는 방식입니다.

장점

  • 요청 데이터가 외부 서버로 전송되지 않을 수 있음
  • 네트워크 지연시간을 줄일 수 있음
  • 서버 운영 비용을 줄일 수 있음

고려사항

  • 기기의 GPU·메모리·전력 제약
  • 모델 크기와 응답 품질의 trade-off
  • 다양한 사용자 기기 환경에 대한 대응

2. Single-model Service

하나의 모델 또는 하나의 모델 버전을 전용 서비스로 배포하는 방식입니다.

장점

  • 구조가 단순하고 모델별 격리가 쉬움
  • 모델별 성능과 자원 사용량을 관리하기 쉬움

고려사항

  • 요청이 적을 때 GPU 자원이 유휴 상태가 될 수 있음
  • 모델 수가 증가하면 서비스와 배포 대상도 함께 증가함

3. Multi-Model Service

하나의 실행 환경이나 컨테이너에서 여러 모델이 자원을 공유하는 방식입니다.

장점

  • 여러 모델이 자원을 공유하므로 활용률을 높일 수 있음
  • 모델 종류가 많은 환경에서 배포 자원을 줄일 수 있음

고려사항

  • 모델 간 메모리 경쟁
  • 모델 로딩과 교체에 따른 지연
  • 특정 모델의 트래픽 증가가 다른 모델에 영향을 줄 가능성

4. Model Serving Platform

모델 실행뿐 아니라 배포, 리소스 그룹, 오케스트레이션, 워크플로우와 같은 운영 기능까지 포함하는 플랫폼 형태입니다.

장점

  • 모델 배포와 확장, 운영 자동화에 유리함
  • 여러 모델과 환경을 일관된 방식으로 관리할 수 있음

고려사항

  • 초기 구성과 운영 복잡도가 증가함
  • 플랫폼 자체를 이해하고 관리해야 함

어떤 방식이 항상 정답인 것은 아닙니다. 모델 크기, 트래픽 규모, 보안 요구사항, 하드웨어와 비용을 함께 보고 선택해야 합니다.


👉 Step 07. vLLM을 살펴보는 이유

“The high-throughput and memory-efficient inference and serving engine for LLMs.”

— vLLM 공식 소개 문구

# 기본 Transformers 실행 예시
from transformers import pipeline

generator = pipeline(
    'text-generation',
    model='<model-id>',
    device_map='auto'
)
result = generator('모델 서빙이란?', max_new_tokens=64)
# vLLM 실행 예시
vllm serve <model-id> \
  --dtype auto \
  --max-model-len 2048

📌 이 글에서의 vLLM 이해
vLLM은 새로운 모델이 아니라, LLM을 효율적으로 실행하고 서비스하기 위한 서빙 엔진이다.

CH1에서는 vLLM을 다음과 같이 소개합니다.

The High-Throughput and Memory-Efficient Inference and Serving Engine for LLMs

즉, vLLM은 LLM 추론과 서빙을 더 높은 처리량과 메모리 효율을 목표로 수행하기 위한 엔진입니다.

같은 Hugging Face 모델을 사용하더라도 일반적인 실행 방식과 전용 서빙 엔진의 처리 방식은 다를 수 있습니다. 특히 여러 요청이 동시에 들어오는 상황에서는 요청을 어떻게 묶고, GPU 메모리를 어떻게 사용하며, 생성 작업을 어떤 순서로 스케줄링하는지가 성능에 영향을 줍니다.

이번 CH1에서는 vLLM의 내부 구현을 모두 이해하기보다는 다음 내용을 먼저 확인하는 것을 목표로 합니다.

  • vLLM이 모델 자체가 아니라 서빙을 위한 실행 엔진이라는 점
  • 동일한 모델도 실행 엔진에 따라 처리량과 메모리 효율이 달라질 수 있다는 점
  • 설정값 하나하나가 성능과 자원 사용량에 영향을 줄 수 있다는 점
  • 세부 최적화 원리는 이후 챕터에서 더 자세히 학습한다는 점

📌 Summary

이번 CH1에서 정리한 핵심은 다음과 같습니다.

  1. 모델 서빙은 학습된 모델을 실제 사용자 요청에 응답하는 서비스로 제공하는 과정이다.
  2. 모델은 가중치 데이터, 모델 아키텍처, 실행 코드가 함께 있어야 실행할 수 있다.
  3. LLM 서빙은 정확도뿐 아니라 latency, throughput, GPU 메모리, 비용을 함께 고려해야 한다.
  4. On-Device, Single-model, Multi-Model, Model Serving Platform은 서로 다른 운영 목적과 trade-off를 가진다.
  5. vLLM은 LLM 추론과 서빙을 효율적으로 수행하기 위한 엔진이며, 세부 최적화 원리는 이후 챕터에서 다룬다.

CH1을 통해 LLM 서비스는 단순히 모델을 실행하는 문제가 아니라, 모델·소프트웨어·GPU 자원·트래픽·운영 비용을 함께 다루는 시스템 문제라는 점을 이해하게 되었습니다.

다음에는 CH2에서 LLM 서빙 시스템의 구성 요소와 실제 최적화 기법을 더 자세히 살펴보겠습니다.

profile
안녕하세요! DevOps 엔지니어 이재찬입니다. 블로그에 대한 피드백은 언제나 환영합니다! 기술, 개발, 운영에 관한 다양한 주제로 함께 나누며, 더 나은 협업과 효율적인 개발 환경을 만드는 과정에 대해 인사이트를 나누고 싶습니다. 함께 여행하는 기분으로, 즐겁게 읽어주시면 감사하겠습니다! 🚀

0개의 댓글