# Ruby on Rails 7: 리액티브 애플리케이션을 위한 Hotwire와 Turbo
> Rails 7에서 Hotwire와 Turbo 완벽 가이드. Turbo Drive, Frames, Streams로 JavaScript 없이 리액티브 애플리케이션을 구축하는 방법.
- Published: 2026-01-11
- Updated: 2026-04-07
- Author: SharpSkill
- Tags: ruby on rails, hotwire, turbo, turbo frames, turbo streams
- Reading time: 12 min
---
Rails 7은 Hotwire를 기본으로 통합하여 웹 개발에 혁명을 가져왔습니다. 이 스택은 커스텀 JavaScript를 한 줄도 작성하지 않고도 고도로 리액티브한 애플리케이션을 구축할 수 있게 해줍니다. Turbo Drive, Turbo Frames, Turbo Streams는 기존 SPA 접근 방식을 "HTML over the wire" 철학으로 대체합니다.
> **왜 Hotwire인가?**
>
> Hotwire는 프론트엔드 복잡성을 획기적으로 줄여줍니다. 동적 인터페이스에 React나 Vue가 필요 없습니다. 서버가 바로 사용 가능한 HTML을 전송하고, Turbo가 DOM 업데이트를 자동으로 처리합니다.
## Hotwire 아키텍처 이해하기
Hotwire는 JavaScript 프레임워크의 전형적인 복잡성 없이 매끄러운 사용자 경험을 제공하기 위해 함께 작동하는 세 가지 보완적인 기술로 구성됩니다.
**Turbo Drive**는 링크 클릭과 폼 제출을 가로채서 내비게이션을 가속화합니다. 전체 페이지를 새로고침하는 대신 `
` 콘텐츠만 교체되며, JavaScript와 CSS 컨텍스트가 유지됩니다.
**Turbo Frames**는 페이지를 독립적인 섹션으로 분해합니다. 각 프레임은 개별적으로 업데이트될 수 있어 페이지의 나머지 부분에 영향을 주지 않고 타겟 인터랙션이 가능합니다.
**Turbo Streams**는 WebSocket을 통해 또는 HTTP 요청에 대한 응답으로 실시간 업데이트를 가능하게 합니다. 선언적 DOM 조작을 위한 8가지 CRUD 액션을 사용할 수 있습니다.
```ruby
# Gemfile
# Installing Turbo Rails (included by default in Rails 7+)
gem 'turbo-rails'
```
기존 프로젝트에서는 설치에 단 하나의 명령어만 필요합니다.
```bash
# installation.sh
# Installing Turbo in an existing Rails project
rails turbo:install
# Verify the JavaScript import is present
cat app/javascript/application.js
# Should contain: import "@hotwired/turbo-rails"
```
## Turbo Drive 초기 설정
Turbo Drive는 Rails 7에서 기본적으로 활성화되어 있습니다. 모든 내비게이션이 추가 설정 없이 자동으로 "turbo"가 됩니다. 동작은 data 속성을 통해 커스터마이즈할 수 있습니다.
```erb
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= javascript_importmap_tags %>
<%= yield %>
```
필요한 경우 특정 링크나 폼에서 Turbo Drive를 비활성화할 수 있습니다.
```erb
<%= link_to "Dashboard", dashboard_path %>
<%= link_to "Download PDF", export_path, data: { turbo: false } %>
<%= form_with model: @document, data: { turbo: false } do |f| %>
<%= f.file_field :attachment %>
<%= f.submit "Upload" %>
<% end %>
<%= link_to "Delete", item_path(@item),
data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>
```
> **Turbo Drive 캐시**
>
> Turbo Drive는 방문한 페이지를 캐시합니다. 에셋의 `data-turbo-track="reload"` 속성은 CSS/JS 파일이 변경될 때 전체 새로고침을 강제합니다.
## 타겟 업데이트를 위한 Turbo Frames
Turbo Frames는 독립적으로 업데이트되는 페이지 영역을 정의합니다. 각 프레임은 고유한 식별자를 가지며 일치하는 프레임을 포함하는 응답에만 반응합니다.
```erb
Messages
<%= render @messages %>
<%= link_to "Load more", messages_path(page: @next_page) %>
<%= render "form", message: Message.new %>
```
업데이트가 작동하려면 서버 응답에 같은 식별자를 가진 프레임이 포함되어야 합니다.
```erb
<%= form_with model: [@room, Message.new], id: "new_message" do |f| %>
<%= f.text_area :content, placeholder: "Your message..." %>
<%= f.submit "Send" %>
<% end %>
```
### 무거운 작업을 위한 비동기 브로드캐스팅
요청을 차단하지 않기 위해 브로드캐스팅은 백그라운드에서 수행할 수 있습니다.
```ruby
# app/models/report.rb
class Report < ApplicationRecord
belongs_to :user
after_create_commit :generate_async
private
def generate_async
GenerateReportJob.perform_later(self)
end
end
```
```ruby
# app/jobs/generate_report_job.rb
class GenerateReportJob < ApplicationJob
queue_as :default
def perform(report)
# Simulating a long operation
report.update!(status: "processing")
# Notify user of start
report.broadcast_replace_to(
report.user, :reports,
target: dom_id(report),
partial: "reports/report"
)
# Generate the report
result = ReportGenerator.new(report).generate
report.update!(content: result, status: "completed")
# Notify user of completion
report.broadcast_replace_to(
report.user, :reports,
target: dom_id(report),
partial: "reports/report"
)
end
end
```
## Turbo 고급 패턴
### 인라인 폼 편집
일반적인 패턴은 정적 콘텐츠를 인라인 편집 폼으로 대체하는 것입니다.
```erb
```
```erb
<%= yield %>
```
> **Turbo 디버깅**
>
> 개발 환경에서 JavaScript 콘솔을 열고 `Turbo.setProgressBarDelay(0)`를 입력하면 프로그레스 바를 즉시 볼 수 있습니다. `Turbo.session.drive = false`로 Turbo Drive를 임시로 비활성화할 수 있습니다.
## 에러 처리와 로딩 상태
좋은 UX를 위해서는 로딩 상태와 네트워크 오류 처리가 필요합니다.
```erb
<%= form_with model: @model,
data: {
controller: "form-loading",
action: "turbo:submit-start->form-loading#disable turbo:submit-end->form-loading#enable"
} do |f| %>
<%= yield f %>
<% end %>
```
```javascript
// app/javascript/controllers/form_loading_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = ["submit", "text", "spinner"]
disable() {
this.submitTarget.disabled = true
this.textTarget.classList.add("hidden")
this.spinnerTarget.classList.remove("hidden")
}
enable() {
this.submitTarget.disabled = false
this.textTarget.classList.remove("hidden")
this.spinnerTarget.classList.add("hidden")
}
}
```
### 서버 오류 처리
```ruby
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
rescue_from ActiveRecord::RecordNotFound do |exception|
respond_to do |format|
format.turbo_stream do
render turbo_stream: turbo_stream.replace(
"main_content",
partial: "shared/not_found"
)
end
format.html { render "errors/not_found", status: :not_found }
end
end
end
```
## 성능 최적화
여러 기법으로 성능 좋은 Turbo 애플리케이션을 보장할 수 있습니다.
```ruby
# app/controllers/messages_controller.rb
class MessagesController < ApplicationController
# Avoid N+1 queries with eager loading
def index
@messages = Message.includes(:author, :room)
.order(created_at: :desc)
.page(params[:page])
end
# Fragment caching for static elements
def show
@message = Message.find(params[:id])
fresh_when @message
end
end
```
```erb
<% cache message do %>
<%= message.content %>
By <%= message.author.name %>
<% end %>
```
## 결론
Hotwire와 Turbo는 기존 JavaScript 프레임워크의 복잡성을 제거하여 Rails 개발을 혁신합니다. Turbo Drive는 내비게이션을 가속화하고, Turbo Frames는 타겟 업데이트를 가능하게 하며, Turbo Streams는 강력한 실시간 기능을 제공합니다.
### Hotwire 시작 체크리스트
- 내장된 Hotwire 통합을 위해 Rails 7 이상 사용하기
- 세 가지 컴포넌트 이해하기: Drive, Frames, Streams
- Turbo Frames가 유용한 페이지 영역 식별하기
- 컨트롤러에서 `respond_to`와 `format.turbo_stream` 사용하기
- 실시간 기능을 위한 브로드캐스팅 구현하기
- 간단한 JavaScript 인터랙션을 위해 Stimulus와 결합하기
이 "HTML over the wire" 접근 방식은 Ruby on Rails를 강력하게 만드는 단순성과 생산성을 유지하면서 모던하고 리액티브한 애플리케이션을 구축할 수 있게 해줍니다. 결과적으로 유지보수할 코드가 줄어들고, 뛰어난 성능과 최적의 개발자 경험을 얻을 수 있습니다.
---
Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack.
HTML version of this page: https://sharpskill.dev/ko/blog/ruby-on-rails/ruby-on-rails-7-hotwire-turbo