Ruby on Rails 8 ์๋ฒฝ ๊ฐ์ด๋ 2026: ์ ๊ท ๊ธฐ๋ฅ๊ณผ ๋ง์ด๊ทธ๋ ์ด์ ๋ฐฉ๋ฒ
Rails 8์ Solid Trifecta, ๋ด์ฅ ์ธ์ฆ, Kamal 2, Propshaft๋ฅผ ์ฝ๋ ์์ ์ ํจ๊ป ๋ถ์ํฉ๋๋ค. Rails 7์์ 8๋ก์ ๋จ๊ณ๋ณ ๋ง์ด๊ทธ๋ ์ด์ ๊ฐ์ด๋๋ฅผ ์ ๊ณตํฉ๋๋ค.

Ruby on Rails 8์ Rails 7 ์ดํ ๊ฐ์ฅ ์ค์ํ ๋ฆด๋ฆฌ์ค๋ก, Redis๋ฅผ ๋์ฒดํ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ธฐ๋ฐ ์ธํ๋ผ, ๋ด์ฅ ์ธ์ฆ ์์คํ , ๊ฐ์ํ๋ ๋ฐฐํฌ ํ์ดํ๋ผ์ธ์ ๋์ ํ์์ต๋๋ค. 2024๋ 11์์ ์ถ์๋์์ผ๋ฉฐ 2025๋ 10์ Rails 8.1 ํ์ ๋ฆด๋ฆฌ์ค๋ฅผ ํตํด ์ฑ์ ๋จ๊ณ์ ์ ์ด๋ Rails 8์ ๊ธฐ์กด์ ๋ณ๋์ ์ธํ๋ผ๋ฅผ ์๊ตฌํ๋ ์ธ๋ถ ์์กด์ฑ์ ์ ๊ฑฐํฉ๋๋ค. ํ๊ตญ์ ๊ฐ๋ฐํ์๊ฒ ์ด ๋ณํ๋ ์ด์ ๋ณต์ก๋ ๊ฐ์, ์ธํ๋ผ ๋น์ฉ ์ ๊ฐ, ์ค์ ๊ท๋ชจ ํ๋ก์ ํธ์ ์ง์ ์ฅ๋ฒฝ ์ํ๋ฅผ ์๋ฏธํฉ๋๋ค.
Rails 8์ Redis๋ฅผ Solid Trifecta(Solid Queue, Solid Cache, Solid Cable)๋ก ๋์ฒดํ๊ณ , ๋ด์ฅ ์ธ์ฆ ์์ฑ๊ธฐ๋ฅผ ์ถ๊ฐํ๋ฉฐ, ๊ธฐ๋ณธ ์์ ํ์ดํ๋ผ์ธ์ Propshaft๋ก ์ ํํ๊ณ , ๋ฌด์ค๋จ ๋ฐฐํฌ๋ฅผ ์ํ Kamal 2๋ฅผ ํ์ฌํฉ๋๋ค. Ruby 3.2 ์ด์์ด ํ์ํฉ๋๋ค.
Solid Trifecta: ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ธฐ๋ฐ ์ธํ๋ผ
Rails 8 ์ด์ ์๋ ๋๋ถ๋ถ์ ํ๋ก๋์ ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ฐฑ๊ทธ๋ผ์ด๋ ์ก, ์บ์ฑ, WebSocket pub/sub์ ์ธ ๊ฐ์ง ํต์ฌ ๊ธฐ๋ฅ์ Redis๋ฅผ ์์กดํ์์ต๋๋ค. Solid Trifecta๋ ์ด ์ธ ๊ฐ์ง๋ฅผ PostgreSQL, MySQL, SQLite์ ํธํ๋๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ธฐ๋ฐ ์ด๋ํฐ๋ก ๋์ฒดํฉ๋๋ค.
์ด ์ํคํ ์ฒ ์ ํ์ ์ด์ ๋ณต์ก๋๋ฅผ ํฌ๊ฒ ์ค์ฌ ์ค๋๋ค. Redis ์ธ์คํด์ค๋ฅผ ๋ณ๋๋ก ๋ชจ๋ํฐ๋งํ๊ณ ํ์ฅํ๊ณ ์ ์ง ๊ด๋ฆฌํ ํ์๊ฐ ์์ด์ง๋๋ค. ์ฑ๋ฅ ๋ฉด์์์ ํธ๋ ์ด๋์คํ๋ ์กด์ฌํฉ๋๋ค. ๋์ฉ๋ ์ฒ๋ฆฌ ์๋๋ฆฌ์ค์์๋ Redis๊ฐ ์ฌ์ ํ ๋ ๋น ๋ฅด์ง๋ง, ๋๋ค์์ ์ ํ๋ฆฌ์ผ์ด์ ์์๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ธฐ๋ฐ ์ด๋ํฐ๋ก ์ถฉ๋ถํ ์ฑ๋ฅ์ ํ๋ณดํ ์ ์์ต๋๋ค. Basecamp๋ 10TB ๊ท๋ชจ์ Solid Cache๋ฅผ 60์ผ ๋ณด์กด ๊ธฐ๊ฐ์ผ๋ก ํ๋ก๋์ ์์ ์ด์ํ๊ณ ์์ต๋๋ค.
Solid Queue: ๋ฐฑ๊ทธ๋ผ์ด๋ ์ก ์ฒ๋ฆฌ
Solid Queue๋ Sidekiq, Resque, Delayed Job์ ๋์ฒดํ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ธฐ๋ฐ Active Job ๋ฐฑ์๋์
๋๋ค. PostgreSQL 9.5+์ MySQL 8.0+์์ FOR UPDATE SKIP LOCKED๋ฅผ ํ์ฉํ๋ฉฐ, SQLite์์๋ ์์ ์ ์ผ๋ก ํด๋ฐฑ(fallback) ์ฒ๋ฆฌ๋ฉ๋๋ค.
# config/environments/production.rb
config.active_job.queue_adapter = :solid_queue
# config/solid_queue.yml
production:
dispatchers:
- polling_interval: 1
batch_size: 500
workers:
- queues: "*"
threads: 5
processes: 2
polling_interval: 0.1Puma ํ๋ฌ๊ทธ์ธ์ ๊ฐ๋ฐ ํ๊ฒฝ์์ ์น ์๋ฒ์ ํจ๊ป Solid Queue๋ฅผ ์์ํ๋ฏ๋ก, ๋ณ๋์ ํ๋ก์ธ์ค๋ฅผ ์คํํ ํ์๊ฐ ์์ต๋๋ค.
# config/puma.rb
plugin :solid_queue if ENV["SOLID_QUEUE_IN_PUMA"] || Rails.env.development?Solid Queue๋ ๋ฐ๋ณต ์ก(recurring jobs), ๋์์ฑ ์ ์ด, ํ๋ณ ์ผ์ ์ค์ง ๋ฐ ์ฌ๊ฐ์ ๊ฐ์ ๊ณ ๊ธ ๊ธฐ๋ฅ์ ์ง์ํฉ๋๋ค. ๋ถ๋น 10,000๊ฑด ๋ฏธ๋ง์ ์ก์ ์ฒ๋ฆฌํ๋ ์ ํ๋ฆฌ์ผ์ด์ ์์๋ ๋ณ๋ค๋ฅธ ๋ถํ ์์ด ์์ ์ ์ผ๋ก ๋์ํฉ๋๋ค.
Solid Cache์ Solid Cable
Solid Cache๋ HTML ํ๋๊ทธ๋จผํธ ์บ์๋ฅผ Memcached๋ Redis ๋์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅํฉ๋๋ค. ๋์คํฌ ์คํ ๋ฆฌ์ง(SSD/NVMe)๋ RAM์ ๋นํด ๋น์ฉ์ด ํฌ๊ฒ ๋ฎ์ผ๋ฏ๋ก, ๋ ํฐ ์บ์ ํ๊ณผ ๋ ๊ธด ๋ณด์กด ๊ธฐ๊ฐ์ ํ๋ณดํ ์ ์์ต๋๋ค.
# config/environments/production.rb
config.cache_store = :solid_cache_storeSolid Cable์ Action Cable์ Redis pub/sub ์ด๋ํฐ๋ฅผ ๋์ฒดํฉ๋๋ค. WebSocket ๋ฉ์์ง๊ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ ์ด๋ธ์ ๊ธฐ๋ก๋๊ณ ๊ธฐ๋ณธ์ ์ผ๋ก 100ms ๊ฐ๊ฒฉ์ผ๋ก ํด๋ง๋ฉ๋๋ค. ๋๋ถ๋ถ์ ์ฌ์ฉ ์ฌ๋ก์์ ๊ฑฐ์ ์ค์๊ฐ์ ๊ฐ๊น์ด ํต์ ์ด ๊ฐ๋ฅํ๋ฉฐ, ๋ฉ์์ง๋ 24์๊ฐ ํ ์๋์ผ๋ก ์ ๋ฆฌ๋ฉ๋๋ค.
# config/cable.yml
production:
adapter: solid_cable
polling_interval: 0.1
keep_messages_around_for: 1.day๋ด์ฅ ์ธ์ฆ ์์ฑ๊ธฐ
Rails 8์ ์ธ์ ๊ธฐ๋ฐ ๋ก๊ทธ์ธ, ๋ก๊ทธ์์, ๋น๋ฐ๋ฒํธ ์ฌ์ค์ ์ค์บํด๋ฉ์ ์์ฑํ๋ ๋ค์ดํฐ๋ธ ์ธ์ฆ ์์ฑ๊ธฐ๋ฅผ ํ์ฌํฉ๋๋ค. ๊ธฐ๋ณธ ์ธ์ฆ์ ์ธ๋ถ ์ ฌ(gem)์ด ํ์ํ์ง ์์ต๋๋ค.
# Generate the authentication scaffolding
bin/rails generate authentication์ด ๋ช
๋ น์ User ๋ชจ๋ธ, Session ๋ชจ๋ธ, SessionsController, PasswordsController, Authentication concern์ ์์ฑํฉ๋๋ค. ์์ฑ๋ ์ฝ๋๋ bcrypt์ ํจ๊ป has_secure_password๋ฅผ ์ฌ์ฉํ๋ฉฐ, IP๋น 3๋ถ์ 10ํ์ ๋ก๊ทธ์ธ ์๋ ์ ํ(rate limiting)์ด ํฌํจ๋์ด ์์ต๋๋ค.
# app/controllers/concerns/authentication.rb
module Authentication
extend ActiveSupport::Concern
included do
before_action :require_authentication
helper_method :authenticated?
end
private
def require_authentication
resume_session || request_authentication
end
def resume_session
Current.session = find_session_by_cookie
end
def find_session_by_cookie
Session.find_by(id: cookies.signed[:session_id]) if cookies.signed[:session_id]
end
def request_authentication
session[:return_to_after_authenticating] = request.url
redirect_to new_session_path
end
def authenticated?
Current.session.present?
end
end๋น๋ฐ๋ฒํธ ์ฌ์ค์ ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅ๋ ํ ํฐ์ด ์๋, has_secure_password๊ฐ ์์ฑํ๋ ์๋ช
๋๊ณ ์ ํจ ๊ธฐ๊ฐ์ด ์ ํ๋ ํ ํฐ์ ์ฌ์ฉํฉ๋๋ค. ์ด ์์ฑ๊ธฐ๋ ์๋์ ์ผ๋ก ํ์๊ฐ์
, ์ด๋ฉ์ผ ์ธ์ฆ, ์์
๋ก๊ทธ์ธ์ ํฌํจํ์ง ์์ต๋๋ค. ์์ฑ๋ ์ฝ๋๋ ํ์ฅ ๊ฐ๋ฅํ ๊ธฐ๋ฐ์ ์ ๊ณตํ๋ ๊ฒ์ด์ง, Devise๋ฅผ ์์ ํ ๋์ฒดํ๋ ๊ฒ์ด ์๋๋๋ค.
๋ด์ฅ ์์ฑ๊ธฐ๋ ๋ก๊ทธ์ธ, ๋ก๊ทธ์์, ๋น๋ฐ๋ฒํธ ์ฌ์ค์ ์ ์ฒ๋ฆฌํฉ๋๋ค. ํ์๊ฐ์ , ์ด๋ฉ์ผ ์ธ์ฆ, OAuth, ๋ค๋จ๊ณ ์ธ์ฆ(MFA)์ ์ง์ ๊ตฌํํ๊ฑฐ๋ Authentication Zero ๊ฐ์ ์ ฌ์ ํตํด ์ถ๊ฐํด์ผ ํฉ๋๋ค.
params.expect๋ฅผ ํตํ ์์ ํ ํ๋ผ๋ฏธํฐ ์ฒ๋ฆฌ
Rails 8์ ๊ธฐ์กด์ params.require.permit ํจํด์ ๋์ฒดํ๋ ๋ ์์ ํ ๋์์ธ params.expect๋ฅผ ๋์
ํฉ๋๋ค. ์๋ก์ด ๋ฉ์๋๋ ํค๊ฐ ๋๋ฝ๋์์ ๋ nil์ ์กฐ์ฉํ ๋ฐํํ๋ ๋์ ์์ธ๋ฅผ ๋ฐ์์ํต๋๋ค.
# Before (Rails 7)
def user_params
params.require(:user).permit(:name, :email, :role)
end
# After (Rails 8)
def user_params
params.expect(user: [:name, :email, :role])
endexpect ๋ฉ์๋๋ :user ํค๊ฐ ์กด์ฌํ๊ณ ํ์ฉ๋ ์์ฑ๋ง ํฌํจํ๊ณ ์๋์ง ๊ฒ์ฆํฉ๋๋ค. ํค๊ฐ ๋๋ฝ๋ ๊ฒฝ์ฐ ์ฆ์ ActionController::ParameterMissing์ด ๋ฐ์ํ์ฌ, ์ดํ ์ฒ๋ฆฌ ํ๋ฆ์์ ๋ฐ์ํ ์ ์๋ ๋ฌด์(silent) ๋ฒ๊ทธ๋ฅผ ๋ฐฉ์งํฉ๋๋ค.
Propshaft: ์๋ก์ด ๊ธฐ๋ณธ ์์ ํ์ดํ๋ผ์ธ
Propshaft๋ ๊ธฐ๋ณธ ์์ ํ์ดํ๋ผ์ธ์ผ๋ก Sprockets๋ฅผ ๋์ฒดํฉ๋๋ค. Sprockets๊ฐ ์ปดํ์ผ, ์์ถ, ํ๊ฑฐํ๋ฆฐํ ์ ํ๋์ ๋ชจ๋๋ฆฌ์ ์์คํ ์์ ์ฒ๋ฆฌํ๋ค๋ฉด, Propshaft๋ ์ ์ ์์ ์ ์ ๊ณต๊ณผ ํ๊ฑฐํ๋ฆฐํ ์๋ง ์ง์คํฉ๋๋ค.
JavaScript ๋ฒ๋ค๋ง์ esbuild, Vite, Bun ๊ฐ์ ์ต์ ๋๊ตฌ์ ์์ํฉ๋๋ค. CSS ์ฒ๋ฆฌ๋ Tailwind CLI ๋๋ dart-sass๋ฅผ ํตํด ์ด๋ฃจ์ด์ง๋๋ค. ๊ทธ ๊ฒฐ๊ณผ, ๋ ๋น ๋ฅด๊ณ ์์ธก ๊ฐ๋ฅํ๋ฉฐ ํ์ฌ์ ํ๋ก ํธ์๋ ๋๊ตฌ ์ํ๊ณ์ ์ ๋ง๋ ์์ ํ์ดํ๋ผ์ธ์ ๊ตฌ์ถํ ์ ์์ต๋๋ค.
# Gemfile (Rails 8 default)
gem "propshaft"
# No configuration needed for basic usage
# Assets in app/assets are served and fingerprinted automatically๊ธฐ์กด์ Sprockets๋ฅผ ์ฌ์ฉํ๋ ์ ํ๋ฆฌ์ผ์ด์
์ ๊ณ์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋ง์ด๊ทธ๋ ์ด์
๊ฒฝ๋ก๋ Sprockets ์ ์ฉ ๋๋ ํฐ๋ธ(//= require)๋ฅผ ์ ๊ฑฐํ๊ณ import maps ๋๋ JavaScript ๋ฒ๋ค๋ฌ๋ฅผ ์ฑํํ๋ ๋ฐฉ์์
๋๋ค.
Ruby on Rails ๋ฉด์ ์ค๋น๊ฐ ๋์ จ๋์?
์ธํฐ๋ํฐ๋ธ ์๋ฎฌ๋ ์ดํฐ, flashcards, ๊ธฐ์ ํ ์คํธ๋ก ์ฐ์ตํ์ธ์.
Kamal 2์ Thruster: ๋ฌด์ค๋จ ๋ฐฐํฌ
Rails 8์ Kamal 2๊ฐ ์ฌ์ ๊ตฌ์ฑ๋์ด ์ ๊ณต๋ฉ๋๋ค. Kamal 2๋ ์ Linux ์๋ฒ๋ฅผ ๋จ์ผ ๋ช ๋ น์ผ๋ก ํ๋ก๋์ ์๋ฒ๋ก ํ๋ก๋น์ ๋ํ๋ ๋ฐฐํฌ ๋๊ตฌ์ ๋๋ค. Kamal 2๋ Traefik์ ๋ชฉ์ ์ ๋ง๊ฒ ์ค๊ณ๋ ๋ฆฌ๋ฒ์ค ํ๋ก์์ธ Kamal Proxy๋ก ๋์ฒดํฉ๋๋ค.
# Deploy to a fresh server
kamal setup
# Subsequent deployments
kamal deployThruster๋ Kamal Proxy์ Puma ์ฌ์ด์ ์์นํ์ฌ ํ์ผ ๋ค์ด๋ก๋๋ฅผ ์ํ X-Sendfile ๊ฐ์, ์๋ ์์ ์์ถ(gzip/brotli), HTTP/2 ์ง์์ ์ ๊ณตํฉ๋๋ค. Rails 8์ด ์์ฑํ๋ Dockerfile์๋ ๊ธฐ๋ณธ์ ์ผ๋ก Thruster๊ฐ ํฌํจ๋ฉ๋๋ค.
# Excerpt from Rails 8 generated Dockerfile
RUN gem install thruster
CMD ["thrust", "./bin/rails", "server"]์ด ์คํ(Kamal 2 + Kamal Proxy + Thruster + Puma)์ SSL ์ข ๋ฃ, ๋ฌด์ค๋จ ๋ฐฐํฌ, ๋กค๋ง ์ฌ์์์ Nginx๋ HAProxy ๊ฐ์ ์ธ๋ถ ์๋น์ค ์์ด ์ฒ๋ฆฌํฉ๋๋ค.
ํ๋ก๋์ ์ ์ํ SQLite ๊ฐํ
Rails 8์ ํ๋ก๋์ ํ๊ฒฝ์์์ SQLite ์ง์์ ํฌ๊ฒ ๊ฐ์ ํ์์ต๋๋ค. ์ปค๋ฅ์ ํ๋ง, WAL ๋ชจ๋, ํฅ์๋ ๋์์ฑ ์ฒ๋ฆฌ๋ก ์ค์ ๊ท๋ชจ ์ ํ๋ฆฌ์ผ์ด์ ์์ SQLite๋ฅผ ํ๋ก๋์ ์ ์ ์ฉํ ์ ์๊ฒ ๋์์ต๋๋ค. Solid Trifecta์ ๊ฒฐํฉํ๋ฉด ๋จ์ผ ์๋ฒ์์ ์ธ๋ถ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์๋ฒ ์์ด Rails 8 ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฒด๋ฅผ SQLite๋ก ์ด์ํ ์ ์์ต๋๋ค.
# config/database.yml (SQLite production setup)
production:
primary:
adapter: sqlite3
database: storage/production.sqlite3
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
cache:
adapter: sqlite3
database: storage/production_cache.sqlite3
queue:
adapter: sqlite3
database: storage/production_queue.sqlite3
cable:
adapter: sqlite3
database: storage/production_cable.sqlite3์ด ๊ตฌ์ฑ์ ๋ค ๊ฐ์ SQLite ํ์ผ๋ก ์ ์ฒด ์ ํ๋ฆฌ์ผ์ด์ ์คํ์ ์ด์ํฉ๋๋ค. Kamal์ ์คํ ๋ฆฌ์ง ๋๋ ํฐ๋ฆฌ๋ฅผ ์๊ตฌ ๋ณผ๋ฅจ์ผ๋ก ๋ง์ดํธํ์ฌ ์ปจํ ์ด๋ ์ฌ์์ ์์๋ ๋ฐ์ดํฐ๊ฐ ๋ณด์กด๋ฉ๋๋ค.
Rails 7์์ Rails 8๋ก ์ ๊ทธ๋ ์ด๋ํ๊ธฐ
Rails 7.2์์ Rails 8.0์ผ๋ก์ ๋ง์ด๊ทธ๋ ์ด์ ์ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ด๋ฏธ ๋ํ๋ฆฌ์ผ์ด์ ๊ฒฝ๊ณ ๋ฅผ ํด๊ฒฐํ ์ํ๋ผ๋ฉด ์ํํ๊ฒ ์งํ๋ฉ๋๋ค. Rails 7.0 ๋๋ 7.1์ ์ฌ์ฉํ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋จ๊ณ์ ์ผ๋ก ์ ๊ทธ๋ ์ด๋ํด์ผ ํฉ๋๋ค. 7.0์์ 7.1๋ก, 7.1์์ 7.2๋ก, ๊ทธ๋ฆฌ๊ณ 7.2์์ 8.0์ผ๋ก ์์ฐจ์ ์ผ๋ก ์งํํ๋ ๊ฒ์ด ์์ ํฉ๋๋ค.
Rails 8์ Ruby 3.2 ์ด์์ ์๊ตฌํฉ๋๋ค. Ruby ๋ฒ์ ์ ํ์ธํ๊ณ , Rails 7.2์์ ํ ์คํธ ์ค์ํธ๊ฐ ํต๊ณผํ๋์ง ๊ฒ์ฆํ๋ฉฐ, ์ ๊ทธ๋ ์ด๋๋ฅผ ์์ํ๊ธฐ ์ ์ RailsBump๋ฅผ ํตํด ์ ฌ ํธํ์ฑ์ ์ ๊ฒํด์ผ ํฉ๋๋ค.
1๋จ๊ณ: ์์กด์ฑ ์ ๋ฐ์ดํธ
# Gemfile
gem "rails", "~> 8.0"bundle update rails2๋จ๊ณ: ์ ๋ฐ์ดํธ ํ์คํฌ ์คํ
bin/rails app:update์ด ๋ช
๋ น์ ๊ตฌ์ฑ ํ์ผ์ Rails 8 ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์
๋ฐ์ดํธํฉ๋๋ค. git diff๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ ๋ณ๊ฒฝ ์ฌํญ์ ์ฃผ์ ๊น๊ฒ ๊ฒํ ํด์ผ ํฉ๋๋ค. ์ฃผ์ ๋ณ๊ฒฝ ์ฌํญ์๋ ์๋ก์ด Regexp.timeout ๊ธฐ๋ณธ๊ฐ(1์ด), ๋ณ๊ฒฝ๋ db:migrate ๋์(์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์คํค๋ง ์๋ ๋ก๋), Propshaft ๊ตฌ์ฑ์ด ํฌํจ๋ฉ๋๋ค.
3๋จ๊ณ: ์คํค๋ง ์ฌ์ ๋ ฌ ์ฒ๋ฆฌ
Rails 8์ schema.rb์ ์ปฌ๋ผ ์์๋ฅผ ์ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ปฌ๋ผ ์์์ ์ผ์นํ๋๋ก ์ฌ์ ๋ ฌํฉ๋๋ค. ์คํค๋ง ๋คํ๋ฅผ ์ฆ์ ์คํํ์ฌ ์ด ์ธํ์ ๋ณ๊ฒฝ์ ์ค์ ๋ง์ด๊ทธ๋ ์ด์
๋ณ๊ฒฝ๊ณผ ๋ถ๋ฆฌํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
bin/rails db:schema:dump
git add db/schema.rb
git commit -m "Reorder schema columns for Rails 8"4๋จ๊ณ: ์ ๊ธฐ๋ฅ ์ ์ง์ ๋์
Solid Trifecta, Propshaft, ์ธ์ฆ ์์ฑ๊ธฐ๋ ๊ธฐ์กด ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ ํ์ ์ผ๋ก ๋์ ํ ์ ์์ต๋๋ค. ์ฝ์ด ์ ๊ทธ๋ ์ด๋๊ฐ ์์ ํ๋ ํ ๊ฐ๋ณ์ ์ผ๋ก ์ฑํํ๋ ๊ฒ์ด ๊ถ์ฅ๋ฉ๋๋ค.
- ์ก ์ด๋ํฐ๋ฅผ Solid Queue๋ก ๊ต์ฒด
- ์บ์ ์คํ ์ด๋ฅผ Solid Cache๋ก ์ ํ
- Action Cable์ Solid Cable๋ก ๋ง์ด๊ทธ๋ ์ด์ (ํด๋น๋๋ ๊ฒฝ์ฐ)
- ์์ ํ์ดํ๋ผ์ธ์ Propshaft ๋ง์ด๊ทธ๋ ์ด์ ํ๊ฐ
5๋จ๊ณ: ํ๋ผ๋ฏธํฐ ์ฒ๋ฆฌ ๋ฐฉ์ ์ ๋ฐ์ดํธ
์ปจํธ๋กค๋ฌ ์ ์ฒด์์ params.require.permit ํธ์ถ์ params.expect๋ก ๊ต์ฒดํฉ๋๋ค. ์ด ๋ณ๊ฒฝ์ ์ ํ ์ฌํญ์ด์ง๋ง, ๋ ๊ฐ๋ ฅํ ํ๋ผ๋ฏธํฐ ๊ฒ์ฆ์ ์ํด ๊ถ์ฅ๋ฉ๋๋ค.
Rails 8.1: Continuable Jobs์ ๋ด์ฅ CI
2025๋
10์์ ์ถ์๋ Rails 8.1์ Rails 8์ ๊ธฐ๋ฐ ์์ ๋ ๊ฐ์ง ์ฃผ์ ๊ธฐ๋ฅ์ ์ถ๊ฐํฉ๋๋ค. Continuable Jobs(ActiveJob::Continuable)๋ ์ฅ์๊ฐ ์คํ๋๋ ์ก์ ์ฌ๊ฐ ๊ฐ๋ฅํ ๋จ๊ณ๋ก ๋ถํ ํฉ๋๋ค. ์๋ฒ๊ฐ ์ํฌํธ ๋์ค ์ฌ์์๋๋๋ผ๋ ์ก์ ์ฒ์๋ถํฐ ๋ค์ ์์ํ์ง ์๊ณ ์ค๋จ๋ ์ง์ ์์ ์ ํํ ์ฌ๊ฐ๋ฉ๋๋ค.
# app/jobs/import_records_job.rb
class ImportRecordsJob < ApplicationJob
include ActiveJob::Continuable
def perform(cursor:)
records = Record.where("id > ?", cursor.value || 0).limit(1000)
records.each do |record|
process(record)
cursor.advance(record.id)
end
end
endRails 8.1์ ๋ด์ฅ CI ๊ตฌ์ฑ๊ณผ ๋ค์ดํฐ๋ธ Markdown ๋ ๋๋ง๋ ๋์ ํ์ฌ ์ธ๋ถ ์์กด์ฑ์ ๋์ฑ ์ค์ ๋๋ค.
๊ฒฐ๋ก
Rails 8์ ํ๋ ์์ํฌ ์ฒ ํ์ ์ค์ํ ์ ํ์ ์ผ๋ก, ๊ธฐ๋ฅ์ ํฌ์ํ์ง ์์ผ๋ฉด์ ์ด์ ๋จ์์ฑ์ ๊ทน๋ํํ์์ต๋๋ค. ํต์ฌ ์ฌํญ์ ์ ๋ฆฌํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- Solid Trifecta(Queue, Cache, Cable)๋ ์ก, ์บ์ฑ, WebSocket์์ Redis๋ฅผ ํ์ ์์กด์ฑ์์ ์ ์ธํฉ๋๋ค
- ๋ด์ฅ ์ธ์ฆ ์์ฑ๊ธฐ๋ ์๋ํํฐ ์ ฌ ์์ด ์ธ์ ๊ธฐ๋ฐ ์ธ์ฆ์ ๊ธฐ๋ฐ์ ์ ๊ณตํฉ๋๋ค
params.expect๋params.require.permit์ ๋ ์๊ฒฉํ๊ณ ์์ ํ ํ๋ผ๋ฏธํฐ ์ฒ๋ฆฌ๋ก ๋์ฒดํฉ๋๋ค- Propshaft๋ Sprockets๋ฅผ ๋์ฒดํ๋ ๊ธฐ๋ณธ ์์ ํ์ดํ๋ผ์ธ์ผ๋ก, ๋ฒ๋ค๋ง์ ์ต์ ๋๊ตฌ์ ์์ํฉ๋๋ค
- Kamal 2์ Thruster๋ Nginx๋ Capistrano ์์ด ๋ฌด์ค๋จ ๋ฐฐํฌ๋ฅผ ๊ตฌํํฉ๋๋ค
- Rails 7.2์์์ ์
๊ทธ๋ ์ด๋๋ ์ ์ง์ ์ผ๋ก ์งํ๋ฉ๋๋ค. ์์กด์ฑ ์
๋ฐ์ดํธ,
app:update์คํ, ์ ๊ธฐ๋ฅ์ ๋จ๊ณ์ ๋์ ์์๋ฅผ ๋ฐ๋ฆ ๋๋ค - Rails 8.1์ Continuable Jobs์ ๋ด์ฅ CI๋ฅผ ์ถ๊ฐํ์ฌ ์ธ๋ถ ๋๊ตฌ ์์กด์ฑ์ ๋์ฑ ์ค์ ๋๋ค
์ฐ์ต์ ์์ํ์ธ์!
๋ฉด์ ์๋ฎฌ๋ ์ดํฐ์ ๊ธฐ์ ํ ์คํธ๋ก ์ง์์ ํ ์คํธํ์ธ์.
ํ๊ทธ
๊ณต์
๊ด๋ จ ๊ธฐ์ฌ

Rails 8์ Solid Queue์ Solid Cache: 2026๋ ๊ธฐ์ ๋ฉด์ ์๋ฒฝ ๊ฐ์ด๋
Rails 8์์ ๊ธฐ๋ณธ ํ์ฌ๋ Solid Queue์ Solid Cache๊ฐ Redis๋ฅผ ๋์ฒดํ๋ ๋ฐฉ์์ ์ค๋ช ํฉ๋๋ค. ์ํคํ ์ฒ, ์ค์ , ๋์์ฑ ์ ์ด, 2026๋ ๋ฉด์ ํต์ฌ ์ง๋ฌธ๊น์ง ์ด์ ๋ฆฌํฉ๋๋ค.

2026๋ Rails API ๋ชจ๋ ์๋ฒฝ ๊ฐ์ด๋: RESTful API ์ค๊ณ, ์ง๋ ฌํ ์ ๋ต๊ณผ ๊ธฐ์ ๋ฉด์ ํต์ฌ ์ง๋ฌธ
Rails 8.1 API ๋ชจ๋๋ก ํ๋ก๋์ ๊ธ RESTful API๋ฅผ ๊ตฌ์ถํ๋ ๋ฐฉ๋ฒ์ ๋ค๋ฃน๋๋ค. Alba์ jsonapi-serializer ๋น๊ต, JWT ์ธ์ฆ, ์๋ฌ ์ฒ๋ฆฌ, ํ ์คํธ ํจํด๊ณผ ๋ฉด์ ์ง๋ฌธ๊น์ง ์ด์ ๋ฆฌํฉ๋๋ค.

Rails Turbo์ Hotwire 2026 ์๋ฒฝ ๊ฐ์ด๋: ์ค์๊ฐ ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ๊ณผ ๋ฉด์ ๋๋น
Rails 8์ Turbo 8๊ณผ Hotwire๋ฅผ ํ์ฉํ ์ค์๊ฐ ์น ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ ์ค์ ๊ฐ์ด๋์ ๋๋ค. Turbo Streams, ๋ชจํ, Stimulus ๊ตฌํ ํจํด๊ณผ ๊ธฐ์ ๋ฉด์ ์์ ์์ฃผ ๋์ค๋ ์ง๋ฌธ์ ๋ค๋ฃน๋๋ค.