레벨4의 첫번째 미션, 톰캣 구현하기를 정리해보자!
총 3가지 요구사항이 있다. string으로 들어오는 request를 적절하게 파싱해서 로직을 구현하면 된다.
단순히 메서드 분리를 통해 Http11Processor
객체에서 처리하게 구현했다. html인지 css인지에 따라 contentType을 알맞게 설정해주고, 정적파일은 responseBody에 넣어주었다.
1단계에서 구현한 코드 리팩터링이 시급해 2단계와 3단계를 같이 진행했다.
각 단계의 요구사항을 살펴보자.
회원가입
, 로그인하기
버튼은 GET이 아닌 POST로 HTTP method 변경JSESSIONID=~~~~
형태로 값을 전달하면 클라이언트가 보내는 Request Header의 Cookie필드에 값이 추가됨.HttpRequest에서 rawString을 파싱하는 책임을 가지게 했다.
ServletContainer에서 uri에 따라 알맞은 controller를 찾고 로직을 실행시켰다. 다형성을 이용해 컨트롤러의 종류가 무엇이든 코드가 실행될 수 있게 했다.
그리고 responseManager를 통해 response를 만들어주었다.
실제 자바 서블릿이 어떻게 동작하는지 디버깅을 통해 알아보자.
Spring MVC 프레임워크를 사용했을때 HTTP 요청이 어떻게 처리되는지 디버깅을 통해 알아보자.
Spring boot에 내장된 tomcat이 시작되는 곳 부터 확인하자.(그 이전은 나중에 기회가 되면 알아보자..)
TomcatWebServer
라는 클래스에서 tomcat을 시작한다.
Tomcat
은 server.start()를 호출한다.
LifeCycle
인터페이스의 구현체인 LifecycleBase
의 start() 메서드가 실행된다.
start() 메서드 내부의 init()을 계속 따라가면 Connector
라는 객체의 initInternal()이 호출되는 것을 알 수 있다.
Connector
의 initInternal()에서 CoyoteAdapter
가 adapter로 할당되고, ProtocolHandler
라는 곳에 저장된다.
여기에서 할당된 adapter가 추후 Http11Processor
로 주입된다.
Http11Processor
는 AbtractHttp11Protocol
이라는 객체에 의해 생성되는데, 이 객체는 위의 ProtocolHandler
를 구현한 AbstractProtocol
이라는 객체를 상속받은 객체이다.
이제 Http11Processor
부터 살펴보자.
Http11Processor
의 service() 메서드가 호출되는데, 여기서 rawString이 Request 객체로 변환된다. 여기서의 Request 클래스는 low-level 서버 request이다.
CoyoteAdapter에 의해 low-level Request는 HttpServletRequest
를 구현한 다른 Request
객체로 변환된다.
이렇게 변환된 Request
가 이후에 ApplicationFilterChain
의 doFilter() 메서드로 전달되는 것이다. ApplicationFilterChain
에서 동작방식은 아래 포스팅에 정리해놓았다.
링크
필터가 다 실행되고 난 후 이제 Servlet이 호출된다.
Servlet
인터페이스를 구현한 GenericServlet
을 상속한 HttpServlet
의 service() 메서드가 호출된다.
그 이후엔 FrameworkServlet
이란 객체가 호출되는데, 아무래도 스프링을 이용했기에 그런것 같다(추측입니다.).
여기서 다시 (PATCH 제외) HttpServlet
의 또 다른 service()메서드가 호출되는데, 이 곳에서 doGet, doPost와 같은 메서드가 호출된다.
이후에 몇번의 과정을 거치고 FrameworkServlet
을 상속한 DispatcherServlet
으로 흐름이 넘어간다.
DispatcherServlet
이후의 과정은 아래 포스팅에 정리해놓았다.
링크