본문 바로가기
Spring/Spring Core

[Spring 핵심 알기 - 1] DispatcherServlet 란? frontController 패턴 (with. 전자정부프레임워크 )

by 디찌s 2024. 2. 22.
728x90
반응형

 

 

스프링 MVC 구성

 

 

스프링을 공부하기 시작하면 위와 같은 도식화를 맞닥뜨리게 된다.

 

위 도식화는 현재 스프링이 어떤 식으로 클라이언트에게 view를 전달하는지에 대해 간략한 도식화이며, 이를토대로

 

각각에 대한 핵심 역할들을 알아보고 생각해보는 시간을 가질예정이다.

 

 

시작에 앞서....

 

tomcat server

tomcat server는 대표적인 web application server이다. spring boot에서도 기본 서버로 채택하여 셋팅하는 서버이며,

 

대부분에 si사업이든 플랫폼 사업이든  tomcat server를 많이 사용한다.

 

tomcat server는 사용자가 아래와 같이 url를 요청하면 url에 맵핑된 servlet을 돌려준다.

 

 

 

 

 

 

 

스프링이 나오기전에 아래와 같이 servlet 위주 개발을 많이했다.

 

/**
 * Servlet implementation class ServletParameterEx
 */
@WebServlet("/DoServlet")
public class ServletParameterEx extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public ServletParameterEx() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        response.getWriter().append("Served at: ").append(request.getContextPath());
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);

        request.setCharacterEncoding("EUC-KR");

        String id = request.getParameter("id_info");
        String pw = request.getParameter("pw_info");
        String name = request.getParameter("name_info");
        String[] hobby = request.getParameterValues("hobby");
        String sex = request.getParameter("sex");

        System.out.println("id : " + id);
        System.out.println("pw : " + pw);
        System.out.println("name : " + name);
        System.out.println("sex(남/여) : " + sex);
        System.out.println("hobby : " + Arrays.toString(hobby));
    }

}

 

 

위 코드에서 나오는 '/DoServlet' 톰캣서버에서 인식하는 url이며,

 

톰캣 서버는  '/DoServlet'  url과 맵핑되는 servlet을 찾아다가 클라이언트에게 던져주는 작업을한다.

 

그리고 이 과정을 적는것이 web.xml 이다.

 

 

<servlet>
    <servlet-name>servlet</servlet-name>
    <servlet-class>test.ServletController</servlet-class>

</servlet>

<servlet-mapping>
   <servlet-name>servlet</servlet-name>
   <url-pattern>/action.do</url-pattern>
</servlet-mapping>


 

위처럼 web.xml 파일을 열어보면 위 와같은 내용들을 볼수있는데,

 

tomcat 서버는 web.xml을 읽고 클라이언트가 action.do url을 요청하면 'action.do' 와 맵핑 되어있는 ServletController클래스를 돌려준다.

 

*또한 web.xml에는 filter 등에 내용들도 적어줘서 url 접근전에 여러가지 로직을 수행하는 filter를 만든다.

 

예전엔 servlet을 만들면 이 web.xml에 각 url과 맵핑할 서블렛들을 하나하나 다 적어줘야했다.

 

그러다보니 web.xml은 방대해지고 관리하기 어려워 지기시작했다.

 

이것을 해결하기 위해 FrontController 패턴으로 만들어진 dispatcherServlet이 등장하면서 손쉽게 관리할수있게 되었다.

 

 

FrontController 패턴이란 ?

 

 단 하나의 중앙 Controller를  프레젠테이션 계층맨 앞의둬서 서버로 오는 요청들을  모두 받아 처리하는 패턴이다.

FrontController는 요청에 대한 공통적인 작업을 한후 세부 작업들은 해당 컨트롤러에 위임한다.

또한 클라이언트에게 보낼 뷰를 선택해 최종결과를 생성하는 등의 작업을 수행한다.

그리고 예외가 발생했을 때 이를 일관된 방식으로 처리하는 것도 프론트 컨트롤러의 역할이다.

위와같은 ForntController가 Spring에서는 바로 DispatcherServlet이고, 스프링이 제공하는 스프링 서블릿/MVC의 핵심이다.

 

 

XML을 이용한 DispatcherServlet 구성
  <servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/config/springmvc/dispatcher-servlet.xml</param-value>
    </init-param>
    <load-on-startup>0</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

 

 

톰캣을 위와같이 web.xml에 설정해 놓으면,  모든 url에 대한 요청에대한 맵핑 처리과정을 dispactherServlet에 위임시킨다

 

웹브라우저 요청 과정

  1. 요청 Url을 DispathcerServlet이 받음
  2. DispatcherServlet은 HandlerMapping에게 요청 받은 url과 매칭되는 컨트롤러를 검색하도록 위임 (@RequestMapping)
  3. 컨트롤러를 찾고 handlerAdapter로 처리를 요청
  4. 컨트롤러를 실행하고 결과를 리턴 (ModelAndView)
  5.  

 

 

 

 

 

dispatcherServlet은 위 사진과 같이 흔히 말하는 mvc패턴이라는 역할을 한다.

 

2.전자정부프레임워크 web.xml분석

 

전자정부프레임워크나 기본 스프링부트나 전부다 뼈대는 스프링인건 매한가지다. 그러므로 xml로 dispatcherServlet을 설정하거나 java 파일로 설정하는것이 다를뿐이다.

 

전자전부프레임워크에 web.xml을 간략이 보자면 dispatcherServlet클래스를 불러오고 init-param을 통해 dispatcher-servlet.xml 을 주입해준다.

   ...


  <listener>
    <listener-class>
            org.springframework.security.web.session.HttpSessionEventPublisher
        </listener-class>
  </listener>

  <servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/config/springmvc/dispatcher-servlet.xml</param-value>
    </init-param>
    <load-on-startup>0</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

  <welcome-file-list>
    <welcome-file>login.do</welcome-file>
  </welcome-file-list>

  ...

 

 

dispatcherServlet 클래스에서 상속받는 FrameworkServlet 를 보면 setContextConfigLocation 메소드가 있고 web.xml에 init-param에 넣어주는 dispatch-servlet.xml 를 넣어준다. 이제 dispatch-servlet.xml를 보자

 

    <context:component-scan base-package="kr.co.jirandata" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
    </context:component-scan>

    <util:properties id="config" location="classpath:/conf/config.xml" />

    <mvc:annotation-driven/>

    <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
    <mvc:resources mapping="/resources/**" location="/resources/" />
    <mvc:resources mapping="/admin_img/**" location="/admin_img/" />
    <mvc:resources mapping="/rrdtool/**" location="/rrdtool/" />
    <mvc:resources mapping="/messages/**" location="classpath:/messages/" /> 

    <!--robots -->
    <mvc:resources mapping="/robots.txt" location="/robots.txt" order="0"/> 


    ...


    <!-- JsonView -->
    <bean class="org.springframework.web.servlet.view.BeanNameViewResolver" id="viewResolver" p:order="0"/>
    <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView" id="jsonView">
        <!-- property name="contentType" value="application/json;charset=UTF-8"/-->
        <property name="contentType" value="text/plain;charset=UTF-8"/>
    </bean>

 

 

component-scan을 통해 맵핑되어있는 컨트롤러를 찾아서 클래스를 실행시키고 ViewResolver를통해 해당 내용을 view에 던져준다. '<mvc:resource ...>' 부분은 해당 경로는 정적 리소스라고 알려준다.

728x90
반응형

댓글