본문 바로가기

Java/Spring

Spring 5 입문: Chapter 09. 스프링 MVC 시작하기

더보기

이 프로젝트의 개발 환경

  • 개발 언어 및 개발 환경
    • OpenJDK 12
    • Spring: spring-webmvc 5.0.2.RELEASE
    • Tomcat: tomcat-jdbc: 8.5.27
    • Gradle 7.3
  • 기타 환경
    • macOS Sonoma 14.1.1
    • IntelliJ IDEA 2020.3 Ultimate Edition
더보기

스프링 MVC는 WAS 개발을 위한 스프링의 핵심 프레임워크입니다.

예제에 앞서 이 블로그의 문서: Chapter 08B. JdbcTemplate을 사용한 업데이트 SQL, 트랜잭션을 선행합니다.

예제 프로젝트 작성

sp5-chap09 프로젝트를 생성하고 chap09 패키지를 추가합니다. 그리고 src/main 디렉토리에서 다음 하위 디렉토리를 포함시킵니다.

  • src/main/java
  • src/main/webapp
  • src/main/webapp/WEB-INF
  • src/main/webapp/WEB-INF/view

프로젝트 루트 디렉토리 기준으로 전체 구조는 다음과 같습니다.

$ tree  
.
├── build.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── src
    └── main
        ├── java
        │   └── chap09
        └── webapp
            └── WEB-INF
                └── view

9 directories, 5 files
더보기

이번 프로젝트에서는 webapp 그리고 webapp/WEB-INF 디렉토리가 추가되었습니다.

webapp은 기존 프로젝트의 resources에 해당하며 HTML CSS JS JSP 등 WAS를 구현하는데 필요한 파일이 위치합니다.

그리고 WEB-INF에서는 web.xml 파일이 위치하게 됩니다.

서블릿 스펙에 따르면 WEB-INF 디렉토리의 하위 디렉토리 libclassess가 필요합니다. 각 디렉토리에서는 jar 파일과 컴파일 된 클래스 파일이 위치하게 됩니다.

하지만 maven 또는 gradle 프로젝트의 경우 별도의 의존성을 통해 컴파일 결과가 target 또는 build 디렉토리에 위치하게 됩니다.

따라서 WEB-INF 디렉토리 하위에 lib과 classess를 생성할 필요가 없습니다.

build.gradle 파일에서 다음 의존성을 작성합니다.

apply plugin: 'java'
apply plugin: 'war'

sourceCompatibility = '12'
targetCompatibility = '12'
compileJava.options.encoding = "UTF-8"

repositories {
    mavenCentral()
}

dependencies {
    providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
    providedRuntime 'javax.servlet:jsp:javax.servlet.jsp-api:2.3.2-b02'
    implementation group: 'jstl', name: 'jstl', version: '1.2'
    implementation group: 'org.springframework', name: 'spring-webmvc', version: '5.0.2.RELEASE'
}

wrapper {
    gradleVersion = '7.3'
}
코드 비고
Line 2 apply plugin: 'war' 서블릿/JSP 기반의 웹 애플리케이션 개발을 위한 플러그인을 적용합니다.

gradle wrapper를 실행해 gradle 프로젝트를 준비합니다.

$ gradle wrapper
Starting a Gradle Daemon (subsequent builds will be faster)

BUILD SUCCESSFUL in 4s
1 actionable task: 1 executed

스프링 MVC를 위한 설정

스프링 MVC를 실행하기 위한 최소한의 설정을 지정합니다.

  • HandlerMapping
  • ViewResolver 등

chap09.config 패키지를 생성하고 MvcConfig 클래스를 작성합니다.

package chap09.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");
	}
}
코드 비고
Line 10 @EnableWebMvc 설정 클래스에서 스프링 MVC 설정을 활성화합니다.
Line 13:17 configureDefaultServletHandling(...) { } DispatcherServlet의 매핑 경로를 /로 주었을 때 JSP HTML CSS 등을 올바르게 처리하기 위한 설정입니다.
Line 19:22 configureViewResolvers(...) { } JSP를 이용해서 컨트롤러의 실행 결과를 보여주기 위한 설정을 추가합니다.
더보기

스프링 MVC를 사용하기 위한 구성을 처음부터 끝까지 직접 처리하려면 상당히 복잡한 일을 해야합니다(스프링 2.5 또는 3 버전에선는 이러한 구성을 일일이 처리해야 했습니다).

복잡한 설정을 직접하는 대신 @EnableWebMvc 어노테이션을 사용하면 스프링에서 자동으로 MVC 구성을 진행합니다.

더보기

WebMvcConfigurer 인터페이스는 스프링 MVC의 개별 설정을 조정하기 위해 사용합니다.

configureDefaultServletHandling()configureViewResolvers() 메소드에서는 각각 디폴트 서블릿과 ViewResolver와 관련된 설정을 조정하고 있습니다.

web.xml에서 DispatcherServlet 설정

스프링 MVC가 웹 요청을 처리하려면 DispatcherServlet을 통해서 웹 요청을 수신해야 합니다.

WEB-INF/web.xml 파일을 생성하고 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>
                chap09.config.MvcConfig
                chap09.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>
코드 비고
Line 10:13 <servlet-name>dispatcher DispatcherServletdispatcher 이름으로 등록합니다.
<servlet-class>...DispatcherServlet
Line 14:17 <param-name>contextClass contextClass 초기화 파라미터를 설정합니다.
자바 설정을 사용하는 경우 AnnotationConfigWebApplicationContext를 지정합니다.
이 클래스는 자바 설정을 이용하는 웹 애플리케이션 전용 스프링 컨테이너 클래스입니다.
<param-value>...AnnotationConfigWebApplicationContext
Line 18:24 <param-name>contextConfigLocation contextConfiguration 초기화 파라미터를 설정합니다.
이 파라미터에서는 스프링 설정 클래스 목록을 지정합니다.
각 설정 파일의 경로는 줄바꿈 또는 콤마(,)로 구분합니다.
<param-value>chap09.config.MvcConfig
<param-value>chap09.config.ControllerConfig
Line 25 <load-on-startup>1 톰캣과 같은 컨테이너가 웹 애플리케이션을 구동할 때 이 서블릿을 함께 실행하도록 합니다.
Line 28:31 <servlet-name>dispatcher 모든 요청을 DispatcherServlet이 처리하도록 서블릿 매핑을 설정합니다.
<url-pattern>/
Line 33:44 <filter-class>...CharacterEncodingFilter HTTP 요청 파라미터의 인코딩 처리를 위한 서블릿 필터를 등록합니다.
스프링은 인코딩 처리를 위한 필터인 CharacterEncodingFilter 클래스를 제공합니다.

DispatcherServlet은 초기화 과정에서 contextConfiguration 초기화 파라미터가 지정하는 설정 파일을 이용해서 스프링 컨테이너를 초기화합니다.

  • chap09.config.MvcConfig
  • chap09.config.ControllerConfig

예시에서는 MvcConfigControllerConfig 클래스를 이용해 스프링 컨테이너를 생성합니다(ControllerConfig 클래스는 이어서 작성합니다).

컨트롤러(Controller) 구현

컨트롤러는 클라이언트의 요청을 처리하는 클래스입니다.

chap09 패키지에서 HelloController 클래스를 작성합니다.

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";
	}
}
코드 비고
Line 8 @Controller 스프링 MVC의 컨트롤러로 사용합니다.
Line 11 @GetMapping("/hello") 메서드가 처리할 요청 경로를 지정합니다.
예시에서는 /hello 경로의 요청을 hello() 메소드로 처리하도록 매핑합니다.
Line 12:17 Model Model 파라미터는 컨트롤러의 처리 결과를 뷰에 전달하기 위한 용도입니다.
@RequestParam HTTP 요청 파라미터를 메소드의 파라미터로 매핑한 객체입니다.
model.addAttribute() Model에 greeting이라는 속성과 값을 추가합니다.
return "hello" 컨트롤러의 처리 결과로 보여줄 뷰 이름으로 hello를 사용합니다.
더보기

스프링 MVC 프레임워크의 컨트롤러(Controller)란 웹 요청을 처리하고 결과를 뷰에 전달하는 스프링 빈 객체입니다.

컨트롤러로 사용될 클래스는 @Controller 어노테이션을 등록하고 @GetMapping 또는 @PostMapping 어노테이션을 메소드에서 등록해 요청의 경로를 지정합니다.

더보기

컨트롤러가 지정하는 요청 경로는 서블릿 컨텍스트 경로(또는 웹 애플리케이션 경로)를 기준으로 합니다.

컨트롤러는 스프링 빈으로 등록해야 합니다. chap09 패키지에서 ControllerConfig 클래스를 작성합니다.

이 설정 클래스는 DispatcherServlet 설정의 contextConfiguration 초기화 파라미터에 의해서 설정됩니다.

package chap09.config;

import chap09.HelloController;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ControllerConfig
{
	@Bean
	public HelloController helloController()
	{
		return new HelloController();
	}
}

JSP 구현

컨트롤러가 생성한 결과를 보여줄 뷰 코드를 작성합니다. 뷰 코드는 JSP를 이용해서 구현합니다.

src/main/webapp/WEB-INF/view 디렉토리에서 hello.jsp를 작성합니다.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
    <title>Hello</title>
</head>
<body>
    인사말: ${greeting}
</body>
</html>
코드 비고
Line 8 ${greeting} 컨트롤러에서 Model 객체에 greeting 속성으로 입력한 값을 출력합니다.

IntelliJ IDEA에서 Tomcat으로 실행하기

IntelliJ IDEA | 상단 툴바 | Run | Edit Configurations에 들어갑니다.

Add New Configuration(+)를 누르고 Tomcat Server를 검색해 Local을 선택합니다.

Deployment 탭에서 Add(+) | Artifact를 클릭하고 Gradle: sp5-chap09.war (exploded)를 선택합니다.

Application context는 sp5-chap09를 사용합니다.

Server 탭으로 이동해 Application server에서 톰캣 서버 버전을 선택합니다.

Name은 톰캣 서버 버전에 의해 자동 생성된 값 또는 임의의 값을 사용합니다. HTTP port는 디폴트 8080을 사용합니다.

URL은 자동 생성된 값을 사용합니다.

애플리케이션을 실행하면 다음 콘솔 로그와 함께 웹 브라우저에서 새로운 탭이 실행됩니다.

/Users/namepgb/tomcat/apache-tomcat-8.5.84/bin/catalina.sh run
NOTE: Picked up JDK_JAVA_OPTIONS:  --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED
[2024-01-03 04:45:01,974] Artifact Gradle : sp5-chap09.war (exploded): Waiting for server connection to start artifact deployment...
03-Jan-2024 04:45:02.738 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log 서버 버전 이름:    Apache Tomcat/8.5.84
03-Jan-2024 04:45:02.741 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log Server 빌드 시각:  Nov 16 2022 13:34:24 UTC
03-Jan-2024 04:45:02.741 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log Server 버전 번호:  8.5.84.0
03-Jan-2024 04:45:02.741 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log 운영체제 이름:     Mac OS X
03-Jan-2024 04:45:02.741 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log 운영체제 버전:     10.16
03-Jan-2024 04:45:02.742 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log 아키텍처:          x86_64
03-Jan-2024 04:45:02.742 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log 자바 홈:           /Library/Java/JavaVirtualMachines/adoptopenjdk-12.jdk/Contents/Home
03-Jan-2024 04:45:02.742 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log JVM 버전:          12.0.2+10
03-Jan-2024 04:45:02.742 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log JVM 벤더:          AdoptOpenJDK
03-Jan-2024 04:45:02.742 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE:     /Users/namepgb/Library/Caches/JetBrains/IntelliJIdea2020.3/tomcat/e5802ba8-14f2-49b3-a0ff-9229474720a7
03-Jan-2024 04:45:02.742 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_HOME:     /Users/namepgb/tomcat/apache-tomcat-8.5.84
03-Jan-2024 04:45:02.744 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log 명령 행 아규먼트:  --add-opens=java.base/java.lang=ALL-UNNAMED
03-Jan-2024 04:45:02.744 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log 명령 행 아규먼트:  --add-opens=java.base/java.io=ALL-UNNAMED
03-Jan-2024 04:45:02.744 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log 명령 행 아규먼트:  --add-opens=java.base/java.util=ALL-UNNAMED
03-Jan-2024 04:45:02.744 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log 명령 행 아규먼트:  --add-opens=java.base/java.util.concurrent=ALL-UNNAMED
03-Jan-2024 04:45:02.745 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log 명령 행 아규먼트:  --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED
03-Jan-2024 04:45:02.745 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log 명령 행 아규먼트:  -Djava.util.logging.config.file=/Users/namepgb/Library/Caches/JetBrains/IntelliJIdea2020.3/tomcat/e5802ba8-14f2-49b3-a0ff-9229474720a7/conf/logging.properties
03-Jan-2024 04:45:02.745 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log 명령 행 아규먼트:  -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
03-Jan-2024 04:45:02.745 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log 명령 행 아규먼트:  -Dcom.sun.management.jmxremote=
03-Jan-2024 04:45:02.745 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log 명령 행 아규먼트:  -Dcom.sun.management.jmxremote.port=1099
03-Jan-2024 04:45:02.745 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log 명령 행 아규먼트:  -Dcom.sun.management.jmxremote.ssl=false
03-Jan-2024 04:45:02.745 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log 명령 행 아규먼트:  -Dcom.sun.management.jmxremote.password.file=/Users/namepgb/Library/Caches/JetBrains/IntelliJIdea2020.3/tomcat/e5802ba8-14f2-49b3-a0ff-9229474720a7/jmxremote.password
03-Jan-2024 04:45:02.745 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log 명령 행 아규먼트:  -Dcom.sun.management.jmxremote.access.file=/Users/namepgb/Library/Caches/JetBrains/IntelliJIdea2020.3/tomcat/e5802ba8-14f2-49b3-a0ff-9229474720a7/jmxremote.access
03-Jan-2024 04:45:02.746 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log 명령 행 아규먼트:  -Djava.rmi.server.hostname=127.0.0.1
03-Jan-2024 04:45:02.746 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log 명령 행 아규먼트:  -Djdk.tls.ephemeralDHKeySize=2048
03-Jan-2024 04:45:02.746 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log 명령 행 아규먼트:  -Djava.protocol.handler.pkgs=org.apache.catalina.webresources
03-Jan-2024 04:45:02.746 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log 명령 행 아규먼트:  -Dorg.apache.catalina.security.SecurityListener.UMASK=0027
03-Jan-2024 04:45:02.746 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log 명령 행 아규먼트:  -Dignore.endorsed.dirs=
03-Jan-2024 04:45:02.746 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log 명령 행 아규먼트:  -Dcatalina.base=/Users/namepgb/Library/Caches/JetBrains/IntelliJIdea2020.3/tomcat/e5802ba8-14f2-49b3-a0ff-9229474720a7
03-Jan-2024 04:45:02.746 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log 명령 행 아규먼트:  -Dcatalina.home=/Users/namepgb/tomcat/apache-tomcat-8.5.84
03-Jan-2024 04:45:02.746 정보 [main] org.apache.catalina.startup.VersionLoggerListener.log 명령 행 아규먼트:  -Djava.io.tmpdir=/Users/namepgb/tomcat/apache-tomcat-8.5.84/temp
03-Jan-2024 04:45:02.747 정보 [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent 프로덕션 환경들에서 최적의 성능을 제공하는, APR 기반 Apache Tomcat Native 라이브러리가, 다음 java.library.path에서 발견되지 않습니다: [/Users/namepgb/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.]
03-Jan-2024 04:45:02.778 정보 [main] org.apache.coyote.AbstractProtocol.init 프로토콜 핸들러 ["http-nio-8080"]을(를) 초기화합니다.
03-Jan-2024 04:45:02.802 정보 [main] org.apache.catalina.startup.Catalina.load Initialization processed in 417 ms
03-Jan-2024 04:45:02.844 정보 [main] org.apache.catalina.core.StandardService.startInternal 서비스 [Catalina]을(를) 시작합니다.
03-Jan-2024 04:45:02.844 정보 [main] org.apache.catalina.core.StandardEngine.startInternal 서버 엔진을 시작합니다: [Apache Tomcat/8.5.84]
03-Jan-2024 04:45:02.862 정보 [main] org.apache.coyote.AbstractProtocol.start 프로토콜 핸들러 ["http-nio-8080"]을(를) 시작합니다.
03-Jan-2024 04:45:02.877 정보 [main] org.apache.catalina.startup.Catalina.start Server startup in 74 ms
Connected to server
[2024-01-03 04:45:03,070] Artifact Gradle : sp5-chap09.war (exploded): Artifact is being deployed, please wait...
03-Jan-2024 04:45:03.845 정보 [RMI TCP Connection(2)-127.0.0.1] org.apache.jasper.servlet.TldScanner.scanJars 적어도 하나의 JAR가 TLD들을 찾기 위해 스캔되었으나 아무 것도 찾지 못했습니다. 스캔했으나 TLD가 없는 JAR들의 전체 목록을 보시려면, 로그 레벨을 디버그 레벨로 설정하십시오. 스캔 과정에서 불필요한 JAR들을 건너뛰면, 시스템 시작 시간과 JSP 컴파일 시간을 단축시킬 수 있습니다.
03-Jan-2024 04:45:04.002 정보 [RMI TCP Connection(2)-127.0.0.1] org.springframework.web.servlet.FrameworkServlet.initServletBean FrameworkServlet 'dispatcher': initialization started
03-Jan-2024 04:45:04.019 정보 [RMI TCP Connection(2)-127.0.0.1] org.springframework.context.support.AbstractApplicationContext.prepareRefresh Refreshing WebApplicationContext for namespace 'dispatcher-servlet': startup date [Wed Jan 03 04:45:04 KST 2024]; root of context hierarchy
03-Jan-2024 04:45:04.072 정보 [RMI TCP Connection(2)-127.0.0.1] org.springframework.web.context.support.AnnotationConfigWebApplicationContext.loadBeanDefinitions Successfully resolved class for [chap09.config.MvcConfig]
03-Jan-2024 04:45:04.094 정보 [RMI TCP Connection(2)-127.0.0.1] org.springframework.web.context.support.AnnotationConfigWebApplicationContext.loadBeanDefinitions Successfully resolved class for [chap09.config.ControllerConfig]
03-Jan-2024 04:45:04.534 정보 [RMI TCP Connection(2)-127.0.0.1] org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry.register Mapped "{[/hello],methods=[GET]}" onto public java.lang.String chap09.HelloController.hello(org.springframework.ui.Model,java.lang.String)
03-Jan-2024 04:45:04.575 정보 [RMI TCP Connection(2)-127.0.0.1] org.springframework.web.servlet.handler.AbstractUrlHandlerMapping.registerHandler Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler]
03-Jan-2024 04:45:04.619 정보 [RMI TCP Connection(2)-127.0.0.1] org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.initControllerAdviceCache Looking for @ControllerAdvice: WebApplicationContext for namespace 'dispatcher-servlet': startup date [Wed Jan 03 04:45:04 KST 2024]; root of context hierarchy
03-Jan-2024 04:45:04.752 정보 [RMI TCP Connection(2)-127.0.0.1] org.springframework.web.servlet.FrameworkServlet.initServletBean FrameworkServlet 'dispatcher': initialization completed in 750 ms
[2024-01-03 04:45:04,764] Artifact Gradle : sp5-chap09.war (exploded): Artifact is deployed successfully
[2024-01-03 04:45:04,764] Artifact Gradle : sp5-chap09.war (exploded): Deploy took 1,694 milliseconds
03-Jan-2024 04:45:12.870 정보 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory 웹 애플리케이션 디렉토리 [/Users/namepgb/tomcat/apache-tomcat-8.5.84/webapps/manager]을(를) 배치합니다.
03-Jan-2024 04:45:12.905 정보 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory 웹 애플리케이션 디렉토리 [/Users/namepgb/tomcat/apache-tomcat-8.5.84/webapps/manager]에 대한 배치가 [35] 밀리초에 완료되었습니다.

웹 브라우저에서는 http://localhost:8080/sp5-chap09/ 주소로 404 Not Found 오류가 표시됩니다.

컨트롤러가 매핑된 주소에 해당하는 http://localhost:8080/sp5-chap09/hello?name=bk를 입력합니다. 이때 name=bk는 웹에서 컨트롤러로 요청하는 파라미터입니다.

JSP로 작성한 뷰가 정상적으로 렌더링되는 것을 확인 할 수 있습니다.