작심팔일러의 스프링 시작하기(8)

서은경·2022년 8월 22일
0

Spring

목록 보기
14/43

스프링 MVC 시작하기

책에서는 스프링을 기반으로 톰캣을 다운받아 설정했지만 나는 스프링 부트로 jsp를 설정했다.. 딱히 이유가 있진 않지만 요즘 개발자들은 스프링 부트를 많이 이용하는 추세라 그냥 어떤식으로 스프링 MVC가 동작하는지 정도만 익히면 될 것 같아서 톰캣 설정은 건너뛰었다.

참고로 spring boot 공식 문서에서는 jsp를 추천하지 않고 다른 템플릿을 추천한다..!

JSP 프로젝트를 만들기에 앞서 몇가지 설정해줘야 할 것이 있다.
build.gradle 파일에 톰캣 라이브러리를 추가해주고

plugins {
    id 'org.springframework.boot' version '2.6.4'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'java'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {

    //JSP(Java Server Page)도 템플릿 엔진이기 때문에 사용하기 위해서는 별도의 라이브러리가 필요 (JSP를 지원하는 대표 엔진=apache의 tomcat)
    implementation "org.apache.tomcat.embed:tomcat-embed-jasper"
    // 스프링 부트는 Spring MVC, REST 및 Tomcat을 기본 임베디드 서버로 사용
    implementation 'org.springframework.boot:spring-boot-starter-web'

    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
}

test {
    useJUnitPlatform()
}

스프링 부트 프로젝트 구조가 변경되었기 때문에 스프링 부트에서 사용하는 뷰리졸버의 설정을 변경해준다

application.properties

spring.mvc.view.prefix=/WEB-INF/view/
spring.mvc.view.suffix=.jsp

그럼 시작~!

스프링 MVC를 위한 설정

스프링 MVC를 실행하는데 최소 두가지의 설정이 필요하다.

  1. 스프링 MVC의 주요 설정(HandlerMapping, ViewResolver 등)
package config;

// 스프링 부트 사용하긴 하지만 스프링 MVC 구조를 자세히 보기 위해 전부 만들어봄

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
// 스프링 MVC 설정을 활성화한다. 스프링 MVC를 사용하는데 필요한 다양한 설정을 생성한다.
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {

    // DispatcherServlet의 매핑 경로를 '/'로 주었을 때, JSP/HTML/CSS 등을 올바르게 처리하기 위한 설정을 추가한다.
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    // JSP를 이용해서 컨트롤러의 실행 결과를 보여주기 위한 설정을 추가한다.
    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.jsp("/WEB-INF/view/", ".jsp");
    }
}
  • @EnableWebMvc : 이 어노테이션은 스프링 MVC 설정을 활성화한다. 스프링 MVC를 사용하는데 필요한 다양한 설정을 생성한다.
  • public void configureDefaultServletHandling : DispatcherServlet의 매핑 경로를 '/' 로 주었을 때, JSP/HTML/CSS 등을 올바르게 처리하기 위한 설정을 추가한다.
  • public void configureViewResolver : JSP를 이용해서 컨트롤러의 실행 결과를 보여주기 위한 설정을 추가한다.
  1. 스프링의 DispatcherServlet 설정
<?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>

DispatcherServlet이란 HTTP 프로토콜로 들어오는 모든 요청을 가장 먼저 받아 적합한 컨트롤러에 위임해주는 front-controller 이다.

각 행에 대해 설명해보면

DispatcherServlet을 dispatcher라는 이름으로 등록한다.

	<servlet-name>dispatcher</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>

contextClass 초기화 파라미터는 설정한다. 자바를 사용하는 경우 AnnotationConfigWebApplicationContext 클래스를 사용한다. 이 클래스는 자바 설정을 이용하는 웹 어플리케이션 용 스프링 컨테이너 클래스이다.

	<init-param>
            <param-name>contextClass</param-name>
            <param-value>
                org.springframework.web.context.support.AnnotationConfigWebApplicationContext
            </param-value>
        </init-param>

contextConfiguration 초기화 파라미터의 값을 지정한다. 이 파라미터에는 스프링 설정 클래스 목록을 지정한다. 각 설정 파일의 경로는 줄바꿈이나 콤마로 구분한다.

	<init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                config.MvcConfig
                config.ControllerConfig
            </param-value>
        </init-param>

톰캣과 같은 컨테이너가 웹 어플리케이션을 구동할 때 이 서블릿을 함께 실행하도록 설정한다.

<load-on-startup>1</load-on-startup>

모든 요청을 DispatcherServlet이 처리하도록 서블릿 매핑을 설정한다.

	<servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

HTTP 요청 파라미터의 인코딩 처리를 위한 서블릿 필터를 등록한다. 스프링은 인코딩 처리를 위한 필터인 CharacterEncodingFilter 클래스를 제공한다. encoding 초기화 파라미터를 설정해서 HTTP 요청 파라미터를 읽어올 때 사용할 인코딩을 지정한다.

	<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.xml 파일 설정까지 완료했다!
DispatcherServlet은 초기화 과정에서 contextConfiguration 초기화 파라미터에 지정한 설정파일을 이용해서 스프링 컨테이너를 초기화한다. 즉 MvcConfig, ControllerConfig 클래스를 이용해 스프링 컨테이너를 생성한다.

코드 구현

필요한 설정은 끝났고 실제로 구현할 코드는 다음과 같다.
1. 클라이언트의 요청을 알맞게 처리할 컨트롤러

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 어노테이션을 적용한 클래스는 스프링 MVC에서 컨트롤러로 사용한다.
@Controller
public class HelloController {

    // @GetMapping 어노테이션은 메서드가 처리할 요청 경로를 지정한다.
    @GetMapping("/hello")
    // Model 파라미터는 컨트롤러의 처리 결과를 뷰에 전달할 때 사용한다.
    // @RequestParam 어노테이션은 HTTP 요청 파라미터의 값을 메서드의 파라미터로 전달할 때 사용된다.
    public String hello(Model model, @RequestParam(value="name", required = false) String name) {
        model.addAttribute("greeting", "안녕하세요" + name);
        return "hello";
    }
}

스프링 MVC 프레임워크에서 컨트롤러란 간단히 설명하면 웹 요청을 처리하고 그 결과를 뷰에 전달하는 스프링 빈 객체이다.

  • @GetMapping 어노테이션 값은 서블릿 컨텍스트 경로(또는 웹 어플리케이션 경로)를 기준으로 한다.
  • @RequestParam 어노테이션은 HTTP 요청 파라미터를 메서드의 파라미터로 전달받을 수 있게 해준다. value 속성은 HTTP 요청 파라미터의 이름을 지정하고 required 속성은 필수 여부를 지정한다.
  • @GetMapping이 붙은 메서드는 컨트롤러의 실행결과를 보여줄 뷰 이름을 리턴하는데, 이 뷰 이름은 논리적인 이름이며 실제로 뷰 이름에 해당하는 뷰 구현을 찾아주는 것은 ViewResolver이다.

🙋‍♀️@RequestParam 사용이유가 뭔가요? 안쓰면 안되나요?
💡 @RequestParam은 jsp에서 보낸 request값을 효율적으로 받기 위해 사용한다.
http://localhost:8080/practice6/hello?name=test
이 경우 @GetMapping의 hello, @RequestParam의 name과 매칭하게 된다. @RequestParam을 쓰지 않아도 쿼리 스트링으로 받은 값을 사용할 수 있으나 시스템에 따라 자바 컴파일러 최적화 옵션을 적용하게 되면 컴파일 시점에 변수명이 사라져 받을 수 없게된다. 이런 문제 때문에 명시적으로 작성해주는게 좋음.

  1. 처리 결과를 보여줄 JSP
<%@ page contentType="text/html; charset=utf-8" %>
<!DOCTYPE html>
<html>
    <head>
        <title>Hello</title>
    </head>
    <body>
        인사말: ${greeting}
    </body>
</html>

컨트롤러의 hello() 메서드가 리턴한 뷰 이름과 jsp 파일의 이름이 같음을 알 수 있다. 이 파일간의 연결은 MvcConfig 클래스의 다음 설정을 통해 이루어진다.

  @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.jsp("/WEB-INF/view/", ".jsp");
    }

registry.jsp() 코드는 jsp를 뷰 구현으로 사용할 수 있도록 해주는 설정이다. jsp() 메서드의 첫번째 인자는 jsp 파일 경로를 찾을 때 사용할 접두어이며 두번째 인자는 접미사이다.

🗣 나의 여담이지만 .. 스프링 부트로 프로젝트 실습을 했을 때보다 확실히 손이 많이 가는구나 느꼈다. 그래도 스프링 MVC 동작 원리에 대해 하나하나 짚어가면서 해보니 훨씬 깊게 알 수 있어서 좋았다 !!!

0개의 댓글