하드웨어 서버 영업을 할 때 부터 항상 궁금했던건데, 물리 서버에서 어떻게 백엔드 애플리케이션이 동작을 하는지가 항상 궁금했었다. 그런 동기에서 Rails Application을 작동 방식, 즉 서버의 핵심인 Request/Response Cycle을 정리해보았습니다. 크게 아래와 같은 1~8단계로 Cycle로 작동하며, 각 단계 위에서 Object가 새로 만들어지면서 정의된 method들을 Call한다고 볼 수 있습니다. 참고로, 같은 컨트롤러 클래스의 심지어 같은 Action Method를 요청하는 복수의 Request들이 있을 때 Object들은 어떻게 생성될까요? 이떄는 각 요청 당 Object들이 따로 만들어집니다. (the controller class creates a new instance of itself, and forwards the arguments to the #dispatch instance method. This means each request is handled by a new, clean controller object.)
Prerequisite: Rack
1단계: The Rack Entry Point: 다른 object 를 생성하기 위한 베이스 object로 생각합니다.
2단계: MiddleWare -> 많은 액션 디스패쳐가 랙 미들웨어로서 실행된다.(Many of Action Dispatcher's internal components are implemented as Rack middlewares)
Rack middleware are app objects that call other app objects. This allows middleware to do two things: Once the request has passed through all 20 middleware objects, it then enters the router. 미들웨어는 요청을 받아서 중간에 척추처럼 쭉 타고 실행되는 애플리케이션이라고 볼 수 있다.
3단계: Routing
- ActionDispatch::Routing::RouteSet 인스턴스-> (request env -> ActionDispatch::Request Object 로 변환)(whereas env hash: generic Representations of a web Req -> 이 Request object가 dispatch할 적정한 route를 찾는다. 물론 이에 매칭되는 컨트롤러 클래스와 그 안에 매칭되는 Action Method까지 포함해서 lookup한다.
- lookup한 후, 우선 비어있는 reponse object를 만든다. (an instance of ActionDispatch::Response)
- 마지막으로는 controller class가 해당 클래스 매서드인 #dispatch로 실행이 된다. (controller_class.dispatch(action, request, response)
- 모든 app에 있는 route set은 ActionDispatch::Routing::Routeset 에 런타임 동안 인스턴스안에 저장되어있다.
- How Routing Process Works
4단계: The Controller
- Controller의 엔트리 포인트는 routing 과정의 마지막에 있었던 #dispatch class method 이다.
- 특이사항은 각 컨트롤러 클래스마다 또 독자적인 stack of middleware가 있다.컨트롤러 클래스 매서드인 dispatch method 참조
- Controller class가 스스로(즉 클래스 매서드로) 새로운 인스턴스를 만들고, 이때의 Argument를 dispatch instance method 로 forward 해준다.
- 아래부터 순서대로 dispatch class method(먼저 실행), dispatch instance method
- 아래에 process(name) 과정에서 correct action method를 call하는 것임
- 근데 process(name)에서 action method를 콜 하기 전에 deep inheritance hierarchy에 따라 여러가지 method들이 사이에서 콜 된다.
- 즉, dispatch instance method와 action method 사이 Call Stack에서 여러 method들이 먼저 call된다. 중요한 점은 single controller object마다 이 모든 methods가 call된다는 점임..!
5단계: Rendering
- 먼저 아래와 같이 컨트롤러에서 Implement 되는 render 코드를 보자.
- class ExampleController < ApplicationController
def index
render plain: 'Hello, world!'
end
End - 위와 같이 내가 무엇을 랜더링 하든 간에 해당 index 함수의 실행 결과(응답 결과, response)는 response object의 body,(즉, response.body) 에 저장됩니다. 또한, response object 안에 Content-Type이라는 HTTP header에 text/plain형식으로 값이 들어갑니다.
6단계: Leaving The Controller: 컨트롤러가 예정된 Action Method 를 Call 한 뒤, Rails Applicatioin 의 Call Stack은 해당 컨트롤러 클래스의 하이라키(계층 질서)에 따라 아래와 같은 순서로 동작합니다.
- After_action callback method call
- Instrumentation finishes: 여기서 instrumentation은 process_action 과 관련되 있는 hook들을 제공합니다. Redirect_to 나, cleanup_view_runtime 같은 해당 액션과 관련된 method들이 있습니다.
- Rails 에서의 Instrumentation은 process_action과 관련이 있는 ActionController Namespace 내에 정의되어있으며, class method로 이루어져 있습니다.
- Global I18n config is restored to its original value: 레일즈 글로벌 I18n 모듈이 원래의 오리지널 값으로 다시 회복합니다.
- Flash messages are stored within the session: 플래시 메시지가 세션에 저장됩니다. 여기서 Flash Message는 Controller 의 Action Method 내에서 정의된 경고 창 등을 발생하는 method로 생성된 것을 의미합니다.
7단계: Leaving Routing
- Routing 은 단순히 controller에서 리턴 값으로 돌려주는 것을 Middleware로 그대로 보내줍니다. (단, response.headers 가 X-Cascade: pass 를 포함하고 있지 않다면..!)
- 가끔 컨틀롤러로부터 반환되는 헤더에서 또 다른 Routing을 향하는 요청을 보낸다면, 그 요청을 Re-dispatch 합니다. 즉, 또 다른 Route 를 찾는 시도를 하게 됩니다.
8단계: Leaving Middleware
- Routing 이후, Rack Response 배열이 모든 미들웨어를 통해서 반환됩니다. 즉, 실행된 Rails Application 이 요청을 받아서 적절한 action method가 실행되고, 이후에 일련의 과정을 거치면서 모든 미들웨어를 한번씩 찍으면서 응답값을 반환해주는 것입니다.
결론(Conclusion): Rails 의 요청/응답 주기는 Rack을 기본으로 합니다. 즉, root appliaction object는 rack app 입니다. 이 오브젝트 위에서 이제 다른 object들이 생성되는 것입니다.. 그리고 이 위에 Rails의 각종 기능들이 Rack Middleware 위에서 실행됩니다. 아하.. 이런 원리로 Rails Application이 서버에서 하루종일 켜져있어서 실행되는구나.
*참고: Dispatcher 란?
사용자가 프로그램을 실행하면 프로세스가 생성되고 Ready상태가 된다.(Ready Queue) 그 후 스케줄러가 Ready Queue에 있는 프로세스 중 하나를 프로세서(CPU)가 사용가능한 상태가 될 때 CPU를 할당해준다.
이를 준비상태(Ready)에서 실행상태(Running)로 상태전이(State Transition)된다고 한다. 이 과정을 디스패칭(dispatching)이라고 하고 디스패처(dispatcher)가 이 일을 수행한다. (source: https://www.crocus.co.kr/1406 )
source: https://www.rubypigeon.com/posts/examining-internals-of-rails-request-response-cycle/
Examining The Internals Of The Rails Request/Response Cycle
Come with me on a journey through the internals of Rails, as we trace a request from the web server to the controller action method, and follow the response back again. This will give you a glimpse of how Rails works under the hood, hopefully exposing some
www.rubypigeon.com
'Back_End(Ruby on Rails)' 카테고리의 다른 글
Rails_추천 시스템에 Redis 적용(Implementaion of Redis in Ruby on Rails) (0) | 2020.02.14 |
---|---|
Ruby 의 Garbage Collection 을 이해할 수 있는 GC 모듈 (Ruby GC Module, which helps to understand the Garbage Collection of Ruby) (0) | 2020.02.14 |
RubyOnRails/Model Association (0) | 2020.02.10 |
Rails Transaction Isolation Level (트랜잭션 격리 레벨) (0) | 2020.02.10 |
Rails N+1 Query (N+1 쿼리 문제란?) (0) | 2020.02.10 |