🚀

초기 Rails 앱 디플로이 SaaS 비교

Fly.io, Render, DigitalOcean, Fargate, Railway, Heroku 등 실전 비교

Rails 앱을 처음 배포할 때 가장 고민되는 것이 "어디에 올릴까?"입니다. Heroku가 무료 티어를 폐지한 이후, Fly.io, Render, Railway 등 대안이 급부상했습니다.

비교 기준: "1인/소규모 팀의 Rails 8 + SQLite 프로젝트를 가장 빨리, 가장 싸게, 가장 안정적으로 배포할 수 있는 곳은 어디인가?"

서비스 최소 비용 Docker SQLite 지원 볼륨(영구 스토리지) Rails 8 친화도 적합한 단계
Fly.io ~$5/월 O O (볼륨 마운트) O 높음 (공식 지원) MVP → 프로덕션
Render 무료 티어 있음 O 제한적 (영구 디스크 없음) X (무료) / O (유료) 중간 MVP
DigitalOcean (Droplet) $4~6/월 O (직접 설정) O (로컬 디스크) O (로컬 SSD) 높음 (자유도 최고) 프로덕션
Railway 사용량 과금 O 제한적 제한적 중간 빠른 프로토타이핑
Heroku $7/월~ O X (ephemeral filesystem) X 낮음 (PostgreSQL 강제) 레거시
AWS Fargate $10+/월 O 복잡 (EFS 필요) O (EFS) 낮음 (복잡) 대규모

Fly.io vs DigitalOcean — 실전 운영 비교

이 프로젝트는 Fly.io와 DigitalOcean Droplet을 동시 운영하고 있습니다. Rails 8 + SQLite + Solid Queue 구성에서 체감한 차이:

Fly.io 장점: 배포가 간단 (fly deploy 한 줄), 글로벌 엣지 네트워크, SSL 자동, Kamal 대비 설정이 적음

Fly.io 단점: 볼륨 I/O 레이턴시가 DigitalOcean보다 높음 → SQLite database locked 에러 빈발 (아래 상세 설명)

DigitalOcean 장점: 로컬 SSD로 I/O 성능이 안정적, 가격 대비 성능 우수, 완전한 제어권

DigitalOcean 단점: 서버 설정을 직접 해야 함 (Kamal 또는 Docker Compose), SSL은 직접 설정 또는 Cloudflare


⚠️ Fly.io + SQLite + Solid Queue = "database is locked" 문제

Rails 8의 SQLite + Solid Queue 구성을 Fly.io에서 운영하면, "SQLite3::BusyException: database is locked" 에러가 빈번하게 발생할 수 있습니다. DigitalOcean에서는 같은 구성에서 거의 발생하지 않는 에러입니다.

원인 분석:

SQLite는 동시에 1개의 writer만 허용합니다(WAL 모드에서도 write lock은 1개). Solid Queue는 지속적으로 DB에 write하는데, 웹 프로세스도 동시에 write하면 lock 충돌이 발생합니다.

Fly.io에서 특히 심한 이유:

  1. Fly.io 볼륨 I/O 성능: DigitalOcean Droplet은 로컬 SSD, Fly.io는 네트워크 연결 볼륨(Network-attached volume). 같은 busy_timeout 설정이라도 lock 잡는 시간이 다르다:
  • DigitalOcean: lock 잡는 시간 ms 단위 → timeout 안에 lock 해제됨 → 에러 없음

  • Fly.io: lock 잡는 시간 수십~수백ms → timeout 초과 → BusyException 발생

둘 다 WAL 모드 + 동일한 timeout 설정인데, I/O latency 차이 하나로 결과가 완전히 달라진다
2. Solid Queue + Web이 같은 DB 파일 공유: 두 프로세스가 동시에 write하면 BusyException 발생. DigitalOcean의 로컬 SSD는 latency가 낮아서 lock이 빨리 풀리지만, Fly.io 볼륨은 네트워크 스토리지라 lock 보유 시간이 김
3. WAL 모드 미설정 또는 busy_timeout 부족: Rails 8은 기본으로 WAL 모드를 설정하지만, busy_timeout(lock 대기 시간)이 짧으면 에러 발생. 기본값 5000ms로는 부족할 수 있음

해결 방법:

# config/database.yml
production:
  adapter: sqlite3
  database: /data/production.sqlite3
  pool: 5
  timeout: 10000  # busy_timeout 10초로 증가
  pragmas:
    journal_mode: wal
    synchronous: normal
    busy_timeout: 10000

  • busy_timeout을 10000ms(10초)로 증가

  • Solid Queue용 DB를 별도 파일로 분리하는 것도 효과적 (queue.sqlite3, cache.sqlite3, cable.sqlite3)

  • 그래도 문제가 계속되면 DigitalOcean Droplet + Kamal 조합이 SQLite 운영에는 더 안정적

구조 다이어그램

배포 난이도 랭킹 (쉬움 → 어려움)
쉬움 (Easy)
Heroku Render Railway
git push만으로 배포 완료. 인프라 지식 불필요
보통 (Medium)
Fly.io DigitalOcean App Platform
Dockerfile 이해 필요. CLI 기반 설정
고급 (Advanced)
Kamal + VPS AWS Fargate
Docker, 네트워크, SSL 등 인프라 전반 이해 필수
가격 vs 제어 매트릭스
↑ 풀 컨트롤
저비용 + 높은 제어
Kamal + Hetzner
~$5/월, SSH 풀 액세스
고비용 + 높은 제어
AWS Fargate
$30+/월, 엔터프라이즈급
저비용 + 낮은 제어
Render Free
Railway Free
$0, 제한된 리소스
중간 비용 + 낮은 제어
Heroku
DigitalOcean
$7~25/월, PaaS 관리형
← 저비용 ↓ 낮은 제어 고비용 →
Rails 배포 플로우 (간소화)
📝
코드
🐳
Dockerfile
🔨
이미지 빌드
📦
레지스트리 Push
🚀
플랫폼 배포
🔒
도메인 + SSL
🌐
Live!
* PaaS(Heroku, Render 등)는 이 과정을 자동화합니다
추천 가이드
사이드 프로젝트
Fly.io Railway
- 무료 또는 $5/월 이하
- 빠른 프로토타이핑에 최적
- Dockerfile만 있으면 OK
스타트업
Render Fly.io
- $7~25/월
- 관리형 DB, 자동 SSL
- 팀 협업 기능 지원
프로덕션
Kamal + Hetzner Kamal + DO
- $5~20/월 (VPS 비용만)
- SSH 풀 액세스, 완전한 제어
- Rails 8 공식 배포 도구
핵심 포인트
Rails 8부터 Kamal이 기본 배포 도구 -- docker build + SSH 배포를 자동화
PaaS는 편리하지만 비용이 빠르게 증가 -- 트래픽 증가 시 VPS 전환 고려
무료 플랜은 콜드 스타트(cold start) 지연이 있음 -- 프로덕션에는 부적합

핵심 포인트

1

Dockerfile 작성 (Rails 7.1+는 자동 생성)

2

환경변수 설정 (DATABASE_URL, SECRET_KEY_BASE, RAILS_MASTER_KEY)

3

PostgreSQL/SQLite 데이터베이스 설정

4

에셋 프리컴파일 + 이미지 빌드

5

PaaS에 배포 (git push 또는 Docker push)

6

커스텀 도메인 + SSL 설정

7

모니터링 + 로그 확인

사용 사례

사이드 프로젝트 빠른 배포 MVP 검증용 최소 비용 배포 팀 프로젝트 스테이징 환경 프로덕션 서비스 운영