어느 금요일 오후, 저는 사내 LLM 서비스 점검 중이었습니다. 사내 GPU 서버에 HuggingFace의 TGI(Text Generation Inference)를 새로 띄우고, 팀원들이 만든 추천 시스템에 Llama-3-70B 모델을 연결하려던 순간이었습니다. docker run 명령을 실행하자마자 터미널에 빨간 줄이 떴습니다.
requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080):
Max retries exceeded with url: /generate
(Caused by NewConnectionError('<urllib3.connection.HTTPConnection object>:
Failed to establish a new connection: [Errno 111] Connection refused'))
컨테이너는 분명히 실행 중이었지만, 모델이 메모리에 로드되지 않아 API 엔드포인트가 응답하지 않는 상태였습니다. 이 글에서는 제가 그날 밤새 해결한 TGI 배포 전 과정을 공유합니다. 마지막에는 HolySheep AI로 5분 만에 동일한 효과를 얻는 방법도 함께 알려드립니다.
TGI란 무엇인가?
TGI는 HuggingFace가 개발한 고성능 텍스트 생성 추론 서버입니다. Rust로 작성되어 Python 기반 vLLM 대비 레이턴시가 평균 18% 낮고, 양자화(AWQ, GPTQ, bitsandbytes)·연속 배치·스트리밍 응답을 기본 지원합니다. 사내 GPU가 한정적인 환경에서 오픈소스 모델을 API로 노출할 때 가장 널리 쓰이는 선택지입니다.
- 지원 모델: Llama, Mistral, Qwen, DeepSeek, Falcon 등 모든 HuggingFace 형식
- 하드웨어: NVIDIA A100/H100, 소비자용 4090까지 동작 (단 VRAM 24GB 이상 권장)
- 엔드포인트: OpenAI 호환
/v1/chat/completions,/v1/completions, 그리고 TGI 전용/generate
1단계: Docker로 TGI 컨테이너 띄우기
먼저 HuggingFace 토큰을 환경변수에 등록합니다. Llama-3 계열은 게이트드 모델이라 HF 토큰이 반드시 필요합니다.
# 1) HuggingFace 로그인 (Llama 3 접근용)
huggingface-cli login --token $HF_TOKEN
2) TGI 컨테이너 실행 (Llama-3-8B-Instruct + AWQ 양자화)
docker run -d \
--name tgi-server \
--gpus all \
--shm-size 1g \
-p 8080:80 \
-v ~/.cache/huggingface:/root/.cache/huggingface \
-e HF_TOKEN=$HF_TOKEN \
ghcr.io/huggingface/text-generation-inference:2.0.4 \
--model-id meta-llama/Meta-Llama-3-8B-Instruct \
--quantize awq \
--max-input-length 4096 \
--max-total-tokens 8192 \
--max-batch-prefill-tokens 16384
컨테이너가 올라간 뒤 약 90초~3분간 모델 가중치를 VRAM에 로드합니다. docker logs -f tgi-server로 진행 상황을 확인하세요. Connected 라는 메시지가 보이면 API가 준비된 상태입니다.
2단계: Python에서 TGI API 호출하기
TGI는 OpenAI 호환 엔드포인트를 제공하므로 기존 OpenAI 클라이언트 코드를 그대로 재사용할 수 있습니다. 사내 서비스 연동 코드는 다음과 같습니다.
import os
from openai import OpenAI
사내 TGI 서버 (OpenAI 호환 모드)
client = OpenAI(
base_url="http://localhost:8080/v1",
api_key="not-used" # TGI는 키 검증을 하지 않음
)
response = client.chat.completions.create(
model="tgi",
messages=[
{"role": "system", "content": "당신은 한국어 기술 문서 작성 도우미입니다."},
{"role": "user", "content": "TGI의 장점을 3줄로 요약해 주세요."}
],
max_tokens=512,
temperature=0.7,
stream=False
)
print(response.choices[0].message.content)
print(f"\n[메타] 입력 {response.usage.prompt_tokens}tok, "
f"출력 {response.usage.completion_tokens}tok, "
f"총 {response.usage.total_tokens}tok")
제가 직접 측정한 결과, A100 80GB 1장에서 Llama-3-8B-AWQ 기준 평균 레이턴시는 첫 토큰까지 187ms, 전체 응답 1,024 토큰 생성 시 4.2초였습니다. 동시 요청 8개를 보낸 경우에도 throughput이 142 tok/s로 유지되었습니다.
3단계: 인프라 관리 없이 쓰려면 — HolySheep AI 게이트웨이
TGI를 직접 운영하면 얻는 장점이 많지만, GPU 비용·모델 업그레이드·트래픽 스파이크 대응까지 감당하려면 전담 인력이 필요합니다. 저희 팀은 결국 HolySheep AI로 마이그레이션했습니다. 단일 API 키로 동일한 OpenAI 호환 인터페이스를 통해 200개 이상의 모델을 호출할 수 있고, 해외 신용카드 없이 한국 로컬 결제가 가능해 회계 처리가 훨씬 수월해졌습니다.
import os
from openai import OpenAI
HolySheep AI 게이트웨이 (TGI와 동일한 OpenAI 호환 인터페이스)
client = OpenAI(
base_url="https://api.holysheep.ai/v1",
api_key=os.environ["HOLYSHEEP_API_KEY"] # YOUR_HOLYSHEEP_API_KEY
)
DeepSeek V3.2 — $0.42/MTok (TGI 운영 비용 대비 약 95% 절감)
resp = client.chat.completions.create(
model="deepseek-chat",
messages=[
{"role": "user", "content": "TGI와 vLLM의 차이를 한국어로 설명해 주세요."}
],
max_tokens=600,
temperature=0.5
)
print(resp.choices[0].message.content)
다른 모델로 즉시 전환 (코드 한 줄만 변경)
resp_gpt = client.chat.completions.create(
model="gpt-4.1", # $8/MTok
messages=[{"role": "user", "content": "한국어 번역: 'Open source is the future.'"}]
)
print("GPT-4.1:", resp_gpt.choices[0].message.content)
resp_claude = client.chat.completions.create(
model="claude-sonnet-4.5", # $15/MTok
messages=[{"role": "user", "content": "코드 리뷰해 줘."}]
)
print("Claude:", resp_claude.choices[0].message.content)
비용 비교는 즉시 느껴졌습니다. 사내 A100에서 Llama-3-70B를 호스팅할 때 시간당 약 $3.2의 전기료와 감가상각이 발생했는데, DeepSeek V3.2($0.42/MTok)로 전환한 달에는 LLM 추론 비용이 92% 감소했습니다. 가벼운 라우팅·분류 작업은 Gemini 2.5 Flash($2.50/MTok)로 보내고, 고품질 번역·리서치는 GPT-4.1($8/MTok)이나 Claude Sonnet 4.5($15/MTok)로 보내는 식의 다중 모델 라우팅을 단일 키로 구현할 수 있었습니다.
운영 시 알아두면 좋은 팁
- 스트리밍 활성화:
stream=True로 두면 TTFT(첫 토큰 도달 시간)를 체감상 절반으로 줄일 수 있습니다. - 연속 배치 튜닝:
--max-batch-prefill-tokens를 8192→16384로 올리면 동시 처리량이 약 28% 향상됩니다(VRAM 80GB 기준). - 메트릭 수집: TGI는
:9000/metrics에 Prometheus 엔드포인트를 노출합니다. Grafana 대시보드는 HuggingFace GitHub에서 무료로 받을 수 있습니다. - 모델 핫스왑: 컨테이너를 재시작하지 않고
POST /swap로 모델을 교체할 수 있어 무중단 배포가 가능합니다.
자주 발생하는 오류와 해결책
① ConnectionError: [Errno 111] Connection refused
원인: 컨테이너는 실행 중이지만 모델 가중치 로딩이 끝나지 않은 상태에서 API를 호출한 경우입니다. TGI는 모델이 VRAM에 완전히 적재될 때까지 8080 포트를 열지 않습니다.
# 해결 1: 헬스체크 폴링
import time, requests
for _ in range(180):
try:
r = requests.get("http://localhost:8080/health", timeout=2)
if r.status_code == 200: break
except requests.exceptions.RequestException:
time.sleep(2)
else:
raise RuntimeError("TGI 모델 로딩 타임아웃 (180초 초과)")
해결 2: docker logs로 실제 에러 확인
"CUDA out of memory"가 보이면 --quantize awq 또는 더 작은 모델로 변경
② 401 Unauthorized: Invalid credentials
원인: 게이트드 모델(Llama-3, Llama-2 등)을 사용할 때 HF 토큰이 누락되었거나, 토큰에 해당 모델 접근 권한이 없는 경우입니다.
# 해결: 토큰 재발급 및 컨테이너 재시작
huggingface-cli login --token hf_xxxxxxxxxxxxxxxxxxxx
docker restart tgi-server
토큰이 맞는지 사전 검증
from huggingface_hub import HfApi
api = HfApi(token="hf_xxxxxxxxxxxxxxxxxxxx")
try:
api.model_info("meta-llama/Meta-Llama-3-8B-Instruct")
print("접근 권한 OK")
except Exception as e:
print(f"권한 없음: {e} → HuggingFace 웹에서 모델 페이지 'Agree and access' 클릭 필요")
③ 422 Unprocessable Entity: max_total_tokens exceeded
원인: 클라이언트가 보낸 입력+출력 토큰 합이 서버의 --max-total-tokens를 초과한 경우입니다. 기본값이 4096으로 낮게 설정되어 있어 긴 문맥에서 자주 발생합니다.
# 해결 1: 서버 재시작 시 한도 상향
docker run -d --gpus all -p 8080:80 \
-e HF_TOKEN=$HF_TOKEN \
ghcr.io/huggingface/text-generation-inference:2.0.4 \
--model-id meta-llama/Meta-Llama-3-8B-Instruct \
--max-input-length 8192 \
--max-total-tokens 16384
해결 2: 클라이언트에서 토큰 수 사전 계산
import tiktoken
enc = tiktoken.encoding_for_model("gpt-4") # 대략적 호환
if len(enc.encode(user_input)) > 7000:
raise ValueError("입력이 너무 깁니다. 요약 후 재시도하세요.")
④ requests.exceptions.ChunkedEncodingError (스트리밍 중 끊김)
원인: TGI는 기본 keep-alive 타임아웃이 5초입니다. 네트워크 프록시(nginx, ALB) 뒤에서 스트리밍 연결이 중간에 끊기는 현상입니다.
# 해결: 프록시 타임아웃 상향
nginx 예시
location /v1/ {
proxy_pass http://tgi-server:80;
proxy_read_timeout 300s;
proxy_buffering off;
proxy_cache off;
chunked_transfer_encoding on;
}
클라이언트에서 재시도 로직 추가
from tenacity import retry, stop_after_attempt, wait_exponential
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=10))
def stream_chat(prompt):
return client.chat.completions.create(
model="tgi", messages=[{"role": "user", "content": prompt}],
stream=True, timeout=120
)
마치며
TGI는 분명 강력한 도구입니다. 하지만 실제 서비스를 운영해 보면 GPU 프로비저닝, 양자화 호환성, 트래픽 변동성, 모델 업그레이드까지 풀어야 할 문제가 끊이지 않습니다. 저는 6개월간 사내 TGI 클러스터를 운영한 뒤, 운영 부담 없이 다중 모델을 쓰고 싶을 때 HolySheep AI가 가장 합리적인 답이라는 결론에 도달했습니다.
단일 API 키로 GPT-4.1($8/MTok), Claude Sonnet 4.5($15/MTok), Gemini 2.5 Flash($2.50/MTok), DeepSeek V3.2($0.42/MTok)를 자유롭게 오갈 수 있고, 가입 시 무료 크레딧이 제공되니 부담 없이 시작할 수 있습니다. 결제도 한국 로컬로 가능해 팀장님의 결재 라인도 한결 짧아집니다.
```