본문 바로가기
  • 실행력이 모든걸 결정한다
Spring Series/Spring Framework

[Spring] 자바 코드를 이용한 MVC 전략 설정

by 김코더 김주역 2022. 10. 6.
반응형

1. @EnableWebMvc와 WebMvcConfigurer

1) @EnableWebMvc와 WebMvcConfigurer의 관계

- @Configuration 클래스에 @EnableWebMvc를 붙여주는 것만으로 <mvc:annotation-driven/>를 xml bean 설정 파일에 넣었을 때와 동일하게 동작한다. 하지만, 기본 설정을 변경하게 된다면 어노테이션 방식이나 xml 방식으로는 설정이 너무 복잡해진다. 그래서 Spring은 자바 코드 방식의 설정을 위한 WebMvcConfigurer를 제공한다.

- Spring은 @EnableWebMvc와 같은 @Enable 전용 어노테이션으로 등록되는 인프라 bean에 대한 추가 설정을 위해 컨피규어러(Configurer)라는 설정용 bean을 활용하는 방법을 제공한다. 컨피규어러 bean이 구현해야 하는 인터페이스의 이름은 대부분 Configurer로 끝난다. 컨피규어러 bean은 @Enable 전용 어노테이션을 처리하는 단계에서 활용되어 인프라 bean의 설정을 수행한다.

 

● 정리하자면, @EnableWebMvc로 등록되는 인프라 bean에 대한 추가 설정은 WebMvcConfigurer의 구현체가 담당하는 것이다.

 

 

2) WebMvcConfigurer의 설정 메소드

- WebMvcConfigurer의 메소드들을 통해 @MVC에 관한 다양한 설정이 가능하다. 참고로, WebMvcConfigurer 문서는 아래 링크에서 확인할 수 있다.

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.html

 

WebMvcConfigurer (Spring Framework 5.3.23 API)

 

docs.spring.io

- WebMvcConfigurer은 인터페이스이기 때문에 모든 메소드를 구현해야 한다. 구현할 필요가 없는 메소드는 내용을 비워놓아도 된다.

- WebMvcConfigurer에서 add로 시작하는 메소드는 디폴트 구성에 빈이나 새로운 오브젝트를 추가할 때 사용되고, configure로 시작하는 메소드는 기존 구성을 새롭게 구성할 때 사용된다. 기존 구성을 새롭게 구성한다는 것은 기존에 있던 디폴트 전략을 무시하고 자신만의 구성으로 디폴트 전략을 다시 추가하거나 커스텀 전략을 추가한다는 것을 의미한다. 디폴트 구성을 유지한 채로 커스텀 전략을 추가하고 싶다면 WebMvcConfigurationSupport를 상속해서 사용하면 된다. WebMvcConfigurationSupport는 @EnableWebMvc에 의해 등록되는 모든 전략 bean을 직접 정의하고 있는 @Bean 메소드들을 갖고 있는 클래스다. @Bean 메소드는 public이기 때문에 오버라이딩해서 사용할 수 있다.

 

(1) addFormatters()

- 포맷터를 추가해주는 메소드다. 포맷터는 String 타입의 요청 파라미터와 컨트롤러 메소드의 파라미터 사이에서 양방향으로 타입을 변환해주는 오브젝트다.

- 포맷터 오브젝트는 직접 생성하거나 bean으로 만들어서 FormatterRegistry에 등록하면 된다.

public void addFormatters(FormatterRegistry registry) {
    registry.addFormatter(new MyFormatter());
}

FormatterRegistry의 addFormatterForFieldType() 메소드를 통해 포맷터가 특정 타입의 필드에만 적용되게 만들 수도 있고, addFormatterForFieldAnnotation() 메소드를 통해 포맷터가 특정 어노테이션이 붙은 필드에만 적용되게 만들 수도 있다. 참고로, FormatterRegistry는 ConverterRegistry 인터페이스를 상속받기 때문에 addConverter() 메소드를 통해 컨버터를 등록할 수도 있다.

 

(2) configureMessageConverters()

- 디폴트 메시지 컨버터 구성을 새롭게 구성할 때 사용한다.

- 메시지 컨버터 오브젝트는 직접 생성하거나 bean으로 만들어서 List<HttpMessageConverter<?>>에 등록하면 된다.

@Autowired MyMessageConverter myMessageConverter;

public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    converters.add(new MappingJacksonHttpMessageConverter());
    converters.add(myMessageConverter);
}

 

(3) getValidator()

- JSR-303의 검증 기능을 사용할 수 있도록 하는 일종의 어댑터인 LocalValidatorFactoryBean을 대신할 범용 검증기를 등록할 때 사용한다.

 

(4) addArgumentResolvers()

- 컨트롤러 메소드에서 사용할 수 있는 파라미터 타입을 추가할 때 쓰이는 HandlerMethodArgumentResolver를 추가할 때 사용한다.

 

(5) addReturnValueHandlers()

- 컨트롤러 메소드에서 사용할 수 있는 리턴 타입을 추가할 때 쓰이는 HandlerMethodReturnValueHandler를 추가할 때 사용한다.

 

(6) configureHandlerExceptionResolvers()

- 디폴트로 등록되는 핸들러 예외 전략을 새롭게 구성할 때 사용한다.

※ 디폴트 핸들러 예외 전략들 중에서 AnnotationMethodHandlerExceptionResolver 전략은 Spring 3.1에서 @ExceptionHandler 지원용 ExceptionHandlerExceptionResolver 전략으로 대체되었다.

 

(7) addInterceptors()

- 인터셉터를 등록해주는 <mvc:interceptors>의 기능을 수행한다.

- 인터셉터 오브젝트는 직접 생성하거나 bean으로 만들어서 메소드의 파라미터에 있는 InterceptorRegistry에 등록하면 된다. InterceptorRegistry가 지원하는 addInterceptor()와 addWebRequestInterceptor() 메소드를 통해 각각 HandlerInterceptor와 WebRequestInterceptor 타입의 인터셉터를 등록할 수 있다.

WebRequestInterceptor은 서블릿과 포틀릿 환경에서 모두 사용할 수 있는 인터셉터 타입이다.

protected void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new MyInterceptor());
}

- 특정 URL 패턴에 대한 요청에만 인터셉터를 적용하려면 addPathPatterns() 메소드를 붙여서 URL 패턴을 지정해주면 된다. 물론 addWebRequestInterceptor() 메소드의 뒤에도 연결 가능하다.

protected void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new MyInterceptor()).addPathPatterns("/user/**");
}

특정 URL 패턴에 대한 요청에만 인터셉터를 적용하지 않으려면 excludePathPatterns() 메소드를 이용하면 된다.

 

(8) addViewControllers()

- URL 패턴을 그대로 뷰 이름으로 돌려주기만 하는 컨트롤러를 등록할 때 사용되는 메소드다.

- 메소드의 파라미터에 있는 ViewControllerRegistry의 addViewController() 메소드에 매핑할 URL을 넣어주면 된다.

 

(9) addResourceHandlers()

- 정적 파일을 편리하고 최적화된 방식으로 다룰 수 있게 해주는 <mvc:resources>의 기능을 수행한다. 

https://kimcoder.tistory.com/532의 [5. <mvc:resources>] 참고

메소드의 파라미터로 제공되는 ResourceHandlerRegistry가 지원하는 addResourceHandler()와 addResourceLocations() 메소드를 통해 각각 요청 경로의 패턴과 실제 저장 경로를 지정하면 된다.

public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
}

 

(10) configureDefaultServletHandling()

- <mvc:default-servlet-handler>의 기능을 수행한다.

https://kimcoder.tistory.com/532의 [4. <mvc:default-servlet-handler>] 참고

메소드의 파라미터로 제공되는 DefaultServletHandlerConfigurer의 enable() 메소드를 사용하면 된다.

public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    configurer.enable();
}

 

 

 

2. 설정자 bean 등록

- 다음과 같이 WebMvcConfigurer의 구현체에 @Configuration과 @EnableWebMvc를 붙이는 방식이 깔끔하다.

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {...}

- WebMvcConfigurer를 통해 등록되지 않는 bean은 구현체에서 @Bean 메소드로 만들어서 등록해주면 된다.

 

 

● 참고 자료 : 토비의 스프링 3.1 Vol.2

 

 

반응형

댓글