<참조> https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/mvc.html

Spring WEB MVC 프레임워크 (1)

 

1. 스프링 웹 MVC 프레임워크 소개

Spring 웹 MVC 프레임워크는 DispatcherServlet 기반으로 설계되었다. DispatcherServlet는 핸들러 매핑, 뷰 처리, 로케일 및 테마 처리, 파일 업로드 지원과 함께 핸들러에 요청을 전달한다. 기본 핸들러는 @Controller, @RequestMapping 어노테이션 표기를 하며 다양한 처리 방법을 제공한다. Spring 3.0은 @Controller, @PathVariable 어노테이션 등의 기능을 이용하여 RESTful 웹 사이트 및 애플리케이션을 만들 수 있다.

 MVC  =  Mode l - View - Controller 

 

Spring Web MVC에서는 모든 객체를 명령 또는 양식(form-backing) 객체로 사용할 수 있다. Spring의 데이터 바인딩(결합)은  유연하다. 예를 들어 유형 불일치 오류는 시스템 오류가 아니라 애플리케이션에서 다룰 수 있는 유효성 검사 오류로 처리한다. 따라서 잘못된 제출 처리나 문자열을 적절하게 변환하기 위해 비즈니스 개체의 속성을 양식형 개체 형식이 지정되지 않은 단순 문자열로 복제할 필요가 없다. 대신 비즈니스 개체에 직접 바인딩하는 것이 더 나은 경우도 많다.

Spring의 뷰 해석은 매우 유연하다. 일반적으로 'Controller'는 데이터를 가진 모델을 준비하고 Map 뷰 이름을 선택하는 일을 처리하지만 응답 스트림에 직접 쓰고 요청을 완료할 수도 있다. 이름 확인은 빈 이름, 속성 파일 또는 사용자 정의 'ViewResolver' 구현을 통해 파일 확장자 또는 'Accept' 헤더 콘텐츠 유형을 통해 구성할 수 있다. 모델(MVC의 M)은 Map 뷰 기술의 추상화를 허용하는 인터페이스이다. JSP, Velocity 및 Freemarker 같은 템플릿 기반 렌더링 기술과 직접 통합하거나 XML, JSON, Atom 및 여러 유형 콘텐츠를 직접 생성할 수 있다. 모델 Map은  JSP 요청 속성과 같은 적절한 형식으로 간단히 변환된다.

스프링 웹 MVC 특징

Spring 웹 모듈에는 다음과 같은 웹 지원 기능이 포함되어 있다.

  • 역할의 명확한 분리.  컨트롤러, 유효성 검사기, 명령 개체, 양식 개체, 모델 개체, DispatcherServlet 처리기 매핑, 뷰 처리기 등의 역할은 각가의 특별한 개체에 의해 수행될 수 있다.
  • JavaBeans로 프레임워크 및 애플리케이션 클래스의 강력하고 간단한 구성.  이 구성 기능에는 웹 컨트롤러에서 비즈니스 개체 및 유효성 검사기에 이르기까지 컨텍스트 전반에 걸쳐 쉽게 참조할 수 있는 기능이 포함된다.
  • 적응성, 비침입성 및 유연성. 주어진 시나리오에 대해 매개변수 어노테이션(예: @RequestParam, @RequestHeader, @PathVariable 등) 중 하나를 사용하여 필요한 컨트롤러 메서드를 정의한다.
  • 재사용 가능한 비즈니스 코드. 특정 프레임워크 기본 클래스를 확장하기 위해 미러링하는 대신 기존 비즈니스 개체를 명령 또는 양식 개체로 사용한다.
  • 사용자 정의 가능한 바인딩 및 유효성 검사 . 잘못된 값, 현지화된 날짜 및 숫자 바인딩 등에 대한 유형 불일치, 유효성 검사를 응용 프로그램 수준에서 처리할 수 있다.
  • 사용자 정의 가능한 핸들러 매핑 및 뷰 해석. 핸들러 매핑 및 뷰 구분은 간단한 URL 기반에서 특수 목적으로 구축된 정교한 서비스까지 다양하다. 
  • 유연한 모델 전송. 이름/값 Map을 사용한 모델 전송은  뷰 기술과 통합하기 쉽다.
  • 사용자 정의 가능한 로케일 및 테마 해석, Spring 태그 라이브러리가 있거나 없는 JSP 지원, JSTL 지원, 추가 브리지 없이 Velocity 지원 
  • 데이터 바인딩 및 테마 기능을 지원하는 JSP 태그 라이브러리. 사용자 정의 태그는 마크업 코드 측면에서 유연성을 허용한다. 
  • Spring 2.0에 도입된 JSP 양식 태그 라이브러리. JSP 페이지에서 양식을 쉽게 작성할 수 있다. 
  •  수명 주기가 현재 HTTP 요청 또는 HTTP Session 범위가 지정된 Bean. 이것은 Spring MVC 기능이 아니라WebApplicationContext Spring MVC가 사용하는 컨테이너 기능이다. 

 

2. DispatcherServlet

Spring 웹 MVC 프레임워크는 다른 웹 MVC 프레임워크와 마찬가지로 요청 기반이며 컨트롤러에 요청을 전달하고 웹 애플리케이션 개발을 용이하게 하는 중앙 서블릿을 중심으로 설계되었지만 DispatcherServlet는 그 이상을 수행한다. Spring IoC 컨테이너와 통합되어 Spring의 다른 기능을 사용할 수 있다. Spring Web MVC의 DispatcherServlet 요청 처리 흐름은 다음 그림과 같다. 

Spring Web MVC의 요청 처리 흐름

DispatcherServlet 실제로 Servlet(HttpServlet 상속함)이며 웹 응용 프로그램 web.xml에 선언된다. web.xml 파일에서 URL 매핑을 사용하여 처리할 요청을 매핑한다. 다음 예제는 DispatcherServlet 선언 및 매핑을 보여준다.

[web.xml]

<web-app>
    <servlet> 
        <servlet-name>example</servlet-name> 
        <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> 
        <load-on-startup> 1 </load-on-startup > 
    </servlet>
    <servlet-mapping> 
        <servlet-name>example</servlet-name> 
        <url-pattern> /example/* </url-pattern> 
    </servlet-mapping>
</web-app>

앞 예에서 /example로 시작하는 모든 요청은 DispatcherServlet에 의해 인스턴스 example에서 처리됩니다. Servlet 3.0+에서는 프로그래밍 방식으로 Servlet 컨테이너를 구성하는 옵션도 있다. 다음은 web.xml 예제와 동일한 코드 기반 예제이다.

public class MyWebApplicationInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext container) {
        ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet());
        registration.setLoadOnStartup(1);
        registration.addMapping("/example/*");
    }
}

WebApplicationInitializer는 Spring MVC에서 제공하는 인터페이스이다. 이것은 코드 기반 구성을 감지하고 모든 Servlet 3 컨테이너를 초기화하는 데 자동으로 사용되도록 해준다. AbstractDispatcherServletInitializer 인터페이스의 추상 기본 클래스 구현은 서블릿 매핑을 지정하여 DispatcherServlet 등록을 쉽게 만든다. 

이제 Spring Web MVC 프레임워크에서 사용되는 다양한 빈(bean)을 등록해야 한다. Web MVC 프레임워크에서 각 DispatcherServlet은 자기 WebApplicationContext를 갖는다. 빈은 서블릿 특정 범위에서 재정의될 수 있으며 주어진 서블릿 인스턴스 로컬의 빈을 정의할 수 있다.

Spring Web MVC 컨텍스트 계층
 

DispatcherServlet 초기화 시 Spring MVC는 웹 애플리케이션  WEB-INF 디렉토리에서 지정된 파일(서블릿명-servlet.xml)에 정의된 빈을 생성하여 전역 범위에서 동일한 이름으로 정의된 빈을 다시 정의한다. 다음 DispatcherServlet 서블릿 구성을 보자. (web.xml) 

<web-app>
    <servlet>
        <servlet-name>golfing</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>golfing</servlet-name>
        <url-pattern>/golfing/*</url-pattern>
    </servlet-mapping>
</web-app>

이런 Servlet 구성을 사용하는 응용 프로그램에 /WEB-INF/golfing-servlet.xml 파일이 존재해야 한다 . 이 파일에는 모든 Spring Web MVC 관련 구성 요소(빈)가 포함된다. 서블릿 초기화 매개변수를 통해 이 구성 파일의 위치를 변경할 수 있다.

WebApplicationContext는 웹 애플리케이션에 필요한 추가 기능이 있는 확장이다. WebApplicationContext는 ServletContext에 결합되며 RequestContextUtils 클래스의 정적 메서드를 사용하여 WebApplicationContext를 조회할 수 있다.

 

2.1 WebApplicationContext의 특별한 Bean 유형 

DispatcherServlet은 요청을 처리하고 적절한 뷰를 렌더링하기 위해 특별한 빈을 사용한다. 이 빈은 Spring MVC의 일부이다. WebApplicationContext에서 하나 이상 구성하기만 하면 사용할 특별한 빈을 선택할 수 있다. 

 

표 1. WebApplicationContext의 특별한 Bean  

HandlerMapping HandlerMapping 구현에 따라 세부사항이 달라지는 일부 기준에 따라 수신 요청을 처리기 및 전처리 및 후처리기(처리기 인터셉터) 목록에 매핑한다. 널리 사용되는 구현은 어노테이션이 달린 컨트롤러를 지원하지만 다른 구현도 존재한다.
HandlerAdapter DispatcherServlet이 핸들러가 실제 호출되었는지 여부에 관계없이 요청에 매핑된 핸들러를 호출하도록 도와준다. 예를 들어, 어노테이션이 달린 컨트롤러를 호출하려면 다양한 어노테이션을 해결해야 한다. 따라서 HandlerAdapter 주요 목적은 이런 세부 사항으로부터 DispatcherServlet을 보호하는 것이다.
HandlerExceptionResolver 예외를 뷰에 매핑하여 복잡한 예외 처리 코드도 허용한다.
ViewResolver 논리적 문자열 기반의 뷰 이름을 실제 View 유형으로 확인한다.
LocaleResolver 국제화된 뷰를 제공할 수 있도록 클라이언트가 사용하는 로케일을 확인한다.
ThemeResolver 예를 들어 개인화된 레이아웃을 제공하기 위해 웹 애플리케이션에서 사용할 수 있는 테마를 해석한다.
MultipartResolver 예를 들어 HTML 양식에서 파일 업로드 처리를 지원하기 위해 여러 부분으로 구성된 요청을 구문 분석합니다.
FlashMapManager 일반적으로 리디렉션을 통해 한 요청에서 다른 요청으로 속성을 전달하는 데 사용할 수 있는 "입력" 및 "출력" FlashMap을 저장하고 검색한다.

 

2.2 기본 DispatcherServlet 구성

특별한 빈에 대해 DispatcherServlet은 사용할 구현 목록을 관리한다. 이 정보는 org.springframework.web.servlet 패키지의 DispatcherServlet.properties 파일에 보관된다.

특별한 빈에는 기본값이 있다. 예를 들어 InternalResourceViewResolver가 접두사 속성을 뷰 파일의 상위 위치로 설정하도록 구성한다. 다만 WebApplicationContext에서 InternalResourceViewResolver와 같은 특수 빈을 구성하면 해당 특수 빈 유형에 대한 기본 구현 목록을 재정의한다는 것에 유의하자. 예를 들어 InternalResourceViewResolver를 구성하는 경우 ViewResolver 구현 기본 목록은 무시된다.

 

2.3 DispatcherServlet 처리 순서

DispatcherServlet을 설정하고 특정 DispatcherServlet에 대한 요청이 들어오면 DispatcherServlet은 다음과 같이 요청 처리를 진행한다.

  1. WebApplicationContext는 컨트롤러와 프로세스의 다른 요소가 사용할 수 있는 속성으로 요청에서 검색되고 바인딩된다. 기본적으로 DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE 키 아래에 바인딩 된다.
  2. 로케일 확인자는 요청을 처리(뷰 렌더링, 데이터 준비 등)할 때 사용할 지역을 확인하기 위해 프로세스의 요소를 활성화하는 요청에 바인딩됩니다. 로케일 해석이 ​​필요하지 않으면 필요하지 않다.
  3. 테마 해석기는 뷰와 같은 요소가 사용할 테마를 결정하도록 하는 요청에 바인딩된다. 테마를 사용하지 않는다면 무시해도 된다.
  4. 멀티파트 파일 확인자를 지정하면 요청에서 멀티파트가 검사된다. 멀티파트가 발견되면 프로세스의 다른 요소에 의한 추가 처리를 위해 요청이 MultipartHttpServletRequest에 래핑 된다.
  5. 적절한 핸들러가 검색된다. 핸들러를 찾으면 모델 또는 렌더링을 준비하기 위해 핸들러(전처리기, 후처리기 및 컨트롤러)와 연결된 실행 체인이 처리된다.
  6. 모델이 반환되면 뷰가 렌더링된다. 모델이 반환되지 않으면(보안 이유로 요청을 가로채는 전처리기 또는 후처리기로 인한 것일 수 있음) 요청이 이미 이행되었을 수 있으므로 뷰가 렌더링되지 않는다.

WebApplicationContext에 선언된 핸들러 예외 해석기는 요청을 처리하는 동안 throw 예외를 선택한다. 이러한 예외 해결 프로그램을 사용하면 예외를 처리하기 위한 사용자 처리을 정의할 수 있다.

Spring DispatcherServlet은 또한 Servlet API에 의해 지정된 대로 last-modification-date의 반환을 지원한다. 특정 요청에 대한 마지막 수정 날짜를 결정하는 프로세스는 간단하다. DispatcherServlet은 적절한 핸들러 매핑을 찾고 찾은 핸들러가 LastModified 인터페이스를 구현하는지 테스트한다. 그렇다면 LastModified 인터페이스의 getLastModified(request) 메서드 값이 클라이언트에 반환된다.

web.xml의 Servlet 선언에 Servlet 초기화 매개변수(init-param 요소)를 추가하여 개별 DispatcherServlet 인스턴스를 사용자 정의할 수 있다. 

표 2. DispatcherServlet 초기화 매개변수

contextClass 이 서블릿에서 사용하는 컨텍스트를 인스턴스화하는 WebApplicationContext를 구현하는 클래스이다. 기본적으로 XmlWebApplicationContext가 사용된다.
contextConfigLocation 컨텍스트를 찾을 수 있는 위치를 나타내기 위해 컨텍스트 인스턴스(contextClass에 의해 지정)에 전달되는 문자열이다. 문자열은 여러 컨텍스트를 지원하기 위해 여러 문자열(쉼표 구분 기호 사용)으로 구성된다. Bean이 두 번 정의된 여러 컨텍스트 위치의 경우 최신 위치를 우선한다.
namespace WebApplicationContext의 네임스페이스이다. 기본값은 서블릿명-servelet이다.

 

 

 

반응형

'SPRING' 카테고리의 다른 글

Spring WEB MVC 프레임워크 (3)  (0) 2022.06.13
Spring WEB MVC 프레임워크 (2)  (0) 2022.06.13
Spring, JDBC 예제 코드  (0) 2022.06.12
이클립스 메이븐 프로젝트 만들기  (0) 2022.06.06
스프링 부트 JAR 독립 실행/배포  (0) 2022.06.06

+ Recent posts