- MVC 패턴
MVC 패턴은 다양한 웹 프레인워크에 적용된 디자인 패턴이다. 클라이언트로부터 요청을 받고, 요청에 맞는 처리를 하고, 응답을 만드는 과정을 분리하여 유연하고 효율적으로 코드를 작성할 수 있도록 한다. 이때 요청에 따른 처리를 하는 부분을 Model, 응답을 만드는 부분을 View, 요청을 받는부분을 Controller라고 하고, 각 앞글자를 따서 MVC 패턴이라고 부른다.
Model(모델) | 어플리케이션의 데이터나 로직을 처리하는 역할 |
View(뷰) | 클라이언트에 반환할 응답을 생성하는 역할 |
Controller(컨트롤러) | 클라이언트의 요청에 따라 모델과 뷰의 호출을 제어하는 역할 |
Spring MVC는 MVC 패턴을 채택한 프레임 워크로, 스프링 웹 어플리케이션 개발에 필수적으로 사용된다.
- 실습: 프로젝트 생성
먼저, 메이븐 프로젝트를 생성하고 pom.xml에 다음과 같이 dependencis를 추가한다.
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.27.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.27.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
</dependencies>
pom.xml에 빌드에 필요한 plugins도 추가한다.
<build>
<plugins>
<!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-compiler-plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-war-plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
그리고 Tomcat으로 Spring 웹 프로젝트를 시작할 때 필요한, WebApplicationInitializer 구현 클래스를 만들어 준다. 톰캣은 웹 프로젝트를 시작할 때, WebApplicationInitializer 구현 클래스를 찾아서 기본 설정을 하게 만든다. 여기서 앱의 context, dispatcherServlet, filter를 등록한다.
public class Init implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
System.out.println("onStartup...");
addListender(servletContext);
addDispatcher(servletContext);
addFilter(servletContext);
}
public void addListender(ServletContext servletContext) {
System.out.println("addListender...");
AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
appContext.register(AppConfig.class);
ContextLoaderListener listender = new ContextLoaderListener(appContext);
servletContext.addListener(listender);
}
public void addDispatcher(ServletContext servletContext) {
System.out.println("addDispatcher...");
AnnotationConfigWebApplicationContext webContext = new AnnotationConfigWebApplicationContext();
webContext.register(WebConfig.class);
DispatcherServlet dispatcherServlet = new DispatcherServlet(webContext);
ServletRegistration.Dynamic webServlet = servletContext.addServlet("webServlet", dispatcherServlet);
webServlet.addMapping("/");
webServlet.setLoadOnStartup(1);
}
public void addFilter(ServletContext servletContext) {
System.out.println("addFilter...");
CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter("UTF-8", true, true);
FilterRegistration.Dynamic webEncodingFilter = servletContext.addFilter("webEncodingFilter", encodingFilter);
webEncodingFilter.addMappingForUrlPatterns(null, false, "/*");
}
}
//AppConfig.java 파일
@Configuration
public class AppConfig {
}
//WebConfig.java 파일
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter{
}
그리고 톰캣으로 run on server를 하였을 때, 다음과같이 WebApplicationInitializer를 발견하고 구동하면 준비는 끝난다.
- 실습: 페이지 띄우기
이제 클라이언트로 부터 요청이 들어왔을때, 특정 페이지를 띄워보겠다. 먼저 요청을 처리할 컨트롤러와 관련 설정을 해야한다.
@Controller
@RequestMapping("/main")
public class HomeController {
@GetMapping("/home")
public String home() {
return "home";
}
}
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.study.spring.controller")
public class WebConfig extends WebMvcConfigurerAdapter{
@Bean
public InternalResourceViewResolver internalResourceViewResolver() {
return new InternalResourceViewResolver("/view/", ".jsp");
}
}
"/main/home"로 요청이 오면 "home"이란 view를 사용하도록 하는 컨트롤러를 만들었다. 그리고 WebConfig에서 ConponentScan으로 해당 컨트롤러를 등록하도록 하고, 컨트롤러가 "home"이란 view를 사용하라는 응답을 했을 때, "/view/home.jsp"를 응답하도록 하는 viewResolver를 빈으로 등록하였다.
그리고 다음과 같이 home.jsp를 만들고, 서버를 동작시키고 "/main/home"로 접속하면 home.jsp 파일이 응답으로 온 것을 확인할 수 있다.
- 실습: 데이터 주고 받기
이제 클라이언트로부터 데이터를 받아서, 처리하고 그 결과를 반환해보자. home.jsp에서 두개의 숫자를 보내면, 두 숫자을 합을 sum.jsp에서 보여주는 구조로 하겠다.
<html>
<head>
<meta charset="UTF-8">
<title>Home</title>
</head>
<body>
<h1>Home</h1>
<form action="./sum" method="get">
<input type="number" name="num1"/>
<input type="number" name="num2"/>
<input type="submit" value="submit"/>
</form>
</body>
</html>
home.jsp에서 ./sum으로(현재 url이 /main/home 이므로 결국 /main/sum) num1, num2 두개의 숫자를 보낸다.
@Controller
@RequestMapping("/main")
public class HomeController {
...
@GetMapping("/sum")
public String sum(@RequestParam(name = "num1") Integer num1,
@RequestParam(name = "num2") Integer num2,
Model model) {
model.addAttribute("result", num1 + num2);
return "sum";
}
}
HomeController의 sum메소드에서 해당 데이터를 받아서, 두 숫자의 합을 model에 넣어주고 "sum" 뷰를 호출하도록 한다. 여기서 model은 뷰에서 사용할 데이터를 보관하는 객체이다.
<html>
<head>
<meta charset="UTF-8">
<title>Home</title>
</head>
<body>
<h1>SUM</h1>
${ result }
</body>
</html>
그리고 다음과 같이 sum.jsp 파일을 만들면 끝이다. model에 들어간 result데이터는 ${result}와 같이 사용할 수 있다.