[Spring] Web MVC 패턴의 흐름과 Controller, View, Model 구현법

JeongEun Kim·2023년 4월 28일
0

Spring

목록 보기
5/8

MVC(Model-View-Controller) Pattern

MVC 패턴이란?

MVC (모델-뷰-컨트롤러) 는 사용자 인터페이스, 데이터 및 논리 제어를 구현하는데 널리 사용되는 소프트웨어 디자인 패턴이다. 소프트웨어의 비즈니스 로직과 화면을 구분하는데 중점을 두고 있다. 이러한 "관심사 분리" 는 더나은 업무의 분리와 향상된 관리를 제공한다.

어플리케이션의 확장을 위해 Model, View, Controller라는 세 가지 영역으로 분리한다. 컴포넌트의 변경이 다른 컴포넌트에 영향을 미치지 않아 유지보수가 용이하며, 컴포넌트 간의 결합성이 낮아 프로그램 수정이 용이해 확장성이 뛰어나다.

Model

  • 어플리케이션 상태의 캡슐화
  • 상태 쿼리에 대한 응답
  • 어플리케이션의 기능 표현
  • 변경을 View에 통지

View

  • 모델을 화면에 시각적으로 표현
  • 모델에게 업데이트 요청
  • 사용자의 입력을 컨트롤러에 전달
  • 컨트롤러가 view를 선택하도록 허용

Controller

  • 어플리케이션의 행위 정의
  • 사용자 액션을 모델 업데이트와 mapping
  • 응답에 대한 view 선택

Web MVC 요청 흐름


MVC 패턴의 장단점

장점

  • 화면과 비즈니스 로직을 분리해서 작업 가능
  • 영역별 개발로 인해 확장성이 뛰어남
  • 표준화된 코드를 사용하므로 공동작업이 용이하고 유지보수성이 좋음

단점

  • 개발과정이 복잡해 초기 개발속도가 늦음
  • 초보자가 이해하고 개발하기에 다소 어려움



Spring Web MVC

Spring MVC란?

Spring MVC란, Spring에서 제공하는 웹 모듈로 Model, View, Controller 세가지 구성요소를 사용해 사용자의 다양한 HTTP Request를 처리하고 다양한 응답을 할 수 있도록 만든 프레임워크이다.

Spring MVC의 특징

  • Spring은 DI나 AOP 같은 기능 뿐만 아니라, Servlet 기반의 WEB 개발을 위한 MVC Framework를 제공
  • Spring MVC는 Model2 Architecture와 Front Controller Pattern을 Framework 차원에서 제공
  • Spring MVC Framework는 Spring을 기반으로 하고있기 때문에 Spring이 제공하는 Transaction 처리나 DI 및 AOP 등을 손쉽게 사용

Spring MVC 구성요소

DispatcherServlet(Front Controller)

  • 모든 클라이언트의 요청을 전달받음
  • Controller에게 클라이언트의 요청을 전달하고, Controller가 리턴한 결과값을 View에 전달하여 알맞은 응답을 생성

HandlerMapping

  • 클라이언트의 요청 URL을 어떤 Controller가 처리할지를 결정
  • URL과 요청 정보를 기준으로 어떤 핸들러 객체를 사용할지 결정하는 객체이며, DispatcherServlet은 하나 이상의 핸들러 매핑을 가질 수 있음

Controller

  • 클라이언트의 요청을 처리한 뒤, Model을 호출하고 그 결과를 DispatcherServlet에 알려줌

ModelAndView

  • Controller가 처리한 데이터 및 화면에 대한 정보를 보유한 객체

ViewResolver

  • Controller가 리턴한 뷰 이름을 기반으로 Controller의 처리 결과를 보여줄 View를 결정

View

  • Controller의 처리결과를 보여줄 응답화면을 생성

Spring MVC 요청 흐름

Spring MVC 실행 순서

  1. DispatcherServlet이 요청을 수신

    • 단일 Front Controller Servlet
    • 요청을 수신하여 처리를 다른 컴포넌트에 위임
    • 어느 Controller에 요청을 전송할지 결정
  2. Dispatcher Servlet은 Handler Mapping에 어느 Controller를 사용할지 문의

    • URL과 Mapping
  3. DispatcherServlet은 요청을 Controller에 전송하고 Controller는 요청을 처리한 후 결과 리턴

    • Buisness Logic 수행 후 결과 정보(Model)가 생성되어 JSP와 같은 view에서 사용됨
  4. ModelAndView Object에 수행결과가 포함되어 DispatcherServlet에 리턴

  5. ModelAndView는 실제 JSP 정보를 갖고 있지 않으며, ViewResolver가 논리적 이름을 실제 JSP 이름으로 변환

  6. View는 결과정보를 사용해 화면을 표현


Spring MVC 구현

Spring MVC를 이용한 Application 구현 Step

  • web.xml에 DispatcherServlet 등록 및 Spring 설정파일 등록
  • 설정 파일에 HandlerMapping 설정
  • Controller 구현 및 Context 설정 파일(servlet-context.xml)에 등록
  • Controller와 JSP의 연결을 위해 View Resolver 설정
  • JSP 코드 작성

Controller 작성

  • 좋은 디자인은 Controller가 많은 일을 하지 않고, Service에 처리를 위임하는 것

weg.xml - DispatcherServlet 설정

  • <init-param>을 설정하지 않으면 "<Servlet-name>-servlet.xml" file에서 applicationContext의 정보를 load
  • Spring Container는 설정파일의 내용을 읽고 ApplicationContext 객체를 생성
  • <url-pattern>은 DispatcherServley이 처리하는 URL Mapping pattern을 정의
  • Servlet이므로 1개 이상의 DispatcherServlet 설정 가능
  • <load-on-startup>1</load-on-startup> 설정 시 WAS startup시 초기화 작업 진행

  • DispatchrServlet은 여러개 설정 가능
  • 각 DispatcherServlet마다 각각의 ApplicationContext 생성

web.xml - 최상위 Root ContextLoader 설정

  • Context 설정 파일들을 로드하기 위해 web.xml에 파일 리스너 설정(ContextLoaderListner)

  • 리스너 설정이 되면 /WEB-INF/spring/root-context.xml 파일을 읽어서 공통적으로 사용되는 최상위 Context를 생성

  • 그 외의 다른 컨텍스트 파일들을 최상위 어플리케이션 컨텍스트에 로드하기 위해서

Application Context 분리

  • 어플리케이션 레이어에 따라 어플리케이션 컨텍스트 분리

Controller Class 작성(HomeController.java)

Context 설정파일에 Controller 등록 (servlet-context.xml)

Controller와 response page 연결을 위한 ViewResolver 설정 (servlet-context.xml)

JSP (index.jsp)



Controller

@Controller와 @RequestMapping 선언

  • method 단위의 mapping이 가능

  • DefaultAnnotationHandlerMapping과 AnnotationHandlerAdapter를 사용함
    (Spring 3.0부터는 기본 설정이므로 별도의 추가 없이 사용 가능)

  • Controller Class는 Client의 요청을 처리

@Controller 선언

  • Class 타입에 적용
  • Spring 3.0부터는 @Controller 사용을 권장함

Controller Class를 <bean>에 등록

Controller Class 자동 스캔

- context:component-scan 선언
- base-package에 설정된 package 내의 class 중 @Controller annotation이 적용된 클래스는 자동 스캔 대상이 됨

@RequestMapping 선언

  • 요청 URL mapping 정보를 설정
  • 클래스타입과 메소드에 설정 가능

  • Controller method의 HTTP method에 한정
    • 같은 URL 요청에 대하여 HTTP method(GET, POST, ...)에 따라 서로 다른 메소드를 mapping 할 수 있음

  • 아래의 Controller에서 @RequestMapping annotation을 설정하지 않으면? HTTP ERROR 404


Controller method의 parameter type

  • Controller method의 parameter로 다양한 Object를 받을 수 있음

@RequestParam annotation을 이용한 parameter mapping

HTML form과 Command Object(DTO, VO)

  • SpringMVC는 form에 입력한 data를 JavaBean 객체를 이용하여 전송할 수 있음

Command 객체를 List로 받기

View에서 Command 객체에 접근

  • Command 객체는 자동으로 반환되는 Model에 추가됨
  • Controller의 @RequestMapping annotation method에서 전달받은 Command 객체에 접근
  • @ModelAttribute를 사용하여 View에서 사용할 Command 객체의 이름을 변경

@RequestHeader annotation을 이용한 header mapping


@RequestBody parameter type

  • HTTP 요청 Body가 그대로 객체어 전달됨.
  • AnnotationMethodHandlerAdapter에는 HttpMessageConverter 타입의 메시지 변환기가 기본으로 여러개 등록되어 있음.
  • @RequestBody가 붙은 parameter가 있으면 해당 미디어 타입을 확인 후 처리 가능한 변환기(Converter)가 자동으로 객체로 변환시켜줌.
  • 주로 @ResponseBody와 함게 사용됨. → 비동기 처리

Servlet API 사용

  • HttpSession의 생성을 직접 제어해야하는 경우
  • Controller가 Cookie를 생성해야하는 경우
  • Servlet API를 선호하는 경우
    • javax.servlet.ServletRequest / javax.servlet.HttpServletRequest
    • javax.servlet.ServletResponse / javax.servlet.http.HttpServletResponse
    • javax.servlet.httpHttpSession


Controller Class에서 method의 return type 종류



View

View의 역할

Controller에서는 처리 결과를 보여줄 View의 이름이나 객체를 리턴하고, DispatcherServlet은 View 이름이나 View 객체를 이용하여 view를 생성한다.
생성 방법에는 명시적 지정, 자동 지정으로 두가지가 있다.


View 지정

ViewResolver : 논리적 view와 실제 JSP 파일 mapping

  • servelt-context.xml

View 이름 명시적 지정

  • ModelAndView와 String 리턴 타입

View 자동 지정

  • RequestToViewNameTranslator를 이용하여 URL로부터 view 이름을 결정함
  • 자동 지정 유형
    • return type이 Model이나 Map일 경우
    • return type이 void이면서 ServletResponse나 HttpServletResponse 타입의 parameter가 없는 경우

Redirect View

  • View 이름에 "redirect:" 접두어를 붙이면 지정한 페이지로 redirect됨



Model

View에 전달하는 데이터

  • @RequestMapping annotation이 적용된 method의 Map, Model, ModelMap
  • @RequestMapping method가 return하는 ModelAndView
  • @ModleAttribute annotation이 적용된 method가 return한 객체

## Model 생성 ### Map, Model, ModelMap을 통한 설정 - method의 argument로 받는 방식 ![](https://velog.velcdn.com/images/kjenotn/post/3f02831c-ea21-4d87-988f-05c9f1d15bd3/image.png)

Model Interface 주요 method

  • Model addAttribute(String name, Object value);
  • Model addAttribute(Object value);
  • Model addAllAttributes(Collection< ? > values);
  • Model addAllAttributes(Map<String, ?> attributes);
  • Model mergeAttributes(Map<String, ?> attributes);
  • boolean containsAttribute(String name);

ModelAndView를 통한 Model 설정

  • Controller에서 처리결과를 보여줄 view와 view에 전달할 값(model)을 저장하는 용도로 사용
  • setViewName(String viewname);
  • addObject(String name, Object value);

@ModelAttribute annotation을 이용한 model data 처리

  • @RequestMapping annotation이 적용되지 않은 별도 method로 모델이 추가될 객체를 생성

## 요청 URL 매칭 ### 전체 경로와 Servlet 기반 경로 매칭 - DispatcherServlet은 DefaultAnnotationHandlerMapping Class를 기본으로 HandlerMapping 구현체로 사용 - Default로 Context 내의 경로가 아닌 Servlet 경로를 제외한 나머지 경로에 대해 mapping

Servlet 기반 경로 매칭

  • Servlet 경로를 포함한 전체 경로를 이용해서 매칭하려는 경우
  • @RequestMapping("product/list")


@PathVariable annotation을 이용한 URI 템플릿


@RequestMappingAnnotation의 추가 설정 방법

@RequestMapping Annotation을 class와 method에 함께 적용하는 경우

Ant 스타일의 URI 패턴 지원

  • ? : 하나의 문자열과 대치
    • : 하나 이상의 문자열과 대치
  • ** : 하나 이상의 디렉토리와 대치



Spring Web MVC 동작 정리

Spring Web Application 동작 원리

실행 순서

  1. 웹 어플리케이션이 실행되면 Tomcat(WAS)에 의해 web.xml이 loading.
  2. web.xml에 등록되어있는 ContextLoaderListner (Java Class)가 생성됨. ContextLoaderListener class는 ServletContextListner interface를 구현하고 있으며, ApplicationContext를 생성함.
  3. 생성된 ContextLoaderListner은 root-context.xml을 loading.
  4. root-context.xml에 등록되어있는 Spring Container가 구동됨. 이때 개발자가 작성한 Buisness Logic(Service)에 대한 부분과 Database Logic(DAO), VO 객체들이 생성됨.
  5. Client로부터 요청(request)가 들어옴.
  6. DispatcherServlet(Servlet)이 생성됨. DispatcherServlet은 FrontController의 역할을 수행함.
    Client로부터 요청온 메시지를 분석하여 알맞은 PageController에 전달하고 응답을 받아 요청에 따른 응답을 어떻게 할지 결정함. 실질적인 작업은 PageController에서 이루어진다. 이러한 클래스들을 HandlerMapping, ViewResolver Class라 부름.
  7. DispatcherServlet은 servlet-context.xml을 loading.
  8. 두번째 Spring Container가 구동되며 응답에 맞는 PageController들이 동작함. 이때 첫번째 Spring Container가 구동되면서 생성된 DAO, VO, Service 클래스들과 협업하여 알맞은 작업을 처리함.

0개의 댓글