Dispatcher-Servlet(디스패처 서블릿)

박지원·2024년 8월 8일

Spring

목록 보기
7/9

디스패처 서블릿이란?

HTTP 프로토콜로 들어오는 모든 요청을 가장 먼저 받아 적합한 컨트롤러에 위임해주는 프론트 컨트롤러(Front Controller)

서블릿(자바 서블릿)

  • 자바를 사용하여 웹 페이지를 동적으로 생성하는 서버측 프로그램
  • 클라이언트의 요청을 처리하고, 그 결과를 반환하는 웹 프로그래밍 기술

클라이언트로부터 어떠한 요청이 오면 Tomcat(톰캣)과 같은 서블릿 컨테이너가 요청을 받는다. 이 모든 요청을 프론트 컨트롤러인 디스패처 서블릿이 가장 먼저 받게 된다. 그러면 디스패처 서블릿은 공통적인 작업을 먼저 처리한 후에 해당 요청을 처리해야하는 컨트롤러를 찾아서 작업을 위임한다.

  • 스프링 부트에서는 스프링 부트 구동시 DispatcherServlet을 서블릿으로 자동 등록하고, 모든 경로 "/"에 대해 매핑
Front Controller : 서블릿 컨테이너의 제일 앞에서 서버로 들어오는 클라이언트의 모든 요청을 받아서 처리해주는 컨트롤러, MVC 구조와 함께 사용되는 디자인 패턴
장점
  • 과거에는 모든 서블릿을 URL 매핑을 위해 web.xml 에 모두 등록해줘야했지만, dispatcher-servlet이 해당 어플리케이션으로 들어오는 모든 요청을 핸들링해주고 공통 작업을 처리면서 상당히 편리하게 이용가능해졌다
    -> 컨트롤러만 구현해두면, 디스패처 서블릿가 알아서 적합한 컨트롤러로 위임해주는 구조
정적 자원의 처리
  • Dispatcher Servlet 이 모든 요청을 처리하다보니, 정적파일 ( 이미지,HTML/CSS/JavaScript) 에 대한 요청도 모두 가로채어 정적자원을 불러오지 못하는 상황 발생

이에 대한 해결 방안 2가지
1. 정작 자원 요청과 애플리케이션 요청을 분리

  • 클라이언트의 요청을 2가지로 분리하는 것
    - /apps 의 URL 로 접근하면 Dispatcher Servlet 이 담당
    • /resources 의 URL 로 접근하면 Dispatcher Servlet 이 담당x
  • 코드가 지저분해지며, 모든 요청에 대해 URL 을 붙여줘야함
  1. 애플리케이션 요청을 탐색하고 없으면 정적 자원 요청으로 처리
  • Dispatcher Servlet이 요청을 처리할 컨트롤러를 먼저 찾고, 요청에 대한 컨트롤러를 찾을 수 없는 경우엔, 2차적으로 설정된 자원 경로를 탐색하여 자원을 탐색
  • 영역을 분리해 효율적인 리소스 관리 지원, 추후에 확장에 용이

Dispatcher-Servlet 의 동작 과정

1. 클라이언트의 요청을 디스패처 서블릿이 받음
  • 디스패처 서블릿은 가장 먼저 요청을 받는 프론트 컨트롤러이다.
  • 서블릿 컨테이너 (웹 컨텍스트) 에서 필터를 지나 스프링 컨텍스트에서 디스패처 서블릿이 가장 먼저 요청을 받게된다.
2. 요청 정보를 통해 요청을 위임할 컨트롤러를 찾음
  • 디스패처 서블릿은 요청을 처리할 핸들러(컨트롤러)를 찾고 해당 객체의 메소드를 호출한다

  • 가장 먼저 어느 컨트롤러가 요청을 처리할 수 있는지를 식별해는 역할-HandlerMapping

  • 컨트롤러 구현하는 방법이 다양하기 때문에, 스프링은 HandlerMapping 인터페이스를 만들어놓고, 다양한 구현 방법에 따라 요청을 처리할 대상을 찾도록 되어있다

  • @Controller 방식은 RequestMappingHandlerMapping 이 처리
    - @Controller 로 작성된 모든 컨트롤러를 찾고 파싱하여 HashMap으로 <요청 정보,처리할 대상> 관리한다

    • 처리할 대상은 HandlerMethod 객체로 컨트롤러, 메서드 등을 갖고 있는데 이는 스프링이 리플렉션을 이용해 요청을 위임하기 때문
  • 요청이 오면 (Http Method, URI) 등을 통해 요청 정보를 만들고, HashMap 에서 요청을 처리할 대상을 찾은 후 HandlerExecutionChain으로 감싸서 반환
    - 감싸는 이유는 컨트롤러로 요청을 넘겨주기 전에 처리해야하는 인터셉터 등을 포함하기 위해서

3. 요청을 컨트롤러로 위임할 핸들러 어댑터를 찾아서 전달함
  • 컨트롤러로 요청을 위임해야 하는데, 디스패처 서블릿은 컨트롤러로 요청을 직접 위임하는 것이 아니라 HandlerAdapter를 통해  위임
  • 다양하게 작성되는 컨트롤러에 대응하기 위해 HandlerAdapter 라는 어댑터 인터페이스를 통해 어댑터 패턴을 적용함으로써 컨트롤러의 구현 방식에 상관없이 요청을 위임할 수 있도록 하였다
4.핸들러 어댑터가 컨트롤러로 요청을 위임함
  • 핸들러 어댑터가 컨트롤러로 요청을 위임하기 전/후에 공통적인 전/후처리 과정 필요

    	1) ArgumentResolver : 인터셉트들을 포함해 요청시에 @RequestParam, @RequestBody 등을 처리
    	2) ReturnValueHandler: 응답시에 ResponseEntity의 Body 를 Json 으로 직렬화하는 등의 처리
  • ArgumentResolver등을 통해 파라미터가 준비 되면 리플렉션을 이용해 컨트롤러로 요청을 위임

5.비즈니스 로직 처리
  • 컨트롤러는 서비스를 호출하고, 작성한 비즈니스 로직들이 진행
6.컨트롤러가 반환값을 반환
  • 비즈니스 로직이 처리된 후에 컨트롤러가 반환값 반환
  • 최근에는 주로 응답 데이터를 사용하는 ResponseEntity를 사용해 반환
7.핸들러 어댑터가 반환값을 처리함
  • Handler Adapter 는 컨트롤러로부터 받은 응답을, 응답 처리기인 ReturnValueHandler 가 후처리한 후에 디서패처 서블릿으로 돌려준다
  • 컨트롤러가 ResponseEntity 를 반환하면 HttpEntityMethodProcessor 가 MessageConverter를 사용해 응답 객체를 직렬화하고 응답 상태를 설정
  • 컨트롤러가 View 이름을 반환하면 ViewResolver 를 통해 View를 반환
8.서버의 응답을 클라이언트로 반환
  • 디스패처 서블릿을 통해 반환되는 응답은 다시 필터들을 거쳐 클라이언트에게 반환
  • 응답이 화면이라면 View 의 이름에 맞는 View를 찾아서 반환해주는 ViewResolver가 적절한 화면을 내린다

정리

  1. 처음 클라이언트에서 요청이 오면 디스패처 서블릿이 해당 요청을 받는다.
  2. Handler Mapping을 통해 요청에 알맞은 컨트롤러를 찾아낸다.
  3. 찾아낸 컨트롤러를 Handler Adapter를 통해 해당 컨트롤러의 메서드를 실행시킨다.
  4. 컨트롤러는 요청을 처리한 뒤 처리한 결과와 해당 뷰 정보(ModelAndView)를 다시 디스패처 서블릿에게 전달한다.
  5. 받은 정보로 디스패처 서블릿은 View Resolver를 통해 View 파일을 찾는다.

참고

0개의 댓글