Spring MVC 시작
스프링을 사용하는 여러 이유가 있지만 한 가지 이유를 꼽자면 스프링이 지원하는 웹 MVC 프레임워크 때문이다.
1. 스프링 MVC를 위한 설정
이 페이지에서 만들 예제가 매우 간단하지만 스프링 MVC를 실행하는데 필요한 최소 설정은 해야 한다. 그 설정은 다음과 같다.
- 스프링 MVC의 주요 설정(HandlerMapping, ViewResolver 등)
- 스프링의 DispatcherServlet 설정
1.1 스프링 MVC 설정
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer{
@Override
public void configureDefaultServletHandling(
DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp("/WEB-INF/view/", ".jsp");
}
}
스프링 MVC를 사용하려면 다양한 구성 요소를 설정해야 한다. 이 요소를 처음부터 끝까지 직접 구성하면 설정이 매우 복잡해진다. 실제로 스프링 2.5나 3 버전에서 스프링 MVC를 사용하려면 상황에 맞는 설정을 일일이 구성해야 했다. 이런 복잡한 설정을 대신 해 주는 것이 바로 @EnableWebMvc 애노테이션이다.
@EnableWebMvc 애노테이션을 사용하면 내부적으로 다양한 빈 설정을 추가해준다. 스프링 MVC를 사용하는데 필요한 기본적인 구성을 설정해준다면,
WebMvcConfigurer 인터페이스는 스프링 MVC의 개별 설정을 조정할 때 사용한다. configureDefaultServletHandling() 메서드와 configureViewResolvers() 메서드는 WebMvcConfigurer 인터페이스에 정의된 메서드로 각각 디폴트 서블릿과 ViewResolver와 관련된 설정을 조정한다.
이 설정 코드에서 중요한 점은 위 설정이면 스프링 MVC를 이용해서 웹 어플리케이션 개발하는데 필요한 최소 설정이 끝난다는 것이다.
1.2 web.xml 파일에 DispatcherServlet 설정
스프링 MVC가 웹 요청을 처리하려면 DispatcherServlet을 통해서 웹 요청을 받아야 한다. 이를 위해 web.xml 파일에 DispatcherServlet을 등록한다.
src/main/wbapp/WEB-INF 폴더에 web.xml 파일을 작성한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
config.MvcConfig
config.ControllerConfig
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>
org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
09~28행 DispatcherServlet을 등록하는데, 각 행은 다음의 의미를 갖는다.
- 10~13행 : DispatcherServlet을 dispatcher라는 이름으로 등록한다.
- 14~19행 : contextClass 초기화 파라미터를 설정한다. 자바 설정을 사용하는 경우 AnnotationConfigWebApplicationContext 클래스를 사용한다. 이 클래스는 자바 설정을 이용하는 웹 어플리케이션 용 스프링 컨테이너 클래스이다.
- 20~26행 : contextConfiguration 초기화 파라미터의 값을 지정한다. 이 파라미터에는 스프링 설정 클래스 목록을 지정한다. 이 파라미터에는 스프링 설정 클래스 목록을 지정한다. 각 설정 파일의 경로는 줄바꿈이나 콤마로 구분한다.
- 27행 : 톰캣과 같은 컨테이너가 웹 어플리케이션을 구동할 때 이 서블릿을 함께 실행하도록 설정한다.
- 30~33행 : 모든 요청을 DispatcherServlet이 처리하도록 서블릿 매핑을 설정한다.
- 35~48행 : HTTP 요청 파라미터의 인코딩 처리를 위한 서블릿 필터를 등록한다. 스프링은 인코딩 처리를 위한 필터인 ChracterEncodingFilter 클래스를 제공한다.
DispatcherServlet은 초기화 과정에서 contextConfiguration 초기화 파라미터에 지정한 설정 파일을 이용해서 스프링 컨테이너를 초기화한다.
2. 코드 구현
이 페이지에서 작성할 코드는 다음과 같다.
- 클라이언트의 요청에 알맞게 처리할 컨트롤러
- 처리 결과를 보여줄 JSP
2.1 컨트롤러 구현
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package chap09;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class HelloController {
@GetMapping("/hello")
public String hello(Model model,
@RequestParam(value = "name", required = false) String name) {
model.addAttribute("greeting", "안녕하세요, " + name);
return "hello";
}
}
- 8행 : @Controller 애노테이션을 적용한 클래스는 스프링 MVC에서 컨트롤러로 사용한다.
- 10행 : @GetMapping 애노테이션은 메서드가 처리할 요청 경로를 지정한다. 위 코드의 경우 “/hello” 경로로 들어온 요청을 hello() 메서드를 이용해서 처리한다고 설정했다. 이름에서 알 수 있듯이 HTTP 요청 메서드 중 GET 메서드에 대한 매핑을 설정한다.
- 11행 : Model 파라미터는 컨트롤러의 처리 결과를 뷰에 전달할 때 사용한다.
- 12행 : @RequestParam 애노테이션은 HTTP 요청 파라미터의 값을 메서드의 파라미터로 전달할 때 사용된다. 위 코드의 경우 name 요청 파라미터의 값을 name 파라미터에 전달한다.
- 13행 : “greeting”이라는 모델 속성에 값을 설정한다. 값으로는 “안녕하세요, “와 name 파라미터의 ㄱ밧을 연결한 문자열을 사용한다. 뒤에서 작성할 JSP코드는 이 속성을 이용해서 값을 출력한다.
- 14행 : 컨트롤러의 처리 결과를 보여줄 뷰의 이름으로 “hello”를 사용한다.
스프링 MVC 프레임워크에서 컨트롤러(Controller)란 @Controller 애노테이션을 붙여야 하고, 웹 요청을 처리하고 그 결과를 뷰에 전달하는 스프링 빈 객체이다. @GetMapping 애노테이션이나 @PostMapping 애노테이션과 같은 요청 매핑 애노테이션을 이용해서 처리할 경로를 지정해 주어야 한다.
-
@GetMapping
@GetMapping 애노테이션의 값은 서블릿 컨택스트 경로(또는 웹 어플리케이션 경로)를 기준으로 한다. 예를 들어 톰캣의 경우 webapps\sp5-chap09 폴더는 웹 브라우저에서 http://host/sp5-chap09 경로에 해당하는데 , 이때 sp-chap09가 컨텍스트 경로가 된다.http://host/sp5-chap09/main/list 경로를 처리하기 위한 컨트롤러는 @GetMapping(“/main/list”)를 사용해야 한다. 따라서 위의 코드에서 처리되는 URL은 http://host/sp5-chap09/hello가 된다. -
@RequestParam
@RequestParam 애노테이션은 HTTP 요청 파라미터를 메서드의 파라미터로 전달받을 수 있게 해 준다. @RequestParam 애노테이션의 value 속성은 HTTP 요청 파라미터의 이름을 지정하고 required 속성은 필수 여부를 지정한다. -
Model.addAttribute()
addAttribute() 메서드는 뷰에 전달할 데이터를 지정하기 위해 사용된다. 이 메서드의 첫 번째 파라미터는 데이터를 식별하는데 사용되는 속성 이름이고 두 번째 파라미터는 속성 이름에 해당하는 값이다. 뷰 코드는 이 속성 이름을 사용해서 컨트롤러가 전달한 데이터에 접근하게 된다. -
@GetMapping이 붙은 메서드의 리턴 값
@GetMapping이 붙은 메서드는 컨트롤러의 실행 결과를 보여줄 뷰 이름을 리턴한다. 위 코드에서는 “hello”를 뷰 이름으로 리턴했다. 이 뷰 이름은 논리적인 이름이며 실제로 뷰 이름에 해당하는 뷰 구현을 찾아주는 것은 ViewResolver가 처리한다.
2.2 JSP 구현
뷰 코드는 JSP를 이용해서 구현한다. src/main/webapp/WEB-INF/view 폴더에 hello.jsp파일을 생성하자.
1
2
3
4
5
6
7
8
9
10
<%@ page contentType="text/html; charset=utf-8" %>
<!DOCTYPE html>
<html>
<head>
<title>Hello</title>
</head>
<body>
인사말: ${greeting}
</body>
</html>
HelloController의 hello() 메서드가 리턴한 뷰 이름은 “hello”였는데 JSP파일의 이름을 보면 “hello.jsp”이다. 여기서 뭔가 관계가 있을 거라 유추해 볼 수 있는데 뷰 이름과 JSP파일과의 연결은 MvcConfig 클래스의 다음 설정을 통해서 이루어진다.
1
2
3
4
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp("/WEB-INF/view/", ".jsp");
}
registry.jsp() 코드는 JSP를 뷰 구현으로 사용할 수 있도록 해주는 설정이다. jsp() 메서드의 첫 번째 인자는 JSP 파일 경로를 찾을 때 사용할 접두어이며 두 번째 인자는 접미사이다. 뷰 이름의 앞과 뒤에 각각 접두어와 접미사를 붙여서 최종적으로 사용할 JSP 파일의 경로를 결정한다.
hello.jsp를 보면 다음과 같은 JSP EL(Expression Language)을 사용했다.
1
인사말 : ${greeting}
이 표현식의 “greeting”은 컨트롤러 구현에서 Model에 추가한 속성의 이름인 “greeting”과 동일하다. 이렇게 컨트롤러에서 설정한 속성을 뷰 JSP 코드에서 접근할 수 있는 이유는 스프링 MVC 프레임워크가 모델에 추가한 속성을 JSP 코드에서 접근할 수 있게 HttpServletRequest에 옮겨주기 때문인다.
따라서 JSP로 뷰 코드를 구현한 경우 컨트롤러에서 추가한 속성의 이름을 이용해서 속성값을 응답 결과에 출력하게 된다.
Ref.
- 최범균, 스프링프로그래밍입문5, 가메출판사.