본문 바로가기
Spring

[Spring] 스프링 MVC의 기본 구조

by Amy IT 2022. 8. 31.

 

목차

     

    MVC 패턴이란?

    이미지 출처 https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller

    MVC 패턴은 어플리케이션을 세 가지 영역, 즉 모델(Model), 뷰(View), 컨트롤러(Controller)로 구분하여 작업을 분리하는 웹 어플리케이션 개발 방법론으로서, 서로 간의 결합도를 최소화하고 유지보수성을 높이며 개발의 효율성을 향상시킵니다. 사용자가 입력을 담당하는 View를 통해 요청을 보내면 해당 요청을 Controller가 받고, Controller는 Model을 통해 데이터를 가져온 후, 해당 데이터를 바탕으로 출력을 담당하는 View를 제어해서 사용자에게 전달합니다.

     

    • Model : 어플리케이션이 무엇을 할 것인지 정의합니다. 내부 Business Login을 처리하기 위한 역할을 합니다. 즉, 데이터 저장소와 연동하여 사용자가 입력한 데이터나 사용자에게 출력할 데이터를 다룹니다.
    • View : 최종적으로 사용자에게 화면으로 무엇을 보여주기 위한 역할을 합니다. 즉, 모델이 처리한 데이터나 그 작업 결과를 가지고 사용자에게 출력할 화면을 만듭니다.
    • Controller : Model과 View 사이의 중계자로서, 클라이언트의 요청을 받으면 해당 요청에 대해 실제 업무를 수행하는 Model을 호출합니다. Model이 업무 수행을 완료하면 그 결과를 가지고 화면을 생성하도록 View에 전달합니다.

     

     

    Spring MVC

    스프링 MVC는 내부적으로 Servlet API를 활용합니다. Servlet/JSP에서는 HttpServletRequest, HttpServletResponse 객체를 이용해 브라우저에서 전송한 정보를 처리합니다. 스프링 MVC는 이러한 작업을 중간에서 내부적으로 처리해 주는 연결 역할을 하기 때문에, 개발자는 Servlet/JSP의 API를 신경 쓰지 않고 웹 어플리케이션을 제작할 수 있게 됩니다. 

     

    스프링 MVC는 '모델 2'라는 방식으로 처리되는 구조입니다. 모델 2 방식은 '로직과 화면을 분리'하는 스타일의 개발 방식입니다. 모델 2 방식에서 사용자의 요청은 Controller를 호출하고, Controller는 데이터를 처리한 후 처리된 데이터를 View로 전달합니다. 

     

    Spring MVC의 기본 구조

    이미지 출처 https://aridom.tistory.com/61

    1. 사용자의 모든 요청은 Front-Controller인 DispatcherServlet을 통해서 처리합니다. 
    2. DispatcherServlet은 받은 요청을 HandlerMapping으로 전달합니다. HandlerMapping은 요청의 처리를 담당하는 컨트롤러를 찾기 위해서 존재합니다. HandlerMapping 인터페이스를 구현한 여러 객체들 중 RequestMappingHandlerMapping의 경우, @RequestMapping 어노테이션을 기준으로 판단하게 됩니다. 요청받은 URL을 분석하여 적합한 컨트롤러를 반환합니다.
    3. DispatcherServlet이 HandlerAdapter를 이용해서 해당하는 컨트롤러를 동작시킵니다.
    4. Controller는 개발자가 작성하는 클래스로, 실제 요청을 처리하는 Business Logic을 작성하게 됩니다. 이때 View에 전달해야 하는 데이터는 주로 Model이라는 객체에 담아서 전달합니다. 
    5. Controller는 View의 이름을 DispatcherServlet에 반환합니다.
    6. DispatcherServlet은 ViewResolver를 호출하여 Controller가 반환한 View의 이름을 기반으로 적합한 View를 찾아줍니다.
    7. DispatcherServlet이 View에 처리 결과를 넘겨 최종 결과를 보여주도록 요청합니다. 
    8. View는 실제로 응답 보내야 하는 데이터를 jsp 등을 이용해서 생성하는 역할을 합니다. 만들어진 응답은 DispatcherServlet을 통해서 전송됩니다.

     

     

    설정 파일

    스프링 MVC는 스프링의 서브(sub) 프로젝트입니다. 스프링은 하나의 기능을 위해서만 만들어진 프레임워크가 아니라 '코어'라고 할 수 있는 프레임워크에 여러 서브 프로젝트를 결합해서 다양한 상황에 대처할 수 있도록 개발되었습니다. 서브 프로젝트는 간단히 설명하자면 '별도의 설정이 존재할 수 있다'는 개념입니다. 스프링 MVC 프로젝트는 일반 Java 영역에 대한 설정은 root-context.xml 에서 설정하고, Web 관련 영역은 servlet-context.xml 에서 설정하여 두 영역을 같이 연동해서 구동합니다. root-context.xml, servlet-context.xml 두 가지 설정 파일과 이들을 설정하기 위한 설정 파일인 web.xml을 살펴보면 스프링 MVC의 동작 원리를 조금 더 구체적으로 알 수 있습니다.

     

    설정 파일 설명
    web.xml 설정을 위한 설정 파일, WAS 구동과 관련된 설정
    root-context.xml 일반 Java 영역에 대한 설정
    servlet-context.xml WEB 관련 영역에 대한 설정

     

    web.xml

    이미지 출처 https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc

    프로젝트의 구동은 web.xml에서 시작합니다. WAS가 처음 구동될 때 web.xml을 읽어 웹 어플리케이션 설정을 구성합니다. root-context.xml 경로를 등록하고, ContextLoaderListener를 생성하며, DispatcherServlet을 등록하며 servlet-context.xml 경로를 지정합니다.

     

    1. root-context.xml의 경로가 설정되어 있습니다. 
    2. 스프링 MVC의 Context Listener가 등록되어 있습니다. Context Listener는 웹 어플리케이션 구동 시 가장 먼저 구동됩니다. ContextLoaderListener는 Root Context를 생성합니다. root-context.xml이 처리되면 root-context.xml에 정의된 객체들이 스프링의 영역(context) 안에 생성되고 객체들 간의 의존성이 처리됩니다.
    3. DispatcherServlet 클래스는 스프링 MVC의 구조에서 핵심적인 역할을 하는 클래스입니다. 내부적으로 웹 관련 처리의 준비작업을 진행하는데, 이때 사용하는 파일이 servlet-context.xml입니다. DispatcherServlet은 Root Context를 부모로 하는 자식 Context를 생성합니다. DispatcherServlet에서 XmlWebApplicationContext를 이용해서 servlet-context.xml을 로딩하고 해석합니다. 이 과정에서 등록된 객체들은 기존에 만들어진 객체들과 같이 연동하게 됩니다.
    4. DispatcherServlet의 이름으로 지정한 appServlet을 모든 url에 대해 매핑하는 설정으로서, 모든 요청을 DispatcherServlet이 받도록 처리하고 있습니다. 
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    
    	<!-- 1. The definition of the Root Spring Container shared by all Servlets and Filters -->
    	<context-param>
    		<param-name>contextConfigLocation</param-name>
    		<param-value>/WEB-INF/spring/root-context.xml</param-value>
    	</context-param>
    	
    	<!-- 2. Creates the Spring Container shared by all Servlets and Filters -->
    	<listener>
    		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    	</listener>
    
    	<!-- 3. Processes application requests -->
    	<servlet>
    		<servlet-name>appServlet</servlet-name>
    		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    		<init-param>
    			<param-name>contextConfigLocation</param-name>
    			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
    		</init-param>
    		<load-on-startup>1</load-on-startup>
    	</servlet>
    	
    	<!-- 4. servlet-mapping -->	
    	<servlet-mapping>
    		<servlet-name>appServlet</servlet-name>
    		<url-pattern>/</url-pattern>
    	</servlet-mapping>
    
    </web-app>

     

    root-context.xml

    일반 Java 영역에 대해 설정하는 설정 파일입니다. 대표적으로 Service나 DAO, 그리고 DB 연동을 위해 사용하는 DataSource, TransactionManager 등을 등록하는 코드가 포함될 수 있습니다. 

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
    	
    	<!-- Root Context: defines shared resources visible to all other web components -->
    		
    </beans>

     

    servlet-context.xml

    WEB 관련 영역에 대해 설정하는 설정 파일입니다. ViewResolver를 통해 View 페이지에 대한 설정을 할 수 있으며 Controller 빈을 등록하는 코드가 포함됩니다.

     

    1. MVC @Controller 설정을 활성화합니다. 적합한 Controller를 인식하도록 하는 HandlerMapping 역할을 합니다.
    2. resources 폴더 경로를 설정하여 resources 폴더 내의 정적인 resource를 효율적으로 제공할 수 있도록 합니다.
    3. ViewResolver는 사용자의 요청에 대한 응답 View를 렌더링하는 역할을 수행합니다. Controller가 반환하는 문자열의 앞에 prefix를 붙이고 뒤에 suffix를 붙여서 View 페이지 지정을 편리하게 합니다. 예를 들어 "home"이라는 문자열은 "/WEB-INF/views/home.jsp"이라는 문자열로 변환되도록 합니다.
    4. Controller 클래스가 속한 패키지 경로를 컴포넌트 스캔하여 Controller 빈이 자동으로 등록 및 생성되도록 합니다.
    <?xml version="1.0" encoding="UTF-8"?>
    <beans:beans xmlns="http://www.springframework.org/schema/mvc"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:beans="http://www.springframework.org/schema/beans"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
    		http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
    		http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    
    	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
    	
    	<!-- 1. Enables the Spring MVC @Controller programming model -->
    	<annotation-driven />
    
    	<!-- 2. Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
    	<resources mapping="/resources/**" location="/resources/" />
    
    	<!-- 3. Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
    	<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    		<beans:property name="prefix" value="/WEB-INF/views/" />
    		<beans:property name="suffix" value=".jsp" />
    	</beans:bean>
    	
    	<!-- 4. component-scan -->
    	<context:component-scan base-package="com.controller" />
    
    </beans:beans>

     

     

     

    참고

     

     

    댓글