Spring Web MVC 에서 HTTP Request를 처리하는 핵심 클래스는 DispatcherServlet이란 클래스이다. 아 DispatcherServlet은 MVC 아키텍처로 구성된 프레젠테이션 계층을 만들 수 있도록 설계되어 있다.
서버가 브라우저 등의 HTTP 클라이언트로부터 요청을 받아 처리 후 응답하기까지의 과정을 알아보자.
-
자바 서버의 서블릿 컨테이너는 HTTP 프로토콜을 통해 들어오는 요청을 DispatcherServlet에 전달해준다. (이때, URL이나 확장자를 설정해주면 일부 요펑만 매핑되도록 설정할 수도 있다.)
-
DispatcherServlet은 요청을 제일 먼저 받아 원하는 전처리 동작을 수행한 후 다음 클래스에게 일부 동작을 위임하고, 원하는 처리를 완수하여 응답값을 보낼 때 까지의 대략적인 로직을 담고있다. 마치 Facade 패턴에서의 Facade 클래스와 비슷한 역할을 하는 것이다.
-
DispatcherServlet이 요청의 URL이나 파라미터 정보, Http 메서드 등을 참고하여 어떤 컨트롤러에게 작업을 위임할지 결정한다. 컨트롤러는 선정하는 것은 DispatcherServlet의 핸들러 매핑 전략을 이용한다. 즉, 사용자의 요청을 기준으로 작업을 어떤 핸들러에게 위임할지를 정하는 것이다.
-
이를 전략이라고 부르는 이유는 DI의 가장 대표적인 용도라고 할 수 있는 전략 패턴이 적용되어 있기 때문이다. DispatcherServlet의 핸들러 매핑 전략은 DispatcherServlet의 수정 없이도 DI를 통해 얼마든지 확장 가능하다ㅏ. 어떤 URL이 들어오면 어떤 컨트롤러 오브젝트가 이를 처리하게 만들지를 매핑해주는 전략을 만들어 DI로 제공해주기만 하면 된다.
엄밀히 말하면 DispatcherServlet은 그 자체로 스프링 컨텍스트에 등록되는 빈이 아니므로, DI가 일어나는 것은 아니다. 하지만 마치 DI가 적용되는 것처럼 서블릿 애플리케이션 컨텍스트의 빈들 가져와 사용한다. (AutoWiring 기법 사용)
-
어떤 컨트롤러/핸들러가 요청을 처리하게 할지를 결정했다면, 다음은 해당 컨트롤러 오브젝트의 메소드를 호출해서 실제로 웹 요청을 처리하는 작업을 위임할 차례다. 그런데 DispatcherServlet이 매핑으로 찾은 컨트롤러를 가져와 싱행하려면 컨트롤러 메소드를 어떻게 호출할지를 알고 있어야한다.
-
DispatcherServlet은 어댑터 인터페이스를 사용해 컨트롤러 오브젝트의 메소드를 호풀하는 방식을 사용한다. 이렇게 하면 항상 일정한 방식으로 컨트롤러를 호출하고 결과를 받을 수 있기 때문에 확장성이 높아진다. 결합도를 낮춰 확장성을 얻은 것이다.
DispatcherServlet <--> AdapterA <--> ControllerA
-
DispatcherServlet이 핸들러 어댑터에 웹 요청을 전달할때는 모든 웹 요청 정보가 담긴
HttpServletRequest
타입의 오브젝트를 전달해준다. 이를 어댑터가 적절히 변환해서 컨트롤러의 메소드가 받을 수 있는 파라미터로 변환해서 전달해주는 것이다. -
HttpServletResponse도 함께 전해준다. 원한다면 리턴하고 싶은 값은
HttpServletResponse
안에 결과를 직접 집어넣을 수도 있다.
-
컨트롤러가 해야 할 마지막 중요한 두 가지 작업은 모델을 생성하고 모델에 정보를 넣어주는 것이다. (나머지 하나는 뷰에 정보를 넣는 것이다.)
-
여기서 뷰란 맵 형태의 정보인데, 이름과 그에 대응되는 값의 쌍으로 정보를 만드는 것이다. 만약 jsp를 사용한다면
.addAttribute(String, Object)
와 같은 함수를 호출하여 값을 집어넣고,${String}
으로 특정 값을 화면에 보이게 띄울 수 있는데, 이때 값을 집어넣는 그 과정이 바로 모델의 정보를 추가하는 과정이다. -
단, Restful api 형태로 개발한다면(
@RestController
) ModelAndView 오브젝트를 사용하지 않는다.
- 뷰의 논리적인 이름을 리턴해주어 DispatcherServlet의 뷰 리졸버가 그를 이용해 뷰 오브젝트를 생성할 수 있도록 한다. jstlView가 컨트롤러가 돌려준 JSP뷰 템플릿을 바탕으로 적절한 모델의 내용을 삽입하는 등등의 과정을 거쳐 뷰 오브젝트를 만든다.
- 뷰 생성까지의 모든 작업을 마쳤으면 DispatcherServlet은 등록된 후처리기가 있는지 확인하고, 있다면 후처리기에서 후속 작업을 진행한 뒤에 뷰가 만들어준 HttpServletResponse에 담인 최종 결과를 서블릿 컨테이너에게 돌려준다.
- 서블릿 컨테이너는 HttpServletResponse에 담긴 정보를 HTTP 응답으로 만들어 사용자의 브라우저나 클라리런트에게 전송하고 작업을 종료한다.
참고: 토비의 스프링