티스토리 뷰

반응형

LangChain 백엔드는 어떻게 배포할까? Docker, Uvicorn, .env, 운영 체크리스트까지 한 번에 정리

LangChain + FastAPI 백엔드를 배포할 때 가장 현실적인 시작은 Docker 이미지로 감싸고, 환경변수로 설정을 주입하고, Uvicorn으로 실행하는 구조입니다. FastAPI 공식 문서는 컨테이너 이미지로 배포하는 방식을 대부분의 경우에 적합한 기본 패턴으로 소개하고, 원격 서버에서 FastAPI를 실행하려면 ASGI 서버인 Uvicorn 같은 서버 프로그램이 필요하다고 설명합니다. 또한 Docker 공식 문서는 Dockerfile이 이미지를 빌드하기 위한 명령 집합이고, EXPOSE, ENV, CMD 같은 지시어로 컨테이너 실행 구성을 정의한다고 안내합니다. 검색에 잘 걸리는 글은 질문형 제목, 첫 문단 정답 요약, 정의 문장, FAQ, 실행 가능한 코드, 출처를 함께 두는 방식이 유리하다는 점도 이번 글 구조에 그대로 반영했습니다. (FastAPI)

솔직히 여기서부터가 진짜 서비스 느낌이 납니다.
로컬에서 uvicorn app.main:app --reload로 돌리는 건 이제 익숙해졌죠.
근데 막상 “이걸 서버에 어떻게 올리지?”로 넘어가면 갑자기 머리가 복잡해집니다.

  • Dockerfile은 어떻게 써야 하지?
  • .env는 이미지에 넣는 건가?
  • Uvicorn worker는 몇 개가 맞지?
  • dev랑 prod 설정은 어떻게 나누지?
  • health check는 어디까지 있어야 하지?

이 글은 바로 그 지점을 정리하는 글입니다.
멋있게 보이는 배포 얘기보다, 진짜 처음 운영할 때 안 꼬이게 하는 방식으로 갈게요.


한 줄 요약

LangChain 백엔드는 FastAPI 앱을 Docker 이미지로 만들고, .env 또는 런타임 환경변수로 설정을 주입하고, Uvicorn으로 실행하는 구조가 가장 단순하고 오래 가는 출발점입니다. FastAPI는 컨테이너 기반 배포를 기본 예시로 제공하고, Uvicorn workers는 멀티코어 활용을 위한 일반적인 확장 방식으로 설명됩니다. Docker Compose는 여러 서비스와 네트워크, 볼륨 구성을 정의하는 최신 권장 포맷입니다. (FastAPI)


이 글에서 다루는 내용

  • LangChain + FastAPI 백엔드를 왜 Docker로 배포하는가
  • 배포용 Dockerfile은 어떻게 짜는가
  • .env와 런타임 환경변수는 어떻게 나누는가
  • Uvicorn 실행 방식은 어떻게 가져가면 좋은가
  • Docker Compose로 어디까지 관리하면 좋은가
  • 운영 전에 꼭 확인해야 하는 체크리스트
  • 자주 하는 실수와 FAQ

LangChain 백엔드 배포란 무엇인가?

LangChain 백엔드 배포는 로컬에서 돌던 FastAPI + Agent + Tool + Memory 구조를, 서버나 클라우드에서 반복 가능하게 실행되도록 패키징하고 실행하는 과정입니다. FastAPI 공식 문서는 컨테이너 이미지 배포를 Kubernetes 같은 오케스트레이터나 클라우드 컨테이너 런타임에서 쓰기 좋은 기본 방식으로 설명하고, Docker 공식 문서는 Dockerfile이 소스 코드를 이미지로 빌드하기 위한 텍스트 기반 명령 파일이라고 정의합니다. (FastAPI)

쉽게 말하면 이겁니다.

  • 로컬: 내 맥북에서만 잘 돌면 됨
  • 배포: 어디서 돌려도 같은 방식으로 실행돼야 함

그래서 배포는 “올리는 법”이라기보다
실행 환경을 고정하는 법에 더 가깝습니다.


왜 Docker가 좋은 시작점일까

FastAPI 공식 문서는 컨테이너 이미지 기반 배포가 보안, 재현성, 단순성 측면에서 장점이 있다고 설명합니다. 또한 “대부분의 경우 하고 싶은 방식”이라고 표현할 정도로 기본 경로로 제시합니다. Docker 문서도 Dockerfile을 통해 빌드 절차를 코드처럼 정의할 수 있다고 설명하죠. (FastAPI)

LangChain 백엔드에서 Docker가 특히 좋은 이유는 이렇습니다.

  • Python 버전 고정
  • 패키지 버전 고정
  • 환경변수 주입 방식 통일
  • 로컬/서버 실행 방식 유사
  • FastAPI + Uvicorn + LangChain 조합을 통째로 재현 가능

즉, Docker는 “배포용 기술”이기도 하지만,
더 본질적으로는 실행 환경을 명시하는 문서이기도 합니다.


가장 현실적인 기본 구조

앞 글에서 설정을 core/config.py로 뺐다면, 배포 단계에서도 그 흐름을 그대로 살리는 게 좋습니다. 검색에 잘 걸리는 글은 구조가 선명해야 한다는 메모 방향처럼, 코드 구조도 배포 구조도 “역할이 보이게” 나뉘어 있는 편이 이해와 유지보수에 유리합니다.

project/
├── app/
│   ├── main.py
│   ├── core/
│   │   └── config.py
│   ├── routers/
│   ├── services/
│   ├── agents/
│   ├── tools/
│   └── schemas/
├── requirements.txt
├── Dockerfile
├── .dockerignore
├── docker-compose.yml
└── .env

이 정도면 충분히 오래 갑니다.


1. 배포용 Dockerfile 작성하기

FastAPI 공식 문서는 FastAPI용 Docker 이미지를 빌드할 때 공식 Python 이미지를 기반으로 시작하는 예시를 제공합니다. Dockerfile 지시어는 위에서 아래 순서대로 실행되고, FROM이 베이스 이미지를 정한다고 Docker 문서가 설명합니다. 또한 Docker는 EXPOSE, ENV, CMD 같은 지시어가 이미지 실행 구성을 정의한다고 안내합니다. (FastAPI)

가장 무난한 출발점은 이런 식입니다.

FROM python:3.11-slim

WORKDIR /app

ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1

COPY requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir --upgrade pip \
    && pip install --no-cache-dir -r /app/requirements.txt

COPY ./app /app/app

EXPOSE 8000

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

왜 이렇게 쓰는가

  • python:3.11-slim
    Python 기반 이미지를 작게 시작하기 좋습니다. FastAPI 공식 예시도 공식 Python 이미지를 기반으로 Dockerfile을 시작합니다. (FastAPI)
  • WORKDIR /app
    이후 작업 디렉토리를 고정합니다. Dockerfile은 명령을 순서대로 적용하므로 작업 디렉토리를 먼저 정해두는 게 자연스럽습니다. (Docker Documentation)
  • COPY requirements.txt 후 pip install
    의존성 레이어를 먼저 만들어두면 코드만 바뀔 때 캐시 활용이 유리합니다. 이건 Docker 빌드 일반 관행과도 맞습니다. (Docker Documentation)
  • EXPOSE 8000
    컨테이너가 어떤 포트를 쓸지 이미지 수준에서 표현합니다. Docker 문서는 EXPOSE가 컨테이너가 수신할 포트를 나타내는 구성이라고 설명합니다. (Docker Documentation)
  • CMD ["uvicorn", ...]
    컨테이너 기본 실행 명령입니다. Docker 문서는 CMD가 기본 실행 커맨드를 설정한다고 설명합니다. (Docker Documentation)

2. .dockerignore는 꼭 두자

반응형

Docker 빌드는 컨텍스트 전체를 보냅니다. 그래서 불필요한 파일이 많으면 이미지 빌드가 느려지고, 의도치 않은 파일이 같이 들어갈 수 있습니다. Docker 빌드 개념 문서는 Dockerfile과 빌드 컨텍스트를 함께 설명하고, 불필요한 컨텍스트를 줄이는 게 일반적으로 유리합니다. (Docker Documentation)

__pycache__/
*.pyc
*.pyo
*.pyd
.venv/
.env
.git/
.gitignore
.idea/
.vscode/
tests/

특히 .env는 이미지 안에 복사하지 않는 편이 좋습니다.
환경변수는 런타임에 주입하는 쪽이 더 안전합니다.


3. .env와 런타임 환경변수는 어떻게 나눌까

이전 글에서 설정 관리를 다뤘죠.
여기서 중요한 건 한 가지입니다.

이미지에는 비밀을 굽지 않는다.

FastAPI settings 문서는 .env와 환경변수를 설정 소스로 사용할 수 있다고 설명하고, Docker 문서는 ENV 지시어로 런타임 환경변수를 설정할 수 있다고 설명합니다. 하지만 민감한 값은 보통 이미지 안 하드코딩이 아니라 실행 시 주입하는 편이 더 안전합니다. (Docker Documentation)

좋은 패턴은 이렇습니다.

로컬 개발

  • .env 사용

서버/운영

  • 컨테이너 실행 시 환경변수 주입
  • Compose environment 또는 env_file
  • 클라우드 시크릿 매니저/환경변수 사용

예시 .env:

APP_NAME=Internal Assistant API
APP_ENV=dev
DEBUG=true

OPENAI_API_KEY=your_openai_api_key
DEFAULT_MODEL=gpt-4o-mini
EMBEDDING_MODEL=text-embedding-3-small

LANGSMITH_TRACING=true
LANGSMITH_PROJECT=internal-assistant-dev

DEFAULT_TIMEOUT_SECONDS=30
ENABLE_STREAMING=true
ENABLE_SHORT_TERM_MEMORY=true
DEFAULT_THREAD_PREFIX=assistant

4. Docker Compose로 실행하기

Docker Compose는 여러 서비스, 네트워크, 볼륨 구성을 정의하는 방식입니다. Docker 공식 문서는 Compose Specification이 최신 권장 포맷이라고 설명합니다. (Docker Documentation)

LangChain 백엔드 하나만 있더라도 Compose는 꽤 편합니다.

  • 포트 노출
  • 환경변수 주입
  • 재시작 정책
  • 나중에 Redis/Postgres 추가하기 쉬움

예시:

services:
  assistant-api:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: internal-assistant-api
    ports:
      - "8000:8000"
    env_file:
      - .env
    restart: unless-stopped

실행:

docker compose up --build

이 구조가 좋은 이유는,
나중에 메모리 persistent storage나 DB가 붙어도 자연스럽게 확장되기 때문입니다.

예를 들면 다음 단계에선 이런 식으로 갑니다.

  • assistant-api
  • postgres
  • redis

그리고 Compose가 그 연결을 같이 관리해줍니다.


5. Uvicorn은 어떻게 실행하는 게 좋을까

FastAPI 공식 문서는 원격 서버에서 FastAPI를 실행하려면 ASGI 서버가 필요하고, 대표적으로 Uvicorn을 쓴다고 설명합니다. 또한 worker 프로세스를 늘리는 방식도 별도 문서로 설명합니다. (FastAPI)

로컬 개발

uvicorn app.main:app --reload

컨테이너/운영 기본형

uvicorn app.main:app --host 0.0.0.0 --port 8000

멀티워커 예시

uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 2

Uvicorn worker는 CPU 활용과 동시성 처리량을 높이는 데 도움이 될 수 있습니다. FastAPI는 worker 프로세스를 사용하는 여러 전략을 설명하지만, 구체적인 worker 수는 서버 리소스와 워크로드에 따라 달라집니다. (FastAPI)

여기서 중요한 감각은 이겁니다.

  • 무조건 worker 많이가 정답은 아니다
  • LLM 백엔드는 외부 API 대기 시간이 많아서 CPU 바운드 서버와 다를 수 있다
  • 스트리밍이 많다면 worker/connection 특성을 같이 봐야 한다

즉 처음엔 단순하게 가는 게 좋습니다.


6. health check는 최소한 꼭 두자

배포하고 나면 제일 먼저 확인하는 게 “살아 있나”입니다.
FastAPI는 단순 JSON endpoint를 만들기 쉽기 때문에 /health 하나쯤은 반드시 두는 게 좋습니다. (FastAPI)

예시:

from fastapi import FastAPI

app = FastAPI()

@app.get("/health")
def health():
    return {"status": "ok"}

나중에 조금 더 나아가면 다음도 넣을 수 있습니다.

  • 앱 버전
  • 환경(dev/staging/prod)
  • 모델명
  • tracing on/off
  • dependency 상태 간단 점검

하지만 처음엔 {"status":"ok"}만 있어도 충분합니다.


7. 배포 전 꼭 확인해야 하는 운영 체크리스트

FastAPI 배포 개념 문서는 운영에서 보안, 시작 시 실행, 재시작, 복제(worker/process), 메모리, 사전 단계 같은 개념을 함께 고려하라고 설명합니다. 특히 마이그레이션 같은 사전 단계는 여러 프로세스가 동시에 돌지 않게 주의해야 한다고 합니다. (FastAPI)

그래서 저는 배포 전 체크리스트를 이렇게 봅니다.

필수

  • OPENAI_API_KEY 주입 확인
  • /health 확인
  • DEFAULT_MODEL 값 확인
  • 로그가 stdout으로 잘 나오는지 확인
  • response_model 계약 깨지지 않는지 확인

있으면 좋은 것

  • LANGSMITH_TRACING 환경 분리
  • dev/staging/prod 프로젝트명 분리
  • streaming endpoint 테스트
  • timeout 기본값 설정
  • request ID 로그 확인

나중에 꼭 필요한 것

  • persistent checkpointer
  • secrets 관리
  • reverse proxy / HTTPS
  • autoscaling 또는 worker 전략
  • 재시작 정책

8. FastAPI + LangChain 배포에서 자주 하는 실수

실수 1. .env를 이미지 안에 복사한다

이건 초보 때 진짜 많이 합니다.
이미지에 민감 정보가 들어가면 관리가 어려워집니다.

실수 2. 로컬 전용 --reload를 운영에 그대로 쓴다

--reload는 개발 편의 기능입니다. 운영 기본 실행은 다르게 보는 게 맞습니다. FastAPI는 개발과 배포 문서를 분리해서 설명합니다. (FastAPI)

실수 3. worker 수를 감으로 크게 잡는다

FastAPI도 worker 전략을 설명하지만, 실제 적정 수는 워크로드에 따라 달라집니다. (FastAPI)

실수 4. build 변수와 runtime 변수 구분을 안 한다

Docker는 ARG와 ENV가 다르다고 설명합니다. 빌드 시점 값과 실행 시점 값을 구분해야 합니다. (Docker Documentation)

실수 5. health endpoint 없이 배포한다

이건 운영 중 문제를 볼 때 꽤 불편합니다.


9. 비교: 로컬 실행 vs Docker 배포

구분로컬 개발Docker 배포

실행 방식 uvicorn --reload uvicorn 또는 컨테이너 기본 CMD
설정 관리 .env 직접 사용 런타임 환경변수 주입 중심
재현성 내 컴퓨터 기준 어디서나 같은 이미지 기준
확장성 단일 프로세스 중심 Compose/오케스트레이터 확장 가능
운영 적합성 낮음 높음

이런 비교표는 검색에도 유리하고, 독자가 “왜 지금 이 단계가 필요한지”를 이해하는 데 도움이 됩니다. 업로드된 메모에서도 비교표와 질문형 제목, FAQ가 AI 검색형 문서에 잘 맞는다고 정리돼 있었습니다.


10. 배포용 전체 예제 코드

Dockerfile

FROM python:3.11-slim

WORKDIR /app

ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1

COPY requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir --upgrade pip \
    && pip install --no-cache-dir -r /app/requirements.txt

COPY ./app /app/app

EXPOSE 8000

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

.dockerignore

__pycache__/
*.pyc
.venv/
.env
.git/
tests/

docker-compose.yml

services:
  assistant-api:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: internal-assistant-api
    ports:
      - "8000:8000"
    env_file:
      - .env
    restart: unless-stopped

health endpoint 예시

from fastapi import FastAPI

app = FastAPI()

@app.get("/health")
def health():
    return {"status": "ok"}

실행:

docker compose up --build

확인:

curl http://127.0.0.1:8000/health

FAQ

Q. LangChain 백엔드는 꼭 Docker로 배포해야 하나요?

꼭 그렇지는 않습니다. 하지만 FastAPI 공식 문서는 컨테이너 이미지 배포를 대부분의 경우에 적합한 기본 방식으로 소개합니다. 재현성과 환경 고정 측면에서 특히 유리합니다. (FastAPI)

Q. .env 파일을 서버에도 같이 올리면 안 되나요?

가능은 하지만, 운영에선 보통 런타임 환경변수나 시크릿 매니저를 쓰는 편이 더 안전합니다. 민감 정보가 이미지나 저장소에 섞이지 않게 하는 게 중요합니다. Docker는 ENV와 환경변수 주입을 통해 실행 시 값을 넣을 수 있게 합니다. (Docker Documentation)

Q. Uvicorn worker는 몇 개가 정답인가요?

정답은 없습니다. FastAPI는 worker 프로세스 사용 전략을 설명하지만, 실제 적정 worker 수는 CPU, 메모리, 요청 패턴, 스트리밍 여부에 따라 달라집니다. (FastAPI)

Q. Docker Compose는 개발용 아닌가요?

Compose는 여러 서비스와 네트워크, 볼륨 구성을 정의하는 최신 권장 포맷입니다. 작은 운영 환경이나 개발/스테이징 환경에서도 충분히 유용합니다. (Docker Documentation)

Q. LangChain tracing 설정도 같이 배포해야 하나요?

네. 개발, 스테이징, 운영에서 LangSmith 프로젝트명을 나눠두는 편이 좋습니다. tracing 자체는 운영에서 매우 유용하지만, 환경 분리를 안 하면 trace가 섞여서 보기 어려워집니다.


핵심 요약

  • LangChain 백엔드는 Docker + FastAPI + Uvicorn + 환경변수 주입 구조가 가장 현실적인 시작입니다. (FastAPI)
  • Dockerfile은 공식 Python 이미지 기반으로 시작하고, COPY requirements.txt → pip install → COPY app 순서가 캐시 활용에 유리합니다. (FastAPI)
  • .env는 로컬 개발엔 편하지만, 운영에선 런타임 환경변수 주입이 더 안전한 경우가 많습니다. (Docker Documentation)
  • Uvicorn worker 수는 정답이 없고, 서버 리소스와 워크로드에 맞춰 조정해야 합니다. (FastAPI)
  • health endpoint, 로그, tracing, 설정 분리는 배포 초반부터 같이 가져가는 편이 좋습니다.
  • 검색에 잘 걸리는 글처럼, 배포 구조도 정의가 명확하고 역할이 분리돼 있어야 사람이든 AI든 이해하기 쉽습니다.

출처

  • FastAPI Docker 배포 문서: FastAPI 앱을 Docker 이미지로 빌드하는 기본 패턴 소개. (FastAPI)
  • FastAPI Deployment Concepts / Manually / Workers: ASGI 서버, Uvicorn, worker, 운영 고려사항 설명. (FastAPI)
  • Docker Dockerfile reference / overview / build variables / Compose reference: Dockerfile 지시어, CMD, EXPOSE, ENV, ARG, Compose 포맷 설명. (Docker Documentation)
  • 업로드해주신 “AI 검색에 잘 걸리는 글” 메모: 질문형 제목, 첫 문단 정답 요약, 비교표, FAQ, 구조화된 글쓰기 전략 반영.

LangChain, FastAPI, Docker, Uvicorn, docker compose, LangChain Backend, AI Agent, 배포전략, 백엔드개발, 주니어개발자

※ 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/06   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함
반응형