Replit Agent 앱을 Fly.io GPU 추론 서버로 전환하기
— vLLM·Ollama 실전 배포와 2026년 7월 이전에 알아야 할 것들
2026년 7월, Fly.io GPU가 사라집니다. 그 전에 지금 이 패턴을 익혀두면 어떤 플랫폼으로 옮기든 재사용할 수 있는 이유를 설명해 드릴게요.
저도 처음에 Replit Agent로 챗봇 앱을 뚝딱 만들어 놓고 "이걸 어떻게 GPU 서버에 연결하지?" 하고 한참 헤맸었는데요. Replit이 앱 코드를 순식간에 만들어준다 해도, AI 추론을 붙이는 인프라 부분은 여전히 손으로 짜야 합니다. 이 글은 그 두 세계를 연결하는 전체 워크플로를 실전 코드와 함께 풀어낸 내용입니다.
이 글에서 다루는 것:
- Replit → GitHub → Fly.io GPU로 이어지는 2단계 배포 패턴 전체
- vLLM과 Ollama를 컨테이너에 올려 LLM 추론 서버로 만드는 방법
- Fly.io GPU 종료(2026-07-31)라는 현실과, 그 이후를 대비한 대안 플랫폼
핵심 개념
Replit Agent: 자연어로 풀스택 앱을 만드는 AI 코딩 에이전트
Replit Agent는 자연어 프롬프트만으로 FastAPI 백엔드부터 React 프론트엔드까지 전체 코드를 생성하고, Replit 환경에서 바로 실행해 주는 도구입니다. 생성된 코드는 GitHub 리포지토리로 바로 push하거나 Docker 이미지로 패키징할 수 있어서, 외부 인프라와 연결하기가 비교적 수월한 편이에요.
핵심 아이디어: Replit Agent가 만든 백엔드 코드에서 LLM API 엔드포인트 URL만 환경변수로 분리해 두면, Fly.io GPU 서버 주소로 교체하는 것만으로 추론 경로를 바꿀 수 있습니다. 클라이언트 코드는 한 줄도 건드릴 필요가 없어요.
Fly.io GPU Machine: 컨테이너 친화적 GPU 서버 (단, 2026-07-31까지)
Fly.io GPU Machine은 NVIDIA A10, L40S, A100-40GB, A100-80GB를 제공하는 컨테이너형 VM입니다. fly.toml에 vm.size만 지정하면 CUDA 드라이버가 사전 탑재된 상태로 올라온다는 게 가장 큰 장점이었는데요.
여기서 한 가지 반드시 알고 가셔야 할 사항이 있습니다. 2025년 2월, Fly.io는 공식 블로그를 통해 GPU 전략 실패를 인정하고, 2026년 7월 31일부로 GPU Machine을 완전 폐기한다고 발표했습니다. GPU 워크로드 시장이 예상보다 훨씬 좁은 니치였고, 대부분의 개발자는 직접 GPU를 돌리기보다 OpenAI·Anthropic 같은 API를 선호한다는 게 이유였어요. 솔직히, 납득이 가는 판단이기도 합니다.
그렇다고 지금 당장 이 패턴이 쓸모없다는 건 아닙니다. 2026년 7월까지는 여전히 유효하고, 여기서 익히는 Dockerfile 작성·환경변수 분리·CI/CD 구성 방식은 Modal이나 RunPod로 이전할 때도 그대로 재활용됩니다.
GPU 가용 리전이 제한적이라는 점도 알아두시면 좋습니다.
- A100-80GB:
iad,sjc,syd,ams리전만 지원 - A10·L40S:
ord리전만 지원
AI 추론 엔진: vLLM과 Ollama 중 어떤 걸 골라야 할까
두 도구 모두 /v1/chat/completions 엔드포인트를 노출하기 때문에, OpenAI SDK를 쓰는 클라이언트 코드는 URL만 바꿔서 그대로 연결됩니다. 차이는 목적에 있어요.
vLLM은 PagedAttention(GPU 메모리를 페이지 단위로 동적 할당해 동시 요청 처리 효율을 크게 높이는 기법)을 사용하는 고처리량 추론 엔진으로, 프로덕션 환경에 적합합니다. Ollama는 llama.cpp 기반으로 설정이 간단하고 다양한 모델을 빠르게 올릴 수 있어서, 개발·테스트나 중소 규모 서비스에 더 잘 맞습니다. 처음 이 스택을 시험해 보는 단계라면 Ollama로 시작해서 필요하면 vLLM으로 올라가는 방식이 편하더라고요.
실전 적용
예시 1: Replit에서 코드 내보내기
먼저 Replit Agent에서 앱을 생성한 뒤, 대시보드의 Connect to GitHub 버튼으로 리포지토리를 연동하고 push합니다. 이때 가장 중요한 작업이 하나 있는데요, 추론 엔드포인트 URL을 반드시 환경변수로 분리해 두는 겁니다. 나중에 Fly.io 주소로 바꿀 때 코드를 건드리지 않아도 됩니다.
# 추론 클라이언트 — URL을 환경변수로 분리해 두면 나중이 편합니다
import os
from openai import AsyncOpenAI
client = AsyncOpenAI(
base_url=os.environ["INFERENCE_BASE_URL"],
api_key=os.environ.get("INFERENCE_API_KEY", "none"),
)
async def chat(message: str) -> str:
response = await client.chat.completions.create(
model=os.environ.get("MODEL_NAME", "llama3"),
messages=[{"role": "user", "content": message}],
)
return response.choices[0].message.content예시 2: Fly.io GPU 서버 배포 구성
flyctl 설치 및 앱 초기화
curl -L https://fly.io/install.sh | sh
fly auth login
# --no-deploy: 바로 배포하지 않고 설정 파일만 생성합니다
fly launch --no-deploy --region ordfly.toml 설정
app = "my-ai-inference-app"
primary_region = "ord"
[vm]
size = "a10"
[[mounts]]
source = "model_storage"
destination = "/models"
[[services]]
internal_port = 8000
protocol = "tcp"
[[services.ports]]
port = 443
handlers = ["tls", "http"]
[[services.ports]]
port = 80
handlers = ["http"]| 설정 항목 | 값 예시 | 설명 |
|---|---|---|
vm.size |
a10, l40s, a100-40gb, a100-80gb |
GPU 머신 종류 |
primary_region |
ord, iad, sjc |
GPU 가용 리전만 지정 가능 |
mounts.destination |
/models |
대형 모델 파일 영구 저장 경로 |
[[services]] 블록이 없으면 외부에서 HTTP 요청을 받을 수 없습니다. 처음 fly.toml을 생성하면 이 블록이 빠져 있는 경우가 있으니 확인해보시면 좋습니다.
vLLM Dockerfile
FROM vllm/vllm-openai:latest
ENV MODEL_NAME="meta-llama/Llama-3-8B-Instruct"
EXPOSE 8000
CMD ["python", "-m", "vllm.entrypoints.openai.api_server", \
"--model", "meta-llama/Llama-3-8B-Instruct", \
"--host", "0.0.0.0", \
"--port", "8000"]중요: HuggingFace 토큰을 Dockerfile에 직접 적어두면 이미지 레이어에 토큰이 그대로 남습니다. 반드시 아래 방식으로 시크릿을 주입하는 것이 안전합니다.
fly secrets set HF_TOKEN=hf_your_token_here컨테이너 안에서는 os.environ["HF_TOKEN"]으로 접근하면 됩니다.
Ollama Dockerfile
여기서 한 가지 함정이 있는데요. ollama serve만 실행하면 컨테이너가 뜨긴 하지만 모델이 로드되어 있지 않아 요청을 받아도 아무것도 반환하지 않습니다. 모델을 미리 pull하는 entrypoint가 필요합니다.
FROM ollama/ollama:latest
EXPOSE 11434
ENTRYPOINT ["/bin/sh", "-c", "ollama serve & sleep 5 && ollama pull llama3 && wait"]배포 실행
fly deploy배포가 완료되면 Replit 앱의 환경변수만 교체해 주면 됩니다.
INFERENCE_BASE_URL=https://my-ai-inference-app.fly.dev/v1
MODEL_NAME=meta-llama/Llama-3-8B-Instruct예시 3: Scale-to-Zero로 GPU 유휴 비용 줄이기
A100 기준 시간당 $2.5~3.5 수준의 비용이 발생하기 때문에, 요청이 없는 시간대에 VM을 내려두는 패턴이 많이 쓰입니다.
# VM 인스턴스 수를 0으로 줄여 과금을 멈춥니다 (앱이 삭제되는 건 아닙니다)
fly scale count 0
# 다시 필요할 때 기동
fly scale count 1자동 재기동이 필요하다면 Fly.io Machines API를 활용해 HTTP 요청이 들어올 때 VM을 깨우도록 구성할 수 있습니다. 다만 콜드 스타트 시 수십 초에서 수 분까지 대기가 발생한다는 점은 감수해야 합니다. 실무에서는 이 지연이 생각보다 꽤 크게 느껴지더라고요. 레이턴시가 중요한 서비스라면 최소 1대는 상시 유지하는 편이 낫습니다.
예시 4: GitHub Actions로 CI/CD 자동화
# .github/workflows/fly-deploy.yml
name: Deploy to Fly.io
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: superfly/flyctl-actions/setup-flyctl@master
- name: Deploy
run: fly deploy --remote-only
env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}장단점 분석
장점
| 항목 | 내용 |
|---|---|
| 빠른 프로토타이핑 | Replit Agent로 수 분 내 앱 코드 완성, GPU 서버로 바로 확장 가능 |
| 컨테이너 친화적 | Dockerfile 하나로 CUDA 드라이버 포함 환경 재현 |
| OpenAI 호환 API | vLLM·Ollama 모두 /v1/chat/completions 지원, 클라이언트 코드 무수정 전환 |
| Scale-to-Zero | 유휴 GPU 비용 완전 제거 가능 |
| 모델 영구 저장 | Fly Volume(VM 재기동 후에도 데이터가 유지되는 퍼시스턴트 블록 스토리지)으로 대형 모델 재다운로드 없이 재사용 |
단점 및 주의사항
| 항목 | 내용 | 대응 방안 |
|---|---|---|
| 서비스 종료 임박 | Fly.io GPU 2026-07-31 폐기 예정 | Modal, RunPod, Replicate로 마이그레이션 계획 미리 수립 |
| GPU 가용 리전 제한 | A100-80GB는 4개 리전, A10·L40S는 ord만 지원 | 배포 전 fly platform vm-sizes로 가용 리전 확인 |
| 콜드 스타트 지연 | Scale-to-zero 후 재기동 시 수십 초~수 분 대기 | 레이턴시 민감한 서비스는 최소 1대 상시 유지 |
| 모델 파일 크기 | LLM은 수십 GB → 초기 배포 시 볼륨 설정 필수 | [[mounts]]로 Fly Volume 연결 |
| 비용 | A100-40GB 기준 약 $2.5~3.5/hr | 공식 Pricing 페이지에서 최신 단가 확인 |
| Replit 코드 품질 | Agent 생성 코드는 프로덕션 보안·최적화 검토 필수 | 인증, 입력 검증, 에러 핸들링 수동 검토 |
| GPU 드라이버 호환성 | 베이스 이미지 따라 호환 여부 달라짐 | Ubuntu 22.04 기반 이미지(nvidia/cuda:12.x) 사용 |
실무에서 가장 흔한 실수
-
GPU 리전 확인 없이
fly launch를 실행하는 경우 — GPU가 지원되지 않는 리전에 앱이 생성되어 배포 실패가 발생합니다.fly launch시--region플래그를 명시해두면 이 문제를 피할 수 있습니다. -
Fly Volume 마운트 없이 대형 모델을 배포하는 경우 — VM이 재시작될 때마다 수십 GB의 모델을 다시 다운로드하게 됩니다.
[[mounts]]설정을 빠뜨리면 비용과 시간 모두 낭비됩니다. -
Replit Agent가 생성한 코드를 검증 없이 프로덕션에 올리는 경우 — 인증 미적용, SQL Injection 취약점, 하드코딩된 시크릿 등이 남아 있는 경우가 종종 있습니다. Agent 생성 코드는 보안 리뷰를 한 번 거치는 편이 안전합니다.
마치며
지금 GPU 추론 서버를 처음 만드는 팀이라면 Fly.io로 이 패턴을 익히고, 2026년 7월 전에 Modal 또는 RunPod 계정을 미리 만들어 두는 것을 권해드립니다. 마이그레이션할 때 Dockerfile과 환경변수 구성은 거의 그대로 가져갈 수 있으니, 지금 배운 내용이 헛되지 않습니다.
지금 바로 시작해볼 수 있는 3단계:
- Replit Agent로 FastAPI + React 챗봇 앱을 생성하고, 추론 엔드포인트 URL을
INFERENCE_BASE_URL환경변수로 분리한 뒤 GitHub에 연동합니다. flyctl을 설치하고fly launch --no-deploy --region ord로 초기화한 다음,fly.toml에vm.size,[[mounts]],[[services]]블록을 추가하고fly deploy를 실행합니다.- Fly.io GPU 종료 공지 스레드를 한 번 읽고, Modal이나 RunPod 무료 티어를 미리 살펴봅니다.
다음 글: Fly.io GPU 종료 이후 — Modal·RunPod·Google Cloud Run으로 AI 추론 서버를 마이그레이션하는 방법과 플랫폼별 비용·콜드스타트 비교