MVC 디자인패턴
Spring MVC


。스프링 어플리케이션을 Model, View, Controller로 구분하여 각 역할에 맞게 코드를 작성하는 방식
▶ MVC 디자인 패턴을 스프링 어플리케이션으로 구현
▶ MVC 디자인 패턴 중 Model2 Architecture + Front Controller 패턴을 기반
。View : JSP or Thymeleaf
。Model : Service , Repository 클래스
。Controller : @Controller
。 현재는 View와 Model의 경우 잘 사용하지않음
▶ View는 프론트엔드 , Model의 비즈니스 로직은 Service , Repository 역할의 클래스에서 수행
Spring MVC 특징
Dispatcher Sevlet, 메타어노테이션을 통한 요청, 응답과정 단순화
。Spring MVC의 Dispatcher Sevlet을 통해 받은 모든 요청을 @Controller를 선언한 Controller Class의 @GetMapping 등의 어노테이션으로 라우팅하여 손쉽게 Http Request와 Http Response를 수행하므로 HttpServlet를 사용하지 않는다.
▶ Spring이 HttpServlet을 추상화한 계층을 제공
- 과거
Spring은 Spring MVC를 통해 ModelMap과 JSP를 통해 프론트엔드 영역까지 담당
。현재는 백엔드와 분리되어 View, Model을 사용하지는 않음.
▶ View는 CSR 방식을 통한 프론트엔드 ( = React , ... )으로 대체
▶ Model의 비즈니스 로직은 Service , Repository 역할의 클래스에서 작성
。Spring은 주로 API를 구축하여 클라이언트( = 프론트엔드 어플리케이션 ) 에 대해 데이터 요청을 할 경우 DB에서 꺼내서 JSON으로 서빙하는 역할을 수행
Spring MVC 구성요소

Dispatcher Servlet ( = Front Controller ) :
。Application의 가장 앞단에서 Client로부터의 요청을 수신하여 중계하는 Controller
▶ 요청부터 응답까지의 전반적인 처리과정을 관리
▶ Model2 구조의 Front Controller
。서블릿의 특징을 지니므로, WAS로부터 HttpServletRequest / HttpServletReponse를 전달받아서 HTTP 요청 / 응답을 수행
。url pattern["/*"]을 Mapping 하므로, Client가 WAS에 요청을 전송하는 url에 관계없이 모든 HTTP Request가 가장 먼저 수신
。@RequestMapping, @GetMapping , ... ( HandlerMapping & HandlerAdapter )를 통해 수신한 요청의 URL에 적합한 Controller를 식별 및 요청을 전달
▶ Client로부터의 모든 요청을 수신 후 요청의 처리를 적합한 개별 Controller로 라우팅

。Spring Boot에 의해 Auto-Configuration이 수행 시 Dispatcher Servlet이 자동으로 Spring Bean으로 등록
▶ Dispatcher Servlet도 Spring Bean
HandlerMapping
。Dispatcher Servlet에서 수신한 요청의 URL을 기반으로 어떤 Controller가 처리할지 결정
▶ @RequestMapping에 포함되어 Dispatcher Servlet에 의해 식별
HandlerAdapter
。HandlerMapping을 통해 요청을 처리할 Controller를 식별 시 요청을 전달
▶ @RequestMapping에 포함
Controller( = Handler )
。Dispatcher Servlet에서 HandlerAdapter를 통해 전달된 클라이언트의 실질적인 요청을 처리하는 @RequestMapping, @GetMapping, ... 이 선언된 method
▶ @Controller 클래스 내 포함
。Method 내 정의된 로직으로 요청을 처리 후 반환
▶ 레이어드 아키텍처를 통한 Controller -> Service -> Repository 순서로 단방향 의존하여 Business logic을 처리
Controller , Service , Repository
。 처리결과를 다시 DispatcherServlet으로 반환
▶ View Resolver를 사용하지않는 REST API의 경우 @ResponseBody를 선언하여 문자열 또는 JSON 형태로 반환
▶ Model과 View를 사용하는 경우 Controller에서 반환된 문자열을 기반으로 View Resolver를 통해 조회된 템플릿으로 동적으로 생성된 HTML 페이지를 반환
Spring MVC 원리

。 보라색 : 개발자가 작성하는 logic
。 파란색 : 스프링이 처리하는 logic
▶ 개발자는 Controller , Service , Repository 역할의 Class를 집중해서 개발
1. 클라이언트가 WAS의 URL에 HTTP Request를 전송
2. Dispatcher Servlet에서 Client로 부터의 Http Request를 수신
3. Dispatcher Servlet에서 HttpRequest의 URL을 기반으로 HandlerMapping을 통해 적절한 Controller를 식별
。 localhost:8080/login 일 경우, @RequestMapping("Login")이 선언된 Controller Method를 식별.
4. HandlerAdapter를 통해 해당 Controller로 요청을 전달
5. Controller에서 요청에 대한 작업을 처리
。레이어드 아키텍처에 따라 Controller -> Service -> Repository로 고수준 클래스에서 저수준 클래스로 단방향 의존하면서 요청 DB의 데이터를 요청 및 Business Logic을 처리
▶ Repository가 Service를 의존할 수 없다.
Controller, Service, Repository
View Resolver를 활용하여 Model과 View를 통해 브라우저에서 렌더링할 HTML 페이지를 생성하여 클라이언트에게 반환하는 경우
1. 해당 Controller에서 ModelMap을 생성 및 View의 이름을 return
。Controller Method의 매개변수에 ModelMap model을 생성하여 model.put("name",name);을 통해 ModelMap에 name라는 변수를 생성하여 전달값을 넣고, "Login" 문자열을 return.
2. return된 문자열을 기반으로 Rendering 할 적절한 Template 파일을 ViewResolver로 식별 후 템플릿 엔진을 통해 동적으로 렌더링할 View를 생성
。application.yml에서 prefix, suffix를 설정하고, src/main/resources/META-INF/templates에서 해당 Login으로 시작하는 jsp파일을 식별 후 템플릿 엔진에 전달
3. 생성된 View를 Controller -> Dispatcher Servlet을 거쳐 Http Response를 통해 클라이언트의 브라우저로 응답하여 렌더링
。HTML 페이지를 생성한 후 HttpServletResponse에 포함 후 Dispatcher Servlet -> 브라우저로 응답
REST API로서 데이터만 클라이언트에게 반환하는 경우
。객체의 경우 DTO로서 일반 POJO를 사용
Controller에 @ResponseBody 선언 및 반환할 데이터를 설정
。@ResponseBody을 선언하는 경우 View Resolver가 작동하지 않게됨.
▶ 클라이언트에게 반환값으로 온전한 문자열을 반환
▶ 객체를 반환하는 경우 Jackson 라이브러리를 통해 JSON으로 변환되어 반환
。또는 @RestController를 선언하는 경우 @ResponseBody이 자동으로 적용
Controller에서 반환된 데이터를 Controller -> Dispatcher Servlet를 거쳐서 클라이언트에게 반환