☁️ 클라우드

Fly.io

Fly.io

전 세계 엣지에 앱을 배포하는 플랫폼. 컨테이너 기반.

상세 설명

Fly.io는 전 세계 35개 이상의 리전에 애플리케이션을 엣지에 배포할 수 있는 클라우드 플랫폼입니다. Firecracker microVM 기술을 사용하여 컨테이너보다 빠른 부팅과 강력한 격리를 제공하며, 사용자와 가장 가까운 위치에서 앱을 실행합니다.

Fly.io의 핵심 특징:

  • 글로벌 엣지 배포: 전 세계 35+ 리전에 수 초 내 배포. 서울 리전 포함
  • Firecracker microVM: AWS가 Lambda에 사용하는 기술. 125ms 부팅
  • Anycast 네트워킹: 사용자를 가장 가까운 인스턴스로 자동 라우팅
  • Fly Machines: 밀리초 단위 프로비저닝. 필요 시 자동 시작/정지
  • Fly Postgres: 글로벌 분산 PostgreSQL 클러스터

요금제 특징:

  • 무료 티어: 3개 shared-cpu-1x VM, 160GB 아웃바운드 트래픽
  • 종량제: CPU/메모리 초 단위 과금. 정지 시 무과금
  • 스케일 투 제로: 트래픽 없을 때 자동 중지로 비용 절감

코드 예제

# Fly CLI 설치 (macOS) brew install flyctl # 로그인 fly auth login # 새 앱 생성 및 배포 (Dockerfile 기반) fly launch # ? Would you like to copy its configuration to the new app? Yes # ? Choose a region for deployment: nrt (Tokyo, Japan) # ? Would you like to set up a Postgresql database now? No # 배포 fly deploy # 앱 상태 확인 fly status # 로그 확인 fly logs # SSH 접속 fly ssh console # 환경 변수 설정 fly secrets set DATABASE_URL="postgres://..." # 스케일링 (인스턴스 수) fly scale count 3 # 리전 추가 (글로벌 배포) fly regions add icn # 서울 fly regions add sin # 싱가포르 fly regions add fra # 프랑크푸르트 # 머신 크기 조정 fly scale vm shared-cpu-2x --memory 1024 # 자동 스케일링 설정 fly autoscale set min=2 max=10 # PostgreSQL 생성 fly postgres create --name my-db --region nrt # 앱에 DB 연결 fly postgres attach my-db
# fly.toml - Fly.io 앱 설정 파일 app = "my-app" primary_region = "nrt" # 도쿄 (한국에서 가장 가까움) [build] dockerfile = "Dockerfile" [env] NODE_ENV = "production" PORT = "8080" [http_service] internal_port = 8080 force_https = true auto_stop_machines = true # 유휴 시 자동 정지 auto_start_machines = true # 요청 시 자동 시작 min_machines_running = 1 # 최소 1개는 항상 실행 processes = ["app"] [http_service.concurrency] type = "requests" hard_limit = 250 soft_limit = 200 [[services]] protocol = "tcp" internal_port = 8080 [[services.ports]] port = 80 handlers = ["http"] [[services.ports]] port = 443 handlers = ["tls", "http"] [[services.tcp_checks]] grace_period = "10s" interval = "15s" timeout = "2s" [[services.http_checks]] interval = "10s" timeout = "2s" grace_period = "5s" method = "GET" path = "/health" protocol = "http" [[vm]] cpu_kind = "shared" cpus = 1 memory_mb = 512 # 멀티 리전 배포 설정 [[regions]] region = "nrt" # 도쿄 count = 2 [[regions]] region = "icn" # 서울 (가능한 경우) count = 1 [[regions]] region = "sin" # 싱가포르 count = 1 # 볼륨 마운트 (영구 스토리지) [[mounts]] source = "data" destination = "/data" # 릴리스 명령어 (배포 후 실행) [deploy] release_command = "npm run db:migrate"
# Fly.io 멀티 리전 배포 전략 # 1. 리전별 인스턴스 배포 fly regions add nrt icn sin syd # 현재 리전 확인 fly regions list # Region Pool: # icn (Seoul) # nrt (Tokyo) # sin (Singapore) # syd (Sydney) # 2. 리전별 스케일링 fly scale count 2 --region nrt fly scale count 2 --region icn fly scale count 1 --region sin # 3. 리전별 환경 변수 (선택적) # Fly는 FLY_REGION 환경 변수를 자동 주입 # 앱 코드에서 활용 가능 # Node.js 예제 - 리전 인식 코드 cat <<'EOF' > server.js const express = require('express'); const app = express(); // Fly.io가 주입하는 환경 변수 const region = process.env.FLY_REGION || 'unknown'; const instanceId = process.env.FLY_ALLOC_ID || 'local'; app.get('/', (req, res) => { res.json({ message: 'Hello from Fly.io!', region: region, instance: instanceId, timestamp: new Date().toISOString() }); }); app.get('/health', (req, res) => { res.status(200).json({ status: 'healthy', region }); }); // 리전별 데이터 처리 app.get('/nearest', (req, res) => { // 사용자는 자동으로 가장 가까운 리전으로 라우팅됨 res.json({ message: `Served from ${region}`, latency: 'minimal' }); }); const port = process.env.PORT || 8080; app.listen(port, () => { console.log(`Server running in ${region} on port ${port}`); }); EOF # 4. Fly Replay - 요청을 다른 리전으로 리플레이 # 헤더로 특정 리전 강제 지정 curl -H "fly-replay: region=nrt" https://my-app.fly.dev/ # 앱 코드에서 리플레이 응답 # res.setHeader('fly-replay', 'region=nrt'); # 5. Fly Postgres 글로벌 분산 fly postgres create --name my-global-db fly postgres attach my-global-db # 읽기 전용 복제본 추가 fly volumes create pg_data --region sin --size 10 fly machine clone <primary-machine-id> --region sin # 애플리케이션에서 읽기/쓰기 분리 # PRIMARY: fly-replay 헤더로 primary 리전으로 라우팅 # REPLICA: 로컬 리전 복제본에서 읽기

실무 대화 예시

플랫폼 선택 회의
"Fly.io vs Vercel vs AWS 어떤 걸 써야 하나요?" "목적에 따라 다릅니다. Vercel은 프론트엔드/Next.js 특화, 서버리스 함수 위주예요. Fly.io는 풀 컨테이너 실행이라 백엔드 API, WebSocket, 상태 유지 앱에 좋습니다. AWS는 대규모 인프라 필요할 때요. 소규모 팀이 글로벌 서비스 빠르게 배포하려면 Fly.io가 딱이에요."
비용 최적화 논의
"Fly.io 비용 관리는 어떻게 하나요?" "스케일 투 제로가 핵심입니다. fly.toml에서 auto_stop_machines=true 설정하면 요청 없을 때 VM이 자동 정지되고 요금이 안 나갑니다. 다만 콜드 스타트가 있으니 min_machines_running=1로 최소 1개는 유지하세요. 개발 환경은 완전 정지해도 되고요."
아키텍처 리뷰
"글로벌 사용자 대상 API 레이턴시를 줄이고 싶어요." "Fly.io로 멀티 리전 배포하세요. 서울, 도쿄, 싱가포르에 인스턴스 두면 아시아 커버되고, Anycast로 사용자가 자동으로 가장 가까운 인스턴스에 연결됩니다. DB는 Fly Postgres 복제본을 각 리전에 두거나, 읽기 요청만 로컬에서 처리하는 패턴 쓰세요."
면접 질문
"Fly.io의 Firecracker microVM이 Docker 컨테이너와 다른 점이 뭔가요?" "Docker는 커널을 호스트와 공유하는데, Firecracker는 각 워크로드에 전용 미니 커널을 제공해서 보안 격리가 강력합니다. AWS Lambda, Fargate에서도 같은 기술 쓰고요. 부팅도 125ms로 컨테이너보다 빠를 수 있어요. 단점은 Docker 이미지를 그대로 못 쓰고 Fly가 변환합니다."

주의사항

⚠️
콜드 스타트: auto_stop_machines 활성화 시 정지된 VM 재시작에 수 초 걸립니다. 지연에 민감한 서비스는 min_machines_running을 설정하세요.
⚠️
볼륨 제약: Fly Volumes는 단일 리전/단일 인스턴스에 바인딩됩니다. 멀티 인스턴스 영구 스토리지가 필요하면 S3/R2 같은 오브젝트 스토리지 사용하세요.
⚠️
리전 가용성: 모든 리전이 항상 가용한 것은 아닙니다. 한국(icn) 리전은 아직 제한적일 수 있으니 도쿄(nrt)를 대안으로 고려하세요.
⚠️
무료 티어 제한: 3개 shared-cpu-1x VM, 256MB 메모리 제한이 있습니다. 프로덕션 워크로드는 유료 플랜 필수입니다.

관련 용어

더 배우기