본문으로 건너뛰기
김신건의 로그

[Rails] Rails 8: Solid Queue/Cache/Cable, Kamal, Propshaft

· 수정 · 📖 약 2분 · 725자/단어 #rails #rails8 #solid-queue #kamal
rails 8, solid queue, solid cache, solid cable, kamal deploy, propshaft, no PaaS

정의

**Rails 8 (2024 11월)**의 표어는 “No PaaS”다. Solid 시리즈로 Redis/외부 큐 의존을 제거하고, Kamal로 Docker 기반 자체 호스팅을 간단하게. 기존 Rails 7 앱은 점진 마이그레이션 가능.

Solid Trifecta

컴포넌트역할백엔드
Solid Queue백그라운드 잡DB
Solid CacheRails.cacheDB
Solid CableAction CableDB

세 가지 모두 DB 사용 → Redis 불필요. 비용·운영 단순화.

Solid Queue

rails-active-job에 표준 어댑터. Rails 8 새 앱 기본.

bin/rails solid_queue:install
# config/application.rb
config.active_job.queue_adapter = :solid_queue

설정:

# config/queue.yml
production:
  dispatchers:
    - polling_interval: 1
      batch_size: 500
  workers:
    - queues: "*"
      threads: 5
      processes: 1
      polling_interval: 0.1

워커:

bin/jobs
# 또는
bundle exec rake solid_queue:start

cron 같은 recurring:

# config/recurring.yml
production:
  daily_report:
    class: DailyReportJob
    schedule: every day at 9am
  cleanup:
    class: CleanupJob
    schedule: every 1 hour

특징:

  • 트랜잭션 안전 (같은 DB)
  • delayed/recurring 지원
  • queue prioritization
  • Sidekiq 만큼은 아니나 충분히 빠름

Solid Cache

# config/environments/production.rb
config.cache_store = :solid_cache_store

DB에 저장 → Redis 없이 캐시. 부분적 LRU 처리.

Rails.cache.write("key", "value", expires_in: 1.hour)
Rails.cache.read("key")
Rails.cache.fetch("key") { expensive_computation }

기존 Rails.cache API와 호환.

대규모 → Redis가 여전히 빠름. 작은 ~ 중규모는 충분.

Solid Cable

# config/cable.yml
production:
  adapter: solid_cable

Action Cable이 DB 통해 pub/sub. Redis 불필요.

3분 polling 기본 (config polling_interval).

Kamal 2

Docker 기반 단일 명령 배포.

bin/kamal init
# config/deploy.yml 생성

bin/kamal setup        # 첫 배포 (서버 setup + Docker 이미지 + 컨테이너)
bin/kamal deploy       # 이후 배포
bin/kamal app logs
bin/kamal console
bin/kamal shell
bin/kamal rollback

config/deploy.yml:

service: myapp
image: myorg/myapp

servers:
  web:
    hosts:
      - 192.168.0.1
      - 192.168.0.2
  job:
    hosts:
      - 192.168.0.3
    cmd: bin/jobs

proxy:
  ssl: true
  host: example.com

registry:
  server: ghcr.io
  username: myorg
  password:
    - KAMAL_REGISTRY_PASSWORD

env:
  clear:
    RAILS_LOG_TO_STDOUT: "1"
    DATABASE_URL: "postgres://..."
  secret:
    - RAILS_MASTER_KEY
    - SECRET_KEY_BASE

builder:
  arch: amd64
  cache:
    type: gha

accessories:
  db:
    image: postgres:16
    host: 192.168.0.4
    env:
      secret: [POSTGRES_PASSWORD]
    directories:
      - data:/var/lib/postgresql/data

bin/kamal deploy로 빌드 + 푸시 + 무중단 롤링 업데이트.

특징:

  • zero-downtime (Traefik 대신 자체 proxy로 8.0+)
  • 다중 서버
  • accessories (DB, Redis 등 별도 컨테이너)
  • 자체 호스팅에 PaaS 같은 UX

Propshaft

Sprockets 후속 (Rails 7.x에서 도입). 더 단순한 asset pipeline.

gem "propshaft"

app/assets/ → 그냥 정적 파일로. 처리 없이 fingerprinting만.

JS는 importmap 또는 esbuild/jsbundling-rails.

importmap-rails (default)

Bundler 없이 ES modules.

# config/importmap.rb
pin "application"
pin "@hotwired/turbo-rails", to: "turbo.min.js"
pin "@hotwired/stimulus", to: "stimulus.min.js"

bin/importmap pin react react-dom
<%= javascript_importmap_tags %>

빌드 단계 없음. 브라우저가 직접 ES module 로드. HTTP/2 + cache로 충분.

Async query (8.0+ 강화)

load_async_query = Post.where(...).load_async
# 다른 작업 진행
posts = load_async_query.to_a

여러 쿼리를 병렬 실행.

새 generators 옵션

rails new myapp --skip-jbuilder --skip-system-test    # 옵션 정리
rails new myapp --solid                                # solid 세 가지 모두
rails new myapp --javascript=esbuild

그 외

  • MySQL 인증 native_password 자동
  • Active Record encrypt 기본 더 강함
  • Authentication generator (bin/rails g authentication)
  • Composite primary key 정식 지원
  • migration generator의 reference에 type 지정

Authentication generator

bin/rails g authentication

기본적인 로그인/가입/로그아웃 컨트롤러와 모델 생성. Devise만큼 풍부하진 않지만 시작점.

class User < ApplicationRecord
  has_secure_password
  ...
end

호환성과 마이그레이션

기존 Rails 7 앱:

  • Solid Queue로 Sidekiq 대체 가능 (양립 가능)
  • Solid Cache로 Redis 대체 점진
  • Solid Cable은 Redis 대체
  • Kamal은 신규/기존 모두
# 7 → 8 업그레이드
bin/rails app:update
bundle update rails

deprecation warning 처리.

함정

1. Solid Queue 처리량 한계

수만 jobs/min은 Sidekiq Pro. 일반 앱(수천)은 충분.

2. Solid Cache의 cache stampede

여러 워커가 동시 만료 시 thundering herd. lock-based 패턴 필요.

3. Kamal과 다중 데이터센터

지역 분산은 자체. Kamal은 단일 cluster 도구.

4. Solid Cable polling

WebSocket 자체 latency는 좋지만 broadcast → DB → polling → 클라이언트로 1-3초 지연 가능.

5. CI/CD와 Docker 캐시

Kamal builder에 cache 설정 안 하면 빌드 매우 느림.

builder:
  cache:
    type: gha          # GitHub Actions
    type: registry     # Docker Registry

Rails 8 + AI

Active Record + pgvector (외부 gem) + 위에서 추출한 embedding으로 RAG 패턴 쉽게.

# pgvector
class Document < ApplicationRecord
  has_neighbors :embedding, dimensions: 1536
end

Document.nearest_neighbors(:embedding, query_vector, distance: "cosine").first(5)

표준은 아니나 Rails 생태계가 빠르게 따라잡는 중.

자주 보는 패턴

미니멀 자체 호스팅

1 VPS:
  Postgres (Docker compose)
  Rails app (Kamal)
  Solid Queue (worker container)
  Caddy / Kamal proxy (TLS)

월 $5~20에 충분한 작은 사이트 + zero downtime.

Hetzner/DigitalOcean + Kamal

Hetzner는 가성비 최고. 4코어 16GB가 월 ~€10.

bin/kamal setup
# 30분 안에 완전 배포 + HTTPS

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기