[SpringBoot] Dispatcher-Servlet(디스패처 서블릿) 개념과 동작과정

주현·2024년 1월 10일
0

springboot

목록 보기
7/8

✔️Dispatcher-Servlet..개념

디스패처 서블릿은 HTTP 프로토콜로 들어오는 모든 요청을 가장 먼저 받아 컨트롤러에 위임해주는 프론트 컨트롤러라 정의가 가능합니다. 자세히 설명을 하자면, 클라이언트로부터 어떤 요천이 들어오면 톰캣과 같은 서블릿 컨테이너가 요청을 받게 됩니다. 이 모든 요청은 디스패처 서블릿이 가장 먼저 받게되는데, 디스패처 서블릿은 공통적인 작업을 먼저 처리후, 해당 요청을 처리해야 하는 컨트롤러를 찾아 작업을 위임합니다.


정적자원의 처리

디스패처 서블릿이 요청을 controller로 넘겨주는 방식은 효율적으로 보이지만, Dispatcher-Servlet이 모든 요청을 처리하다보니, 이미지 HTML등과 같은 정적 파일에 대한 요청마저 모두 가로채는 까닭에 정적자원을 불러오지 못하는 상황도 발생하곤 했습니다. 이러한 문제를 해결하기 위한 방법이 있습니다.

애플리케이션 요청을 탐색후, 없을시 정적 자원 요청으로 처리

Dispatcher-Servlet이 요청을 처리할 컨트롤러를 먼저 찾고, 요청에 대한 컨트롤러를 찾을 수 없는 경우에,2차적으로 설정된 자원경로를 탐색하여 자원을 탐색하는 것입니다. 이런식으로 영역을 분리할시 효율적 리소스 관리를 지원할 뿐만 아니라, 확장을 용이하게 해준다는 장점이 있습니다.


✔️Dispatcher-Servlet의 동작 방식


1. 클라이언트의 요청을 디스패처 서블릿이 받음.
2. 요청 정보를 통해 요청을 위임할 컨트롤러를 찾음.
3. 요청을 컨트롤러로 위임할 핸들러 어댑터를 찾아 전달함.
4. 핸들러 어댑터가 컨트롤러로 요청을 위임함.
5. 비즈니스 로직을 처리함.
6. 컨트롤러가 반환값을 반환함.
7. 핸들러 어댑터가 반환값을 처리함.
8. 서버의 응답을 클라이언트로 반환함.


1. 클라이언트의 요청을 디스패처 서블릿이 받음.

디스패처 서블릿은 가장 먼저 요청을 받는 프론트 컨트롤러입니다. 서블릿 컨텍스트에서 필터를 지나 스프링 컨텍스트에서 디스패처 서블릿이 가장 먼저 요청을 받게 됩니다.

2. 요청 정보를 통해 요청을 위임할 컨트롤러를 찾음.

디스패처 서블릿은 요청을 처리할 핸들러를 찾고 해당 객체의 메소드를 호출합니다. 따라서 가장 먼저 어느 컨트롤러가 요청을 처리할 수 있는지를 식별해야 하는데, 해당 역할을 하는 것이 바로 HandlerMapping입니다. 최근, @Controller, @RequestMapping 관련 어노테이션을 사용해 컨트롤러를 작성하는 것이 일반적입니다. 예전 스팩을 따라서, Controller 인터페이스를 구현하여 컨트롤러를 작성할 수도 있습니다. 즉, 컨트롤러를 구현하는 방법이 다양하기에 스프링은 HandlerMapping 인터페이스를 만들어두고, 다양한 구현 방법에 따라 요청을 처리할 대상을 찾도록 되어 있습니다.

오늘날 흔한 @Conroller의 방식은 RequestMappingHandlerMapping가 처리합니다. 이는 @Controller로 작성된 모든 컨트롤러를 찾은 후 파싱하여 HashMap으로 <요청 정보, 처리할 대상> 관리합니다. 
여기서 처리할 대상은 HandlerMethod 객체로 컨트롤러, 메소드 등을 갖고 있는데, 이는 스프링이 리플렉션을 이용해 요청을 위임하기 때문입니다.
그래서 요청이 오면 (Http Method, URI) 등을 사용해 요청 정보를 만들고, HashMap에서 요청을 처리할 대상(HandlerMethod)를 찾은 후에 HandlerExecutionChain으로 감싸서 반환합니다. HandlerExecutionChain으로 감싸는 이유는 컨트롤러로 요청을 넘겨주기 전에 처리해야 하는 인터셉터 등을 포함하기 위해서입니다.

3. 요청을 컨트롤러로 위임할 핸들러 어댑터를 찾아 전달함.

이후 컨트롤러로 요청을 위임해야 하는데, 디스패처 서블릿은 컨트롤러로 요청을 직접 위임하는 것이 X-> HandlerAdapter를 통해  위임합니다. 그 이유는 컨트롤러의 구현 방식이 다양하기 때문입니다.
과거에는 컨트롤러를 Controller 인터페이스로 구현하였는데,
어노테이션 기반을 이용한 혁신을 내세워 스프링 또한 이렇게 바뀌게 되었습니다.
그래서 다양하게 작성되는 컨트롤러에 대응하기 위해 스프링은 HandlerAdapter라는 어댑터 인터페이스를 통해 어댑터 패턴을 적용함으로써 컨트롤러의 구현 방식에 상관없이 요청을 위임할 수 있도록 하였습니다.

4. 핸들러 어댑터가 컨트롤러로 요청을 위임함.

핸들러 어댑터가 컨트롤러로 요청을 위임한 전/후에 공통적인 전/후처리 과정이 필요합니다. 대표적으로 인터셉터들을 포함해 요청 시에 @RequestParam, @RequestBody 등을 처리하기 위한 ArgumentResolver들과 응답 시에 ResponseEntity의 Body를 Json으로 직렬화하는 등의 처리를 하는 ReturnValueHandler 등이 핸들러 어댑터에서 처리됩니다.

5. 비지니스 로직을 처리함.

6. 컨트롤러가 반환값을 반환함.

비지니스 로직이 처리된 후에는 컨트롤러가 반환값을 반환합니다. 응답 데이터를 사용하는 경우에는 주로 ResponseEntity를 반환하게 되고, 응답 페이지를 보여주는 경우라면 String으로 View의 이름을 반환할 수도 있습니다.요즘은 백과 프론트가 분리돼어 개발하는 시대에서는 주로 ResponseEntity을 사용합니다.

7. 핸들러 어댑터가 반환값을 처리함

HandlerAdapter는 컨트롤러로부터 받은 응답을 응답 처리기인 ReturnValueHandler가 후처리한 후에 디스패처 서블릿으로 돌려줍니다. 만약 컨트롤러가 ResponseEntity를 반환하면 HttpEntityMethodProcessor가 MessageConverter를 사용해 응답 객체를 직렬화하고 응답 상태(HttpStatus)를 설정합니다

8. 서버의 응답을 클라이언트로 반환함

디스패처 서블릿을 통해 반환되는 응답은 다시 필터들을 거쳐 클라이언트에게 반환됩니다.

<참고문헌>
https://mangkyu.tistory.com/18

profile
Just fucking do it!! 개발자가 꿈인 25살 학부생입니다!!

0개의 댓글