1. Dispatcher-Servlet(Dispatcher 서블릿) 개념

dispatcher-servlet에서 dispatch는 보내다라는 뜻을 가지고 있습니다.

       Servlet Container에서 HTTP프로토콜을 통해 들어오는 모든 요청을 프레젠테이션 계층의 제일앞에 둬서 중앙집중식으로 처리해주는 프론트 컨트롤러(Front Controller)

 

이것을 설명해주자면, 클라이언트로부터 어떠한 요청이 오면 Tomcat(톰캣)과 같은 서블릿컨테이너가 요청을 받는데, 이때 제일 앞에서 서버로 들어오는 모든 요청을 처리하는 *프론트 컨트롤러를 Spring에서 정의하였고, 이를 Dispatcher-Servlet이라고 합니다. 그래서 공통처리 작업을 Dispatcher 서블릿이 처리한 후, 적절한 세부 컨트롤러로 작업을 위임해줍니다. 

 

물론 Dispatcher-Servlet이 처리하는 url 패턴을 지정해주어야 하는데 일반적으로는 /*.do와 같으 /로 시작하며 .do로 끝나는 url 패턴에 대해서 처리하라고 지정해줍니다. 

 

Q) Front Controller(프론트 컨트롤러)란?

Front Controller는 주로 서블릿 컨테이너의 제일 앞에서 서버로 들어오는 클라이언트의 모든 요청을 받아서 처리해주는 컨트롤러인데, MVC 구조에서 함께 사용되는 패턴이다.

2. Dispatcher-Servlet의 단점

Spring MVC는 DispatcherServlet이 등장함에 따라 web.xml의 역할을 상당히 축소시켜주었습니다. 기존에는 모든 서블릿에 대해 URL 매핑을 활용하기 위해서 web.xml에 모두 등록해주어야 했지만, dispatcher-servlet이 해당 어플리케이션으로 들어오는 모든 요청을 핸들링해주면서 작업을 상당히 편리하게 할 수 있게 되었습니다. 그리고 이 서블릿을 이용한다면 @MVC 역시 사용할 수 있게되어 좋습니다. 결과적으로 Dispatcher Servlet의 기능 처리를 그려보면 아래의 그림과 같습니다.

 

[Dispatcher-Servlet의 흐름]

 

물론 Dispatcher Servlet이 요청을 Controller로 넘겨주는 방식은 효율적으로 보입니다. 하지만 모든 요청을 처리하다보니 이미지나 HTML 파일을 불러오는 요청마저 전부 Controller로 넘겨버립니다. 게다가 JSP 파일 안의 JavaScript나 StyleCSS 파일들에 대한 요청들 까지도 모두 디스패처 서블릿이 가로채는 까닭에 자원을 불러오지 못하는 상황도 발생하곤 했습니다.  이에 대한 해결책은 두가지가 있는데 첫번째는 클라이언트의 요청을 2가지로 분리하여 구분하는 것입니다.

 

1. /apps 의 URL로 접근하면 Dispatcher Servlet이 담당한다.

2. /resources 의 URL로 접근하면 Dispatcher Servlet이 컨트롤할 수 없으므로 담당하지 않는다.

 

이러한 방식은 괜찮지만 상당히 코드가 지저분해지며, 모든 요청에 대해서 저런 URL을 붙여주기 때문에 직관적인 설계가 될 수 없습니다. 두번째 방법은 모든 요청을 컨트롤러에 등록하는 것인데, 상당히 무식한 방법입니다. 

 

Spring은 이러한 문제들을 해결함과 동시에 편리한 방법을 제공해주는데, 그것은 바로 <mvc:resources />를 이용한 방법인데, 이것은 만약 Dispatcher Servlet에서 해당 요청에 대한 컨트롤러를 찾을 수 없는 경우에, 2차적으로 설정된 경로에서 요청을 탐색하여 자원을 찾아내는 것입니다. 이렇게 영역을 분리하면 효율적인 리소스관리를 지원할 뿐 아니라 추후에 확장을 용이하게 해준다는 장점이 있습니다.

View

뷰는 View 인터페이스를 구현해서 생성합니다.

public interface View{
    void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse resposne) throws Exception;
}

 

스프링에서 제공하는 뷰 목록은 아래와 같습니다.

 

InternalResourceView

RequestDispatcher forward(), include()를 이용하는 뷰입니다.

RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/view/hello.jsp");
request.setAttribute("message", "This is message");
dispatcher.forward(request, response);

 

위는 RequestDispatcher를 사용했던 때의 방식입니다. InternalResourceView의 동작 방식도 이와 동일하다고 보면 됩니다. 아래는 사용 예제의 일부분입니다.

View view = new InternalResourceView("/WEB-INF/view/hello.jsp");

return new ModelAndView(view, model);

 

JstlView

InternalResourceView의 서브 클래스이다.
JSP를 뷰 템플릿으로 사용할 때 JstlView를 사용하면 여러가지 추가 기능을 더 활용할 수 있다.(지역화 메세지 등)

ViewResolver

 - 이 인터페이스는 컨트롤러가 리턴한 뷰 이름을 참고해서 적절하게 뷰 오브젝트를 찾아주는 로직을 담당합니다. Spring에서 지원하는 뷰 리졸버는 다양하게 있으니 참고하면 됩니다.

웹 애플리케이션 뷰 리소스의 물리적인 Path를 결정하기 위해 접두사(prefix)와 접미사(suffix)를 뷰 이름에 붙이는 규칙을 따릅니다.

 

[Java Config]

@Bean
public ViewResolver viewResolver () 
{
    InternalResourceViewResolver resolver = new InternalResourceViewResolver();
    resolver.setPrefix("/WEB-INF/views/");
    resolver.setSuffix(".jsp");
    return resolver;
}

[XML]

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"
    p:prefix="/WEB-INF/views/"
    p:suffix=".jsp" />

HandlerMapping

요청 정보를 기준으로 어떤 컨트롤러를 사용할 것인가를 결정하는 인터페이스입니다. DispatcherServlet에서는 한개 이상의 HandlerMapping을 가질수가 있습니다.

private List<HandlerMapping> handlerMappings;

DispatcherServlet 클래스의 일부분입니다.

꽤 많은 HandlerMapping 인터페이스 구현체가 있으니 참고하고 기본적으로 흔히 사용하는 @Controller와 @RequestMapping 어노테이션을 통해 결정되는 컨트롤러의 경우 RequestMappingHandlerMapping 구현체의 의해 핸들러가 결정됩니다. 거기에 대응되는 Adapter로는 RequestMappingHandlerAdapter 클래스에 의해 컨트롤러의 메서드가 호출됩니다.

REFERENCE

https://mangkyu.tistory.com/18

https://joont92.github.io/spring/View-ViewResolver/

  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기