Rack을 사용한 Rails
이 가이드는 Rack과 Rails의 통합 및 다른 Rack 구성 요소와의 인터페이스에 대해 다룹니다.
이 가이드를 읽고 나면 다음을 알 수 있습니다:
- Rails 애플리케이션에서 Rack Middleware를 사용하는 방법.
- Action Pack의 내부 Middleware 스택.
- 사용자 정의 Middleware 스택을 정의하는 방법.
경고: 이 가이드는 Rack 프로토콜과 Middleware, URL 매핑, Rack::Builder
와 같은 Rack 개념에 대한 기본적인 지식이 필요합니다.
Rack 소개
Rack은 Ruby로 웹 애플리케이션을 개발하기 위한 최소한의, 모듈식의, 적응성 있는 인터페이스를 제공합니다. HTTP 요청과 응답을 가능한 단순한 방식으로 래핑함으로써, Rack은 웹 서버, 웹 프레임워크, 그리고 이들 사이의 소프트웨어(이른바 미들웨어)의 API를 단일 메서드 호출로 통합하고 정제합니다.
Rack이 어떻게 작동하는지 설명하는 것은 이 가이드의 범위를 벗어납니다. Rack의 기본 사항에 익숙하지 않은 경우 아래의 리소스 섹션을 확인하시기 바랍니다.
Rails에서의 Rack
Rails 애플리케이션의 Rack 객체
Rails.application
은 Rails 애플리케이션의 기본 Rack 애플리케이션 객체입니다. Rack 호환 웹 서버는 Rails 애플리케이션을 제공하기 위해 Rails.application
객체를 사용해야 합니다.
bin/rails server
bin/rails server
는 Rack::Server
객체를 생성하고 웹 서버를 시작하는 기본적인 작업을 수행합니다.
다음은 bin/rails server
가 Rack::Server
인스턴스를 생성하는 방법입니다:
Rails::Server.new.tap do |server| require APP_PATH Dir.chdir(Rails.application.root) server.start end
Rails::Server
는 Rack::Server
를 상속하며 다음과 같이 Rack::Server#start
메서드를 호출합니다:
class Server < ::Rack::Server def start # ... super end end
rackup
Rails의 bin/rails server
대신 rackup
을 사용하려면 Rails 애플리케이션의 루트 디렉토리에 있는 config.ru
에 다음을 넣으면 됩니다:
# Rails.root/config.ru require_relative "config/environment" run Rails.application
그리고 서버를 시작합니다:
$ rackup config.ru
다양한 rackup
옵션에 대해 알아보려면 다음을 실행하세요:
$ rackup --help
개발 및 자동 다시 로드
Middleware는 한 번 로드되며 변경 사항을 모니터링하지 않습니다. 변경 사항을 반영하려면 서버를 다시 시작해야 합니다.
Action Dispatcher Middleware 스택
Action Dispatcher의 많은 내부 구성 요소가 Rack Middleware로 구현되어 있습니다. Rails::Application
은 ActionDispatch::MiddlewareStack
을 사용하여 다양한 내부 및 외부 Middleware를 결합하여 완전한 Rails Rack 애플리케이션을 만듭니다.
참고: ActionDispatch::MiddlewareStack
은 Rails의 Rack::Builder
에 해당하지만, Rails의 요구 사항을 충족하기 위해 더 유연하고 기능이 풍부하게 구축되었습니다.
Middleware 스택 검사
Rails에는 Middleware 스택을 검사하는 편리한 명령이 있습니다:
$ bin/rails middleware
새로 생성된 Rails 애플리케이션의 경우 다음과 같은 결과가 나올 수 있습니다:
use ActionDispatch::HostAuthorization use Rack::Sendfile use ActionDispatch::Static use ActionDispatch::Executor use ActionDispatch::ServerTiming use ActiveSupport::Cache::Strategy::LocalCache::Middleware use Rack::Runtime use Rack::MethodOverride use ActionDispatch::RequestId use ActionDispatch::RemoteIp use Sprockets::Rails::QuietAssets use Rails::Rack::Logger use ActionDispatch::ShowExceptions use WebConsole::Middleware use ActionDispatch::DebugExceptions use ActionDispatch::ActionableExceptions use ActionDispatch::Reloader use ActionDispatch::Callbacks use ActiveRecord::Migration::CheckPending use ActionDispatch::Cookies use ActionDispatch::Session::CookieStore use ActionDispatch::Flash use ActionDispatch::ContentSecurityPolicy::Middleware use Rack::Head use Rack::ConditionalGet use Rack::ETag use Rack::TempfileReaper run MyApp::Application.routes
여기에 나열된 기본 Middleware(및 기타 Middleware)는 아래 내부 Middleware 스택 섹션에서 각각 요약되어 있습니다.
Middleware 스택 구성
Rails는 application.rb
또는 환경별 구성 파일 environments/<environment>.rb
를 통해 config.middleware
를 사용하여 Middleware 스택에 Middleware를 추가, 제거, 수정하는 간단한 구성 인터페이스를 제공합니다.
Middleware 추가
다음 메서드 중 하나를 사용하여 Middleware 스택에 새 Middleware를 추가할 수 있습니다:
config.middleware.use(new_middleware, args)
- 새 Middleware를 Middleware 스택의 맨 아래에 추가합니다.config.middleware.insert_before(existing_middleware, new_middleware, args)
- 지정된 기존 Middleware 앞에 새 Middleware를 추가합니다.config.middleware.insert_after(existing_middleware, new_middleware, args)
- 지정된 기존 Middleware 뒤에 새 Middleware를 추가합니다.
# config/application.rb # Rack::BounceFavicon을 맨 아래에 추가 config.middleware.use Rack::BounceFavicon # ActionDispatch::Executor 뒤에 Lifo::Cache 추가. { page_cache: false } 인수 전달 config.middleware.insert_after ActionDispatch::Executor, Lifo::Cache, page_cache: false
Middleware 교체
config.middleware.swap
을 사용하여 기존 Middleware를 다른 Middleware로 교체할 수 있습니다.
# config/application.rb # ActionDispatch::ShowExceptions를 Lifo::ShowExceptions로 교체 config.middleware.swap ActionDispatch::ShowExceptions, Lifo::ShowExceptions
Middleware 이동
config.middleware.move_before
및 config.middleware.move_after
를 사용하여 기존 Middleware의 위치를 변경할 수 있습니다.
# config/application.rb # ActionDispatch::ShowExceptions를 Lifo::ShowExceptions 앞으로 이동 config.middleware.move_before Lifo::ShowExceptions, ActionDispatch::ShowExceptions
# config/application.rb # ActionDispatch::ShowExceptions를 Lifo::ShowExceptions 뒤로 이동 config.middleware.move_after Lifo::ShowExceptions, ActionDispatch::ShowExceptions
Middleware 삭제
애플리케이션 구성에 다음 행을 추가하세요:
# config/application.rb config.middleware.delete Rack::Runtime
그리고 이제 Middleware 스택을 검사하면 Rack::Runtime
이 더 이상 포함되어 있지 않습니다.
$ bin/rails middleware (in /Users/lifo/Rails/blog) use ActionDispatch::Static use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x00000001c304c8> ... run Rails.application.routes
세션 관련 Middleware를 제거하려면 다음과 같이 하세요:
# config/application.rb config.middleware.delete ActionDispatch::Cookies config.middleware.delete ActionDispatch::Session::CookieStore config.middleware.delete ActionDispatch::Flash
브라우저 관련 Middleware를 제거하려면 다음과 같이 하세요:
# config/application.rb config.middleware.delete Rack::MethodOverride
존재하지 않는 항목을 삭제하려고 할 때 오류가 발생하도록 하려면 delete!
를 사용하세요.
# config/application.rb config.middleware.delete! ActionDispatch::Executor
내부 Middleware 스택
Action Controller의 많은 기능이 Middleware로 구현되어 있습니다. 다음 목록은 각각의 목적을 설명합니다:
ActionDispatch::HostAuthorization
- DNS 리바인딩 공격으로부터 보호하기 위해 요청을 보낼 수 있는 호스트를 명시적으로 허용합니다. 구성 방법은 구성 가이드를 참조하세요.
Rack::Sendfile
- 서버별 X-Sendfile 헤더를 설정합니다.
config.action_dispatch.x_sendfile_header
옵션을 통해 구성할 수 있습니다.
ActionDispatch::Static
- public 디렉토리의 정적 파일을 제공합니다.
config.public_file_server.enabled
가false
이면 비활성화됩니다.
Rack::Lock
env["rack.multithread"]
플래그를false
로 설정하고 애플리케이션을 Mutex로 래핑합니다.
ActionDispatch::Executor
- 개발 중 스레드 안전 코드 다시 로드에 사용됩니다.
ActionDispatch::ServerTiming
- 요청에 대한 성능 지표를 포함하는
Server-Timing
헤더를 설정합니다.
ActiveSupport::Cache::Strategy::LocalCache::Middleware
- 메모리 캐싱에 사용됩니다. 이 캐시는 스레드 안전하지 않습니다.
Rack::Runtime
- 요청 실행 시간(초 단위)을 포함하는 X-Runtime 헤더를 설정합니다.
Rack::MethodOverride
params[:_method]
가 설정된 경우 메서드를 재정의할 수 있습니다. 이 Middleware는 PUT 및 DELETE HTTP 메서드 유형을 지원합니다.
ActionDispatch::RequestId
- 응답에 고유한
X-Request-Id
헤더를 사용할 수 있게 하고ActionDispatch::Request#request_id
메서드를 활성화합니다.
ActionDispatch::RemoteIp
- IP 스푸핑 공격을 확인합니다.
Sprockets::Rails::QuietAssets
- 자산 요청에 대한 로거 출력을 억제합니다.
Rails::Rack::Logger
- 요청이 시작되었음을 로그에 알립니다. 요청이 완료되면 모든 로그를 플러시합니다.
ActionDispatch::ShowExceptions
- 애플리케이션에서 반환된 모든 예외를 구조화된 형식으로 최종 사용자에게 표시하는 예외 앱을 호출합니다.
ActionDispatch::DebugExceptions
- 예외 로깅 및 요청이 로컬인 경우 디버깅 페이지 표시를 담당합니다.
ActionDispatch::ActionableExceptions
- Rails 오류 페이지에서 작업을 디스패치할 수 있는 방법을 제공합니다.
ActionDispatch::Reloader
- 개발 중 코드 다시 로드를 지원하기 위한 준비 및 정리 콜백을 제공합니다.
ActionDispatch::Callbacks
- 요청 디스패치 전후에 실행되는 콜백을 제공합니다.
ActiveRecord::Migration::CheckPending
- 보류 중인 마이그레이션을 확인하고 마이그레이션이 보류 중인 경우
ActiveRecord::PendingMigrationError
를 발생시네, 계속해서 한국어 번역문을 제공하겠습니다.
ActionDispatch::Cookies
- 요청에 쿠키를 설정합니다.
ActionDispatch::Session::CookieStore
- 세션을 쿠키에 저장하는 역할을 합니다.
ActionDispatch::Flash
- 플래시 키를 설정합니다.
config.session_store
가 값으로 설정된 경우에만 사용할 수 있습니다.
ActionDispatch::ContentSecurityPolicy::Middleware
- Content-Security-Policy 헤더를 구성하기 위한 DSL을 제공합니다.
Rack::Head
- 모든 HEAD 요청에 대해 빈 본문을 반환합니다. 다른 모든 요청은 변경하지 않습니다.
Rack::ConditionalGet
- “조건부 GET"을 지원하여 페이지가 변경되지 않은 경우 서버가 아무것도 반환하지 않도록 합니다.
Rack::ETag
- 모든 String 본문에 ETag 헤더를 추가합니다. ETag는 캐시 유효성 검사에 사용됩니다.
Rack::TempfileReaper
- 멀티파트 요청을 버퍼링하는 데 사용된 임시 파일을 정리합니다.
팁: 위의 Middleware 중 어느 것이든 사용자 정의 Rack 스택에서 사용할 수 있습니다.