앞의 포스트에서 살펴보았듯이 DispatcherServlet을 커스텀화할 수 있었다. 설정하는 방법은 여러가지가 존재하는데, 강의에서 설명해준 방법을 정리해보자.
가장 원시적인 방법은 직접 빈을 등록하는 것이다.
@Configuration
@ComponentScan
public class WebConfig {
@Bean
public HandlerMapping handlerMapping() {
RequestMappingHandlerMapping handlerMapping = new RequestMappingHandlerMapping();
handlerMapping.setOrder(Ordered.HIGHTEST_PRECEDENCE);
return handlerMapping;
}
@Bean
public HandlerAdapter handlerAdapter() {
RequestMappingHandlerAdapter handlerAdapter = new RequestMappingHandlerAdapter();
// handlerAdapter.setArgumentResolvers();
// handlerAdapter.setMessageConverters();
// handlerAdapter.setReturnValueHandlers();
return handlerAdapter;
}
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
직접 빈을 등록하는 것이 번거롭다면 @EnableWebMvc
어노테이션만으로 편하게 구성할 수 있다.
이 어노테이션의 코드를 따라가보면 WebMvcConfigurationSupport 클래스를 확인할 수 있는데, 기본적인 설정들이 DispatcherServlet의 기본값과 다른 것을 확인할 수 있다.
예를 들어, DispatcherServlet의 HandlerMapping은 BeanNameUrlHandlerMapping 다음으로 RequestMappingHandlerMapping 순으로 되어있었다면, WebMvcConfigurationSupport 클래스에서는 RequestMappingHandlerMapping이 가장 우선순위가 되어있는 것을 알 수 있다. (RequestMappingHandlerMapping의 우선순위가 높아지므로서 성능적인 이점도 있다!)
@Configuration
@EnableWebMvc
public class WebConfig {
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
@EnableWebMvc
어노테이션으로 적용되는 기본적인 빈의 설정들을 WebMvcConfigurer 인터페이스로 조작이 가능하다. 스프링 부트에서도 많이 사용하므로 사용법을 숙지해야한다고 한다.
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp("/WEB-INF/", ".jsp");
}
}
이 인터페이스로 구성할 수 있는 설정은 다음과 같다.
결국, 우리는 어노테이션과 추가적인 조작을 할 수 있는 인터페이스로 더 편리하게 빈을 등록할 수 있다. 그럼 스프링 부트는 어떨까?
DispatcherServlet에 중단점을 걸어두고 디버깅을 해보자.
디버깅을 통해 알아낼 수 있는 정보는, HandlerMapping, HandlerAdapter, ViewResolver 등 스프링 부트에서 자동으로 설정되어 사용되는 것들을 확인할 수 있다.
스프링 부트에서 이러한 빈들에 대한 자동 설정 값은 autoconfigure jar 파일 의 Spring.factories를 열어보면 전체적으로 확인할 수 있다.
💡 스프링 부트에서 직접 빈을 등록하는 방법으로 진행하려면 어떻게 해야할까?
WebMvcAutoConfiguration 클래스를 열어서 확인해보자.
@Configuration( proxyBeanMethods = false ) @ConditionalOnWebApplication( type = Type.SERVLET ) @ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class}) @ConditionalOnMissingBean({WebMvcConfigurationSupport.class}) @AutoConfigureOrder(-2147483638) @AutoConfigureAfter({DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class}) public class WebMvcAutoConfiguration { }
이 코드에서
@ConditionalOnMissingBean
어노테이션은 WebMvcConfigurationSupport 타입의 빈이 없는 경우에는 WebMvcAutoConfiguration 설정을 사용하고, 그렇지 않을 경우에는 사용하지 않는다는 의미를 가진다.따라서
@Configuration, @EnableWebMvc, WebMvcConfigurer
조합을 사용하면 스프링 부트에서 제공하는 자동 설정을 사용하지 않을 수 있고,@Configuration, WebMvcConfigurer
조합을 사용하면 스프링 부트의 자동 설정을 사용할 수 있다.
스프링 부트에서는 자동 설정시 프로퍼티 파일의 값들을 가져와 사용하는데, 이러한 프로퍼티를 정의하기 위해서는 classpath에 대한 정보와 prefix가 존재하니 반드시 확인하고 사용해야한다.
손을 대지 않고 커스터마이징을 할 수 있는 방법이기에 가장 많이 사용하는 방법이라고 한다.
백기선님은 스프링 부트를 사용하는 경우라면 application.properties로 먼저 키-값을 조정하여 커스터마이징을 해보고, application.properties로 안되는 경우에는 WebMvcConfigurer 인터페이스를 이용하고, 그래도 안된다면 직접 빈을 등록하여 해결하는 것을 추천해주셨다.