이 글의 코드 및 정보들은 강의를 들으며 정리한 내용을 토대로 작성하였습니다.
글의 목표
-
WebMvcConfigurer을
왜 구현하고
구현하면 어떤 점이 좋아지는지에 대해 알아보자.
Q & A
Question
-
많은 프로젝트에서 WebMvcConfigurer를 구현한다.
왜 구현하는걸까?
WebMvcConfigurer
-
@EnableWebMvc를 사용하면
ViewResolver 값이 자동으로 등록된다.
-
그렇게 등록된 세팅을 A라고 하자.
-
이 상황에서 A 값에
추가적인 세팅을 더 하고 싶다.
-
만약 추가적인 세팅이 필요하다면
A 세팅과 똑같은 Bean을 구현하고
거기에 원하는 추가적인 세팅을 해서
customViewResolver( )과 같은
Bean을 직접 정의해야한다.
@Bean
public ViewResolver customViewResolver() {
InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
internalResourceViewResolver.setPrefix("/WEB-INF/");
internalResourceViewResolver.setSuffix(".jsp");
return internalResourceViewResolver;
}
-
매우 불편하다.
-
그래서 WebMvcConfigurer를 사용한다.
-
WebMvcConfigurer를 사용하면
@EnableWebMvc가 자동적으로 세팅해주는 설정에
개발자가 원하는 설정을 추가할 수 있게 된다.
-
즉 Override가 가능하다.
-
최종적으로 코드를 보면
configureViewResolvers( ) 와 customViewResolver( )는 같은 역할을 한다.
// configureViewResolvers() = @EnableWebMvc에 의한 세팅 값 + 사용자에 의한 추가 세팅
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp("/WEB-INF/",".jsp");
}
// customViewResolver = @EnableWebMvc 세팅 값 직접 구현 + 사용자에 의한 추가 세팅
@Bean
public ViewResolver customViewResolver() {
InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
internalResourceViewResolver.setPrefix("/WEB-INF/");
internalResourceViewResolver.setSuffix(".jsp");
return internalResourceViewResolver;
}
Answer
-
WebMvcConfigurer를 구현하면
@EnableWebMvc 어노테이션이 자동으로 설정해주는 세팅 값에
사용자가 원하는 세팅을 추가할 수 있게 된다.
-
그렇기 때문에 WebMvcConfigurer를 구현하는 것이다.
Code Example
WebConfig.java
@Configuration
@ComponentScan
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
// Case1. WebMvcConfigurer를 구현하였을 경우
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp("/WEB-INF/",".jsp");
}
}
@Configuration
@ComponentScan
@EnableWebMvc
public class WebConfig {
// Case2. WebMvcConfigurer를 구현하지 않고 직접 Bean을 정의하는 경우
@Bean
public ViewResolver customViewResolver() {
InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
internalResourceViewResolver.setPrefix("/WEB-INF/");
internalResourceViewResolver.setSuffix(".jsp");
return internalResourceViewResolver;
}
}
-
viewResolver가 필요한 상황에서
WebMvcConfigurer 구현 유무에 따른 WebConfig의 Code 차이를 볼 수 있다.
-
일반적으로 WebMvcConfigurer은
WebConfig와 같은 Config 파일에서 사용된다.
-
여기서 WebConfig 파일의 존재 목적은 다음과 같다.
-
DispactcherServlet을 생성할 때
생성자 인자로 WebApplicationContext을 전달한다.
-
그런데 WebApplicationContext은
어떤 Config 파일을 사용할 지 명시해줘야 하는데
그 Config 값으로 일반적으로는 WebConfig를 지정한다.
-
만약 위 문장이 이해가 가지 않는다면
반드시 DispatcherServlet가 WebApplicationContext를 생성하는 2가지 방법 글을 읽길 바란다.
WebMvcConfigurer 구현 X
-
WebMvcConfigurer를 구현하지 않고
추가적인 세팅을 위해
새로운 Bean을 직접 정의하여 사용하는 경우를 알아보자.
-
DispatcherServlet.class에서
doService()에 Break Point를 걸고 값을 체크해보자.
Reference : org.springframework.web.servlet.DispatcherServlet#doService
-
viewResolver에 2개가 등록되어 있다.
-
우리가 정의했던 InternalResourceViewResolver와
ViewResolverComposite가 등록되어 있다.
-
그런데 ViewResolverComposite는 어디서 등록되는 걸까?
-
다음 순서로 코드를 살펴보면 답을 알 수 있다.
@EnableWebMvc -> DelegatingWebMvcConfiguration -> WebMvcConfigurationSupport
WebMvcConfigurationSupport.class -> mvcViewResolver( )
@Bean
public ViewResolver mvcViewResolver() {
ViewResolverRegistry registry = new ViewResolverRegistry();
registry.setContentNegotiationManager(this.mvcContentNegotiationManager());
registry.setApplicationContext(this.applicationContext);
this.configureViewResolvers(registry);
if (registry.getViewResolvers().isEmpty()) {
String[] names = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.applicationContext, ViewResolver.class, true, false);
if (names.length == 1) {
registry.getViewResolvers().add(new InternalResourceViewResolver());
}
}
// ViewResolverComposite을 생성하여 return 한다.
ViewResolverComposite composite = new ViewResolverComposite();
composite.setOrder(registry.getOrder());
composite.setViewResolvers(registry.getViewResolvers());
composite.setApplicationContext(this.applicationContext);
composite.setServletContext(this.servletContext);
return composite;
}
-
만약 위의 순서대로 살펴봐야하는 이유를 모르겠다면
WebConfig에서
@EnableWebMvc을 사용하고 있다는 점을 기억하며
@EnableWebMvc글을 참고하자.
WebMvcConfigurer 구현 O
- 이번에는 WebMvcConfigurer를 구현해보자.
-
위와 마찬가지로
DispatcherServlet.class의 doService()에 Break Point를 걸어보자.
// ref : org.springframework.web.servlet.DispatcherServlet#doService
-
viewResolver에 1개만 등록되어 있다.
-
우리가 임의로 생성한 InternalResourceViewResolver Bean이 불필요해졌다.
Why?
-
WebMvcConfigurer를 상속하여
추가하고자 하는 설정을 Override하였기 때문에
더이상 새롭게 Bean을 추가 할 필요가 없어졌기 때문이다.
-
대신에 Override했던 값은
viewResolvers에 담겨져있음을 확인할 수 있다.
Summary
-
WebMvcConfigurer을 구현함으로써
Application의 어떤 변화가 있는지 알아봤다.
-
주의할 점은
반드시 @EnableWebMvc 어노테이션과
함께 사용해야할 필요는 없다.
-
단지 필자의 프로젝트 구성에서
@EnableWebMvc와 WebMvcConfigurer을 같이 사용하여 예시로 들었을 뿐이다.
-
끝으로
WebMvcConfigurer를
왜 상속하는지
왜 Override하는지 등등
그 이유를 정확하게 인지하고 사용하도록 하자.