DispatcherServlet & Handler
DispatcherServlet 이란? (dispatch : 보내다)
- HTTP 프로토콜로 들어오는 모든 요청을 가장 먼저 받아 적합한 컨트롤러에 위임해주는 프론트 컨트롤러 패턴을 구현한 Servlet이다.
- 프론트 컨트롤러란, 주로 서블릿 컨테이너의 제일 앞에서 서버로 들어오는 클라이언트의 모든 요청을 받아서 처리해주는 컨트롤러로, MVC 구조에서 함께 사용되는 디자인 패턴
- 장점 : web.xml의 역할을 축소시켰다. 과거엔 모든 서블릿을 URL매핑을 위해 web.xml에 모두 등록해줘야했지만, dispatcher-servlet이 해당 어플리케이션으로 들어오는 모든 요청을 핸들링해주고, 공통작업을 처리해준다.
- 문제점 : 모든 요청을 처리하다보니 html등 정적파일에 대한 요청마저 가로채는 문제가 발생했다. → 이를 해결하기 위해, 요청에 대한 컨트롤러를 먼저 찾고, 그러지 못하는 경우에는 2차적으로 설정된 자원(Resource) 경로를 탐색하여 자원을 탐색하도록 한다.
- 동작과정을 간단히 말하면, dispatcherServlet을 통해 요청을 처리할 컨트롤러를 찾아서 위임하고, 그 결과를 반환한다.
동작 과정
1. 클라이언트의 요청을 dispatcherServlet이 받는다.
2. 요청 정보를 통해 요청을 위임할 컨트롤러를 찾는다.
- 요청을 처리할 컨트롤러를 찾고, 해당 메서드를 호출해야 한다.
HandlerMapping
은 원하는 handler를 찾아오는 역할을 수행한다.
HandlerMapping
의 구현체중 하나인 RequestMappingHandlerMapping
은 @Controller로 작성된 모든 컨트롤러빈을 파싱하여 HashMap으로 요청정보, 처리할 대상을 관리한다. (컨트롤러가 아닌, 요청에 매핑되는 컨트롤러와 해당 메서드 등을 갖는 HandlerMethod 객체를 찾는다.)
- 따라서,
HandlerMapping
은 요청이 오면 HttpMethod, URI등을 사용해서 Key 객체인 요청정보를 만들고, Value인 요청을 처리할 HandlerMethod를 찾아 HandlerMethodExecutionChain
으로 감싸서 반환한다.
HandlerMethodExecutionChain
으로 감싸는 이유는 컨트롤러로 요청을 넘겨주기전에 처리해야하는 인터셉터 등을 포함하기 위해서다.
3. 요청을 컨트롤러로 위임할 HandlerAdapter
를 찾아서 전달함
- dispatcherServlet은 컨트롤러로 요청을 직접 위임하는것이 아니라
HandlerAdapter
를 통해 컨트롤러로 요청을 위임하는데, adapter interface!
를 통해 컨트롤러를 호출하는 이유는 컨트롤러의 구현방식이 다양하기 때문이다.
- 최근에는
@Controller
에 @RequestMapping
관련 어노테이션을 사용해 컨트롤러 클래스를 주로 작성하지만, Controller 인터페이스를 구현하여 컨트롤러 클래스를 작성할 수도 있다. 스프링은 HandlerAdapter
라는 adapter interface 통해 adapter pattern을 적용함으로써 컨트롤러의 구현방식에 상관없이 요청을 위임할 수 있다.
4. HandlerAdapter가 컨트롤러로 요청을 위임함
- HandlerAdapter가 Controller로 요청을 넘기기 전에 공통적인 전&후처리 과정이 필요하다.
대표적으로
1) interceptor를 포함해 요청시에 @RequestParam
, @RequestBody
등을 처리하기 위한 ArgumentResolver들
2) 응답시에 ResponseEntity
의 Body를 Json으로 직렬화하는 등의 처리를 하는 ReturnValueHandler
등이 어탭터에서 컨트롤러로 전달되기 전에 처리된다.
5. 비지니스 로직을 처리한다.
- 이후에 Controller는 서비스를 호출하고 우리가 작성한 비지니스 로직들이 진행된다.
6. 컨트롤러가 반환값을 반환함
- 비지니스 로직이 처리된 후에는 컨트롤러가 반환값을 반환한다.요즘은 프론트/백을 분리하고 MSA를 이용하기 때문에 주로 ResponseEntity를 반환한다. 물론 컨트롤러에서 View 이름을 반환할 수도 있다.
7. HandlerAdapter
가 반환값을 처리함
HandlerAdapter
는 Controller로 부터 받은 응답을 응답처리기인 ReturnValueHandler
가 후처리한 후에 dispatcherServlet으로 돌려준다.
- Controller가
ResponseEntity
를 반환하면, HttpEntityMethodProcessor가 MessageConverter를 사용해 응답객체를 직렬화하고, 응답상태(HttpStatus)를 설정한다.
- Controller가
View이름
을 반환하면 ViewResolver를 통해 View를 반환한다.
8. 서버의 응답을 클라이언트로 반환
- dispatcherServlet을 통해 반환되는 응답은 다시 필터들을 거쳐 클라이언트에게 반환된다.
출처