Part 5. 스프링 MVC의 기본 구조
- 스프링 MVC의 기초는 스프링 MVC가 스프링의 서브 프로젝트라는 것이다.
- https://spring.io./projects를 보면 Spring Framework라는 메인 프로젝트 외에 여러 종류의 서브 프로젝트가 존재하는데, 스프링 MVC 역시 이러한 프로젝트 중 일부다.
- 스프링은 하나의 기능을 위해서만 만들어진 프레임워크가 아니 '코어'라고 할 수 있는 프레임워크에 여러 서브 프로젝트를 결합해 다양한 상황에 대처할 수 있도록 개발되었다.
- 서브 프로젝트라는 의미는 '별도의 설정이 존재할 수 있다.'라는 개념이다.
- Spring Legacy Project로 생성한 예제의 경우에도 servlet-context.xml과 root-context.xml로 설정 파일이 분리된 것을 볼 수 있다.
- 스프링 MVC가 서브 프로젝트이므로 구성 방식이나 설정도 조금 다르다.
- 예제에서 만드는 구조는 다음과 같은 구조가 된다.

5.1 스프링 MVC 프로젝트의 내부 구조
- 스프링 MVC 프로젝트를 구성해서 사용한다는 의미는 내부적으로 root-context.xml로 사용하는 일반 Java 영역 (흔히 POJO(Plain Old Java Object))과 servlet-context.xml로 설정하는 Web 관련 영역을 같이 연동해서 구동하게 되는데 아래와 같은 구조다.

- 바깥쪽에 있는 WebApplicationContext라는 존재는 기존의 구조에 MVC 설정을 포함하는 구조로 만들어진다.
- 스프링은 원래 목적 자체가웹 애플리케이션을 목적으로 나온 프레임워크가 아니므로 달라지는 영역에 대해서는 완전히 분리하고 연동하는 방식으로 구현되어 있다.
- Eclipse 내 'Spring Legacy Project'를 이용해 'ex01' 프로젝트를 생성한다.
- 프로젝트는 'Spring MVC Project'로 생성한다.
- 패키지명은 기존과 동일하게 'org.zerock'controller'로 지정한다.


- 생성된 프로젝트는 스프링 버전이 3버전이므로 pom.xml을 수정해 스프링을 5.0.7 버전으로 변경한다.
< pom.xml >
<properties>
<java-version>1.8</java-version>
<org.springframework-version>5.0.7.RELEASE</org.springframework-version>
<org.aspectj-version>1.6.10</org.aspectj-version>
<org.slf4j-version>1.6.6</org.slf4j-version>
</properties>
- 작성된 프로젝트 역시 Lombok 기능을 이용해 간단한 코드를 작성하고, 테스트 할 것이므로 pom.xml에 추가한다.
< pom.xml >
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.0</version>
<scope>provided</scope>
</dependency>
- Spring Legacy Project로 생성된 프로젝트는 서블릿 버전이 2.5 버전을 사용하지만, Java 설정 등을 이용하려면 서블릿 3.0 이상을 사용하는 것이 좋다.
- pom.xml 파일을 아래와 같이 2.5 버전은 주석 처리하거나 삭제하고, 3.1.0 이상 버전을 사용하도록 수정한다.
< pom.xml>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
- Maven의 컴파일 옵션은 1.8버전으로 변경하고 프로젝트의 'Maven' 메뉴에서 'update project'를 실행한다.
< pom.xml >
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArgument>-Xlint:all</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
- 프로젝트를 실행 시 아래와 같이 실행된다.

- 웹 프로젝트는 가능하면 절대 경로를 이용하는 구조를 사용하는 것이 바람직하므로, Tomcat의 'Modules'메뉴를 이용해 '/' 경로로 프로젝트가 실행될 수 있도록 처리한다.

- 프로젝트를 재 실행 시 아래와 같이 실행된다.

5.1.1 Java 설정을 이용하는 경우
- Java 설정을 이용하는 프로젝트는 'jex01'로 생성하고, web.xml과 servlet-context.xml, root-context.xml을 제거한다.
- web.xml은 DD(Deployment Descriptor), 즉 배포서술자라고 불리며, 톰켓의 환경설정을 담당한다. JAVA EE스펙의 프로젝트들은 톰캣이 들고 있는 web.xml과 프로젝트가 가지고 있는 WEB-INF의 web.xml를 거쳐 실행되게 된다.
- servlet-context.xml은 서버실행 후에 request요청이 들어올때마다 메모리를 띄우는 것들을 설정하는 공간이다.
- root-context.xml은 스프링에서 관리해야 하는 객체(Bean)를 설정하는 파일이며, root-context.xml이 들고 있는 정보들은 서버실행시 딱한번 메모리에 뜨게된다.
- Java 설정을 이용하는 경우에 pom.xml에 web.xml이 없다는 설정을 추가해야 하므로 pom.xml에 < plug in > 설정을 추가한다.
< pom.xml >
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
- Java 설정을 이용하는 경우에는 servlet-context.xml이 없는 상태에서 프로젝트를 시작하므로 'org.zerock.config' 패키지를 작성하고, WebConfig 클래스와 RootConfig 클래스를 작성한다.
< RootConfig 클래스 >
package org.zerock.config;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RootConfig {
}
< WebConfig 클래스 >
package org.zerock.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class WebConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] {RootConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
// TODO Auto-genereated method sutb
return null;
}
@Override
protected String[] getServletMappings() {
// TODO Auto-generated method stub
return null;
}
}
- Spring MVC를 이용하는 경우에는 servlet-context.xml을 대신하는 별도의 ServletConfig 클래스를 작성한다.
- ServletConfig 클래스는 기존의 servlet-coontext.xml에 설정된 모든 내용을 담아야 하는데, 이때는 주로 다음과 같은 방식을 이용한다.
* @EnableWebMvc 어노테이션과 WebMvcConfigurer 인터페이스를 구현하는 방식(과거에는 WebMvcConfigurerAdapter 추상클래스를 사용했으나, 스프링 5.0버전부터는 Deprecated 되었다.)
* @Configuration과 WebMvcConfigurationSupport 클래스를 상속하는 방식 - 일반@Configuration 우선순위가 구분되지 않는 경우에 사용
- 예제는 @EanableWebMvc 어노테이션을 이용해 제작한다. 기존에 servlet-context.xml의 내용을 아래 코드를 통해 설정한다.

- WebMvcConfigurer는 스프링 MVC와 관련된 설정을 메서드로 오버라이드 하는 형태를 이용할 때 사용한다.
- ServletConfig 클래스 역시 @ComponentScan을 이용해 다른 패키지에 작성된 스프링의 객체(Bean)를 인식할 수 있다.
- 작성된 ServletConfig 클래스를 정상적으로 실행하기 위해 WebConfig의 설정은 아래와 같이 ServletConfig를 이용하고, 스프링MVC의 기본 경로도 '/'로 변경되어야 한다.

- 설정 이후의 작업은 XML 방식과 동일하게 Tomcat에서 실행하면 된다.