스프링 관련글은 오랜만에 다시 쓰는 것 같네요
오늘은 Spring MVC에 대해서 알아보고, 예제로 한번 구현 해 보도록 하겠습니다.
[Java/Spring-framework] - Spring Framework Documentation
Spring MVC와 관련한 글은 위의 포스팅에서 잠시 얘기 했었습니다. MVC가 무엇인지, 구성이 어떻게 되어있는지에 대한 간단하게 설명했었습니다.
결론적으로, MVC는 비즈니스 처리 로직과 사용자 인터페이스 요소를 분리하여 개발 및 운영에 유연성이 높습니다.
MVC(Model, View, Controller) 의 각 부분에 대해 간단히 설명하면
MVC - Model
어떤 데이터를 보여 줄 지 정의 해 줍니다.
'데이터'를 정의하는 부분으로 조회 뿐 아니라 삽입, 변경, 삭제 등의 작업을 수행하고, 그 과정이 일어나는 비즈니스 로직의 전반적인 부분을 정의 해 줍니다.
MVC - View
데이터를 보여주는 방식을 정의 해 줍니다.
View는 Client 들이 실제로 보는 화면을 표시 해 주는 부분으로, 보여 줄 데이터를 표시하거나 Client의 입력을 받기 위한 입력 폼들을 정의 해 줍니다.
MVC - Controller
Client의 Request에 따른 응답(Response)를 정의 해 주며 모델 및 뷰를 업데이트 하는 로직을 포함 하고 있습니다.
Controller는 Client의 요청을 받아들여 각 요청에 따라 데이터를 설정 해 주거나 화면을 출력 해 주는 등의 전체적인 연결을 관리 해 주는 응답을 정의 해 줍니다.
Front Controller Pattern??
Front Controller Pattern이 갑자기 등장 한 이유는 Spring framework는 Front Controller Pattern 이기 때문입니다.
Front Controller Pattern의 형태는 다음과 같습니다.
- 웹 어플리케이션(Web application)과 관련된 패턴(Pattern)
- 모든 리소스(Resource) 요청을 처리해주는 하나의 컨트롤러(Controller)를 두는 패턴
- MVC(Model-View-Controller) Pattern과 함께 사용하는 패턴
컨트롤러로 리소스 요청을 처리해 주는 패턴이라는 특징은 Front Controller Pattern 의 큰 장점 중 하나라고도 볼 수 있습니다.
그리고 이 컨트롤러라는 것 때문에 플로우를 추적 할 때에도 용이하다는 장점이 있습니다.
Spring framework에 적용 - Front Controller Pattern
Spring framework에 위의 Front Controller를 적용 해 본다면, DispatcherServlet이 Spring framework의 Front Controller가 됩니다.
이 DispatcherServlet은 요청을 처리하기 위한 공유 알고리즘을 제공하지만, 실제 작업은 적절한 컴포넌트들에게 위임하여 수행하게 됩니다.
DispatcherServlet 안에 두 개의 Application Context가 존재하는데요, Servlet-Context와 Root-Context로 나눌 수 있습니다.
Root Context
- ContextLoaderListner에서 생성
- Spring 최상단에 위치한 Context
- 공통적인 기능들을 가진 Bean을 생성하여 다른 Servlet Context에서 참조가 가능합니다. (@Service, Repository, @Configuration, @Component)
Servlet Context
- DispatcherServlet에서 생성
- Servlet 단위로 생성되는 Context
- 서블릿 내에서만 사용하는 Bean 생성 (@Controller, Interceptor)
DispatcherServlet은 설정에 따라 여러개 생성이 가능하며 url pattern을 통해 목적에 맞게 나누어 관리합니다.
예를들어 웹 페이지를 위한 서블릿과 Rest 기반 웹서비스를 따로 관리하기 위한 DispatcherServlet을 생성 할 수 있습니다.
생성한 각각의 DispatcherServlet마다 Servlet Context가 생성됩니다.
Spring MVC에서는 Dispatcher Servlet의 Special Bean들을 통해 Request들을 핸들링 해주어 개발자가 MVC에 필요한 코드만 작성 할수 있도록 지원합니다.
Spring MVC Project 구성 (spring 3.x)
기존 프로젝트의 서블릿 구성을 설명하려고 코드를 가져왔습니다.
<context:component-scan base-package="controller" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- Enables the Spring MVC @Controller programming model -->
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class = "org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes" value = "text/plain;charset=UTF-8" />
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
<property name="contentType" value="text/html; charset=UTF-8"/>
</bean>
<context:component-scan> : component-scan을 통해 특정 패키지 내의 클래스를 스캔하여 어노테이션을 확인해 Bean을 설정해 줍니다. 위 설정에서는 ‘controller’ 패키지 내 stereotype.Controller annotation(@Controller)를 스캔하여 Bean 설정을 해줍니다.
<mvc:annotation-driven> : 스프링 MVC를 위한 Special Bean들을 설정해주는 태그로, Handler mapping에 대한 Bean들을 설정해줍니다. 위 설정에서는 핸들러 어댑터등의 빈을 설정 해주고 ‘message-converter’ 태그 를 통해 @ResponseBody 어노테이션에 대하여 response를 UTF-8 charset으로 JSON 형식 결과값을 보내줄수 있도록 설정해 줍니다.
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">: 해당 클래스는 클래스이름에서 볼수 있듯이 위에서 DispatcherServlet구조에서 알아보았던 Viewresolver 클래스로써, view 파일 설정을 위한 태그입니다. 위 설정에서는 /WEB-INF/jsp/ 폴더내의 .jsp로 끝나는 파일을 String기반 파일 이름으로 서치가 가능하도록 설정해 줍니다.
위의 코드는 Spring의 3.x 버전에서 설정하는 파일을 가져온 것입니다.
Spring 최신버전에서도 설정을 해 보도록 하겠습니다.
Spring MVC Project 구성 (spring boot)
Spring framework의 최신버전인 Spring boot에서 환경설정을 해 보도록 하겠습니다.
우선, Spring Starter 프로젝트를 생성 한 후, 아래 캡쳐화면과 같이 구성을 해 주세요!
저는 이클립스 기반의 STS를 사용했습니다 :)
1. Project 구조
2. Project 소스
Controller
package com.example.demo.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.example.demo.service.ExampleService;
@Controller
public class ExampleController {
@Autowired
private ExampleService exampleService;
@RequestMapping(value="/example", method = RequestMethod.GET)
public String example(Model model) {
model.addAttribute("data",exampleService.getExample());
return "example";
}
}
Service
package com.example.demo.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Service;
@Service
public class ExampleService {
@SuppressWarnings({ "unchecked", "rawtypes" })
public List getExample() {
List result = new ArrayList();
result.add("Example1");
result.add("Example2");
result.add("Example3");
result.add("Example4");
return result;
}
}
Application Properties
#application.properties
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
jsp File
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>woolbro Dev</title>
</head>
<body>
[Example Data List]
<br> ${data }
</body>
</html>
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.test</groupId>
<artifactId>com.woolbro.test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>com.woolbro.test</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3. 실행
실행을 시키면 아래와 같이 콘솔창에 스프링 부트가 실행됩니다.
Spring boot는 부트 내에 개발 톰캣이 함께 있어서 서버를 따로 설정 하지 않아도 되는 편리성이 있습니다.
위의 코드를 보시면 아시겠지만 , 위의 프로젝트 스타트 로그를 확인해보면 스프링부트에서는 기본적으로 default 서블릿을 구성하여 Annotation 설정을 자동으로 해주어 간단한 프로젝트에서는 따로 설정을 하지 않아도 웹 MVC 프로젝트 구현이 가능합니다. 물론, 따로 WebApplicationInitializer 를 구현하여 서블릿 설정을 할 수 있습니다.
'Old Branch' 카테고리의 다른 글
Spring Project 스프링 프로젝트 시작하기 - JDBC ,mysql,mybatis(1) (0) | 2019.07.11 |
---|---|
Spring Project 스프링 프로젝트 시작하기 - Spring MVC 사용하기 (0) | 2019.07.10 |
Python Basic - 파이썬 엑셀(Excel, CSV) 읽기 및 쓰기 (2) (2) | 2019.07.06 |
Python Basic - 파이썬 엑셀(Excel, CSV) 읽기 및 쓰기 (1) (2) | 2019.07.05 |
Python Basic - 파이썬 에러 및 예외 - 예외처리(2) (0) | 2019.07.04 |