본문 바로가기
Spring/이론

MVC(Model-View-Controller)

by 모스키토끼 2020. 3. 17.

Spring MVC Framework

  • 웹 애플리케이션 개발을 위한 모델 뷰 컨트롤러 아키텍처를 제공한다.
    • Model
      - 애플리케이션 데이터를 캡슐화하고 일반적으로 POJO(순수 자바 객체)로 구성된다..
    • View
      - 모델 데이터를 렌더링하고 일반적으로 HTML 출력을 생성한다.
    • Controller
      - 사용자 요청을 처리하고 적절한 모델을 작성하고 렌더링을 위해 View로 전달한다.

1. 개요

Spring MVC Architecture

  • Dispatcher servlet

    • 사용자의 요청을 맨 먼저 받는다.(Front Controller로서 작동한다.)
    • 요청을 적절한 Controller에게 전달해주는 역할
      (애플리케이션으로 들어오는 모든 요청을 intercept 하고 Handler(Controller)에 디스패치(전달)한다.)
    • 요청을 처리하기 위해 Controller에 대한 Handler Mapping을 참조한다.
    • Spring이 만들어준다.
  • Handler Mapping

    • 요청이 들어오면 어떤 Controller가 수행되어야 하는지 알려주는 매핑 테이블
      (특정 요청을 처리하는 적절한 Controller를 찾아 응답한다.)
    • 요청 URL과 Controller 클래스 간의 매핑은 XML 설정 또는 Annotation으로 수행된다.
  • Controller

    • 실제로 사용자의 요청을 처리한다.(다른 business/service 클래스를 호출하여 요청을 처리)
    • 결과를 View로 전달될 Model 객체에 저장
  • View Resolver

    • 적절한 View를 찾아준다.
      (Logical 이름으로부터 Physical view file를 찾는다.)
  • View

    • 필요한 Model을 가져와 보여준다.
    • Physical view file -> JSP, HTML, XML, Velocity template

참고)

Spring이 제공하는 클래스: Dispatcher Servlet, Handler mapping, View Resolver

 

2. 요구되는 Configuration

Maven Configuration(POM.xml)

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">  
  <modelVersion>4.0.0</modelVersion>  
  <groupId>com.javatpoint</groupId>  
  <artifactId>SpringMVC</artifactId>  
  <packaging>war</packaging>  
  <version>0.0.1-SNAPSHOT</version>  
  <name>SpringMVC Maven Webapp</name>  
  <url>http://maven.apache.org</url>  
  <dependencies>  
    <dependency>  
      <groupId>junit</groupId>  
      <artifactId>junit</artifactId>  
      <version>3.8.1</version>  
      <scope>test</scope>  
    </dependency>  
      
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->  
<dependency>  
    <groupId>org.springframework</groupId>  
    <artifactId>spring-webmvc</artifactId>  
    <version>5.1.1.RELEASE</version>  
</dependency>  
  
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->  
<dependency>    
    <groupId>javax.servlet</groupId>    
    <artifactId>servlet-api</artifactId>    
    <version>3.0-alpha-1</version>    
</dependency>  
  
  </dependencies>  
  <build>  
    <finalName>SpringMVC</finalName>  
  </build>  
</project>  

Web deployment descriptor(web.xml)

 

  • DispatcherServlet
    - 스프링 컨테이너 (WebApplicationContext)를 인스턴스 화한다.

    - 요청 --> DispatcherServlet --- instantiate
    ---> Spring Container( Controller(Bean), Special Beans(HandlerMapping, ViewResolver) )
    - DI 컨테이너와 마찬가지로 WebApplicationContext에는 일부 구성 메타 데이터(XML 파일)가 제공되어야 한다.
    • <init-param>에서 설정해준 sales-context.xml이 메타 데이터(sales- 예시로 sales 관련 요청을 설정한 파일명이다.
       
<?xml version="1.0" encoding="UTF-8"?>  
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">  
  <display-name>SpringMVC</display-name>  
   <servlet>    
    <servlet-name>spring</servlet-name>    
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/sales-context.xml</param-value>
    </init-param>

    <load-on-startup>1</load-on-startup>      
</servlet>    
<servlet-mapping>    
    <servlet-name>spring</servlet-name>    
    <url-pattern>/</url-pattern>    
</servlet-mapping>    
</web-app>  
  • ContextLoadListener
    - 공유 Bean을 포함하는 Spring Container를 인스턴스화 한다.
    - DispatcherServlet으로 작성된 Bean은 ContextloaderListener로 작성된 Bean을 참조할 수 있다.

Parent인 ContextLoadListener의 Spring Container는 Child인 DispatchServlet의 Spring Container에게 참조될 수 있다. 반대는 불가능

 

<listener>
  <listener-class>
    org.springframework.web.context.ContextLoaderListener
  </listener-class>
</listener>
  
<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/spring/applicationContext.xml</param-value>
</context-param>

참고)

Spring Container: Bean을 생성해주고, 의존성을 주입해주는 역할

공유되는 Bean들은 ContextLoadListener에 넣어두고

그렇지 않은 Bean들은 DispatcherServlet에 넣어둔다.(그렇지 않은 Bean 예시: Controller)

 

web.XML 설정 및 Spring MVC Configuration 예시

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:app-config.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <servlet>
        <servlet-name>my-dispatcher-servlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:web-config.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>my-dispatcher-servlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

- 공유 빈을 관리하는 contextLoadListener의 설정 파일 명은 app-config.xml

- 공유하지 않은 빈을 관리하는 DispatcherServlet의 설정 파일 명은 web-config.xml

app-config.xml

  • 모든 서블릿과 필터에서 공유될 수 있는 root Spring container의 설정을 지정한다.
  • 애플리케이션 시작 시 Spring의 ContextLoaderListener에 의해 로드된다.
  • 이 파일은 기본적으로 비어 있다.

web-config.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/mvc
                           http://www.springframework.org/schema/mvc/spring-mvc.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd ">

    <mvc:annotation-driven />
    <resources mapping="/resources/**" location="/resources/" />

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="suffix" value=".jsp" />
    </bean>
    
     <context:component-scan base-package="com.memorynotfound" />

</beans>
  • <mvc:annotation-driven />
    - 지정된 패키지의 파일을 스캔하기 위해 annotation 기반 접근 방식을 사용하도록 프레임 워크에 지시한다.
  • <resources mapping.../>
    - 정적 리소스를 HTTP GET 요청과 직접 매핑한다.
    따라서 Image, JavaScript, CSS 등의 리소스들은 Controller를 거치지 않아도 된다.
  • <bean class="... InternalResourceViewResolver">
    - Controller가 반환한 Logical Name에 따라 프레임워크가 실제 JSP 파일을 찾을 수 있게 경로 매핑을 해준다.
    -> 예를 들어, Controller가 sales를 반환한다면 /WEB-INF/views/sales.jsp로 매핑
  • context:component-scan.../>
    - Annotation 기반 strategy를 사용할 때 어떤 패키지를 스캔할지 Spring Container에 알려준다.
    - Container에 annotation이 달린 Controller를 auto-detect(자동 감시)하도록 한다.
    - Container는 패키지 아래의 모든 클래스를 스캔한다.

3. Model

  • 모델은 결과의 일부를 포함한다.
  • Controller에서 뷰로 객체를 전달하는 데 사용.
  • 명명 된 객체의 컬렉션

MVC 아키텍처 Model

  1. 브라우저 request
  2. Presentation Layer(Front Controller, View, Controller)의 Front Controller(DispatcherServlet)가 요청을 받음
  3. DispatcherServlet은 적절한 Controller를 찾아 호출
  4. Controller는 Service Layer에 데이터 처리를 요청
  5. Service Layer -> DAO Layer 호출
  6. DAO Layer에서 받은 데이터를 Model 형태로 Service Layer를 타고 Controller에게 전달
  7. Controller는 Model을 DispatcherServlet에 전달
  8. DispatcherServelt은 View에 Model을 전달
  9. View는 Model을 가지고 HTML을 렌더링 후 DispatcherServlet에 전달
  10. DispatcherServlet은 브라우저에 response

Model Implement 

  • java.util.map( public String getData(Map <String, Object> model){...} )
    - 요구사항: Model 속성을 저장할 때 key의 자료형이 Spring 이어야 한다.
@RequestMapping("/data")
public String getData(Map<String, Object> model){
	String data = service.getData();
    model.put("data", data)
    return "home"
}

 

  • Spring에서 제공한 Model( public String getData(Model model){... } )
    • Map 사용의 단점은 모델의 속성 이름들을 일일이 정해야 한다는 단점이 있다.
    • Model 인터페이스는 addAttribute()같이 Model 속성을 채우는 편리한 메서드를 제공한다.
    • addAttribute()는 자동으로 모델 속성을 생성해준다는 점을 제외하면 Map의 put 메서드와 같다.
@RequestMapping("/data")
public String getData(Model model){
	List<Data> datas = service.getData();
    model.addA

 

  • ModelMap 객체는 Spring에서 제공한다.( public String getData (ModelMap model){ ... } )
    • Model 인터페이스에서 좀 더 편한 기능 제공
      - addAttribute() 메서드에 체이닝 기법 적용
@RequestMapping("/data")
public String getData(ModelMap model){
	model.addAttribute("Lname", "kwon")
    	.addAttribute("Fname","DH");
        
    return "home"
}

4. @Controller

  • Spring Controller는 @Controller annotation이 달린 bean이다.
  • @RequestMapping
    • URL을 전체 클래스 또는 특정 핸들러 메서드에 맵핑하는 데 사용된다.
@Controller
public class HomeController{
	
    @RequestMapping(value="/", method=RequestMethod.GET)
    public String home(Local local, Model model){
    	Date date = new Date();
        DataFormat dataFormat = DataFormat.getTimeInstance(DataFormat.LONG, DataFormat.LONG, locale);
        
        String formatteDate = dataFormat.format(data);
        
        model.addAttribute("serverTime", formattedData);
        return "home";
  	}
}

- 이 메서드는 "home"이라는 View를 리턴한다.

-> "web-config.xml"파일(DispatchServlet의 설정 파일)에 지정된 viewResolver에 의해 실제 파일을 찾는다.

 

  • @RequestParam
    • URL에 쿼리 값을 받을 수 있다.
@RequestMapping(value= "/login", method = RequestMethod.GET)
public String doLogin(@RequestParam String username,
					@RequestParam String password){
                    
       return ...;
}

References

https://memorynotfound.com/spring-mvc-xml-configuration-example/

 

Spring MVC XML Configuration Example

This tutorial shows how to build a basic web application using Spring MVC XML Configuration. We create a simple controller that’ll handle incomming requests and forwards the response to a simple view that’ll display...

memorynotfound.com

https://howtodoinjava.com/spring-mvc/contextloaderlistener-vs-dispatcherservlet/

불러오는 중입니다...

https://www.javatpoint.com/spring-mvc-tutorial

 

Spring MVC Tutorial - javatpoint

Spring MVC Tutorial. Let's see the spring mvc form example, spring mvc flow, spring mvc validation and spring mvc tiles examples.

www.javatpoint.com

 

'Spring > 이론' 카테고리의 다른 글

Spring Security  (0) 2020.03.30
Spring Web Form  (0) 2020.03.25
DB 연동(with Spring JDBC)  (0) 2020.03.09
관점 지향 프로그래밍(AOP, Aspect Oriented Programming)  (0) 2020.03.07
의존성 주입(Dependency Injection)  (0) 2020.03.05

댓글