Spring

[Spring] Custom HttpMessageConvert 생성 & 등록을 위한 WebMvcConfigurer 활용

kimyongjun0129 2025. 6. 6. 23:42

 


 

개요

❗Custom Converter 등록을 위해서만 WebMvcConfigurer을 사용하지는 않습니다. `WebMvcConfigurer`에 대해 간단히 알아본 후, Custom `HttpMessageConverter`를 등록하는 방법에 대해 알아보겠습니다. 또한 일반 Type Converter와 다른 Custom `HttpMessageConverter` 생성 및 등록 방법에 대해 알아보겠습니다.

 


 

WebMvcConfigurer

정의

Spring Framework에서 웹 MVC 설정을 사용자 정의할 수 있도록 제공되는 인터페이스입니다.

 

 

✨ Spring Boot를 사용하면 대부분의 설정이 자동으로 제공되지만, 특별한 요구사항이 있을 때 `WebMvcConfigurer`를 구현해서 설정을 직접 조정할 수 있습니다.

더보기

Spring이 WebMvcConfigurer 구현체를 이용하여 설정하는 것이 아닌데, Spring Boot의 설정이 자동으로 제공되는 이유는 다음과 같습니다.

 

Spring Boot의 자동 설정 클래스

`org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration`

  • 이 클래스는 Spring Boot에서 기본적인 MVC 설정을 자동으로 제공하는 핵심 클래스입니다.
  • 여기서 ViewResolver, MessageConverter, Interceptor 등 대부분의 기본 설정을 자동으로 구성합니다.

 

 

설정 대상

  • URL 매핑
  • 정적 자원 처리
  • CORS
  • 인터셉터
  • Formatter
  • Message Converter 등

 

 

주요 메서드

메서드 역할 설명
configurePathMatch(PathMatchConfigurer configurer) 경로 설정 URL 경로 매칭 방식 설정 (예: 슬래시 처리 등)
configureContentNegotiation(ContentNegotiationConfigurer configurer) 콘텐츠 협상 클라이언트 요청의 Accept 헤더에 따라 반환 콘텐츠 유형 결정
configureAsyncSupport(AsyncSupportConfigurer configurer) 비동기 설정 @Async, Callable, DeferredResult 등을 사용할 때 비동기 처리 설정
configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) 서블릿 핸들링 DispatcherServlet이 처리하지 않는 요청을 서블릿에 위임
addFormatters(FormatterRegistry registry) 포맷터 등록 문자열 ↔ 객체 변환용 포맷터, 컨버터 등록
addInterceptors(InterceptorRegistry registry) 인터셉터 등록 요청 전/후 가로채기 로직 설정 (예: 인증, 로깅)
addResourceHandlers(ResourceHandlerRegistry registry) 정적 자원 처리 /static/**, /public/** 등 정적 파일 위치 매핑
addCorsMappings(CorsRegistry registry) CORS 설정 도메인 간 요청 허용 정책 설정
addViewControllers(ViewControllerRegistry registry) 뷰 컨트롤러 설정 컨트롤러 없이 단순 URL → 뷰 매핑
configureViewResolvers(ViewResolverRegistry registry) 뷰 리졸버 설정 JSP, Thymeleaf 등의 뷰 리졸버 설정
addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) 인자 리졸버 컨트롤러 메서드 인자 바인딩 커스터마이징
addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) 반환값 핸들러 컨트롤러 반환값 처리 방식 커스터마이징
configureMessageConverters(List<HttpMessageConverter<?>> converters) 메시지 컨버터 설정 요청/응답 데이터를 Java 객체와 JSON 등으로 변환
extendMessageConverters(List<HttpMessageConverter<?>> converters) 메시지 컨버터 확장 기존 컨버터에 추가 설정 적용
configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) 예외 처리 설정 예외 → 응답으로 변환하는 설정 커스터마이징
extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) 예외 처리 확장 기존 예외 처리 로직에 추가 기능 부여

 

 

내부 구조

public interface WebMvcConfigurer {
    default void configurePathMatch(PathMatchConfigurer configurer) {
    }

    default void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    }

    default void configureAsyncSupport(AsyncSupportConfigurer configurer) {
    }

    default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    }

    default void addFormatters(FormatterRegistry registry) {
    }

    default void addInterceptors(InterceptorRegistry registry) {
    }

    default void addResourceHandlers(ResourceHandlerRegistry registry) {
    }

    default void addCorsMappings(CorsRegistry registry) {
    }

    default void addViewControllers(ViewControllerRegistry registry) {
    }

    default void configureViewResolvers(ViewResolverRegistry registry) {
    }

    default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
    }

    default void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {
    }

    default void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    }

    default void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
    }

    default void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
    }

    default void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
    }

    @Nullable
    default Validator getValidator() {
        return null;
    }

    @Nullable
    default MessageCodesResolver getMessageCodesResolver() {
        return null;
    }
}
  • 각 메서드는 `default`로 정의되어있습니다. 그 이유는 WebMvcConfigurer 인터페이스 구현 시, 모든 메서드를 구현할 필요없이 필요한 메서드만 구현하기 위함입니다.

 


 

Custom MessageConverter 생성 및 등록

 

❗WebMvcConfigurer 중에서, `HttpMessageConverter`와 관련된 `extendMessageConverters()`와 `configureMessageConverters`를 사용하여 등록합니다.

 

 

등록 방식

1. Custom MessageConverter 작성

public class MyCustomMessageConverter extends AbstractHttpMessageConverter<MyType> {

    public MyCustomMessageConverter() {
        super(new MediaType("application", "mytype"));
    }

    @Override
    protected boolean supports(Class<?> clazz) {
        return MyType.class.isAssignableFrom(clazz);
    }

    @Override
    protected MyType readInternal(Class<? extends MyType> clazz, HttpInputMessage inputMessage)
            throws IOException {
        // 요청 데이터 파싱
        InputStream inputStream = inputMessage.getBody();
        // ...직접 파싱 로직...
        return new MyType();
    }

    @Override
    protected void writeInternal(MyType myType, HttpOutputMessage outputMessage)
            throws IOException {
        // 응답 데이터 출력
        OutputStream outputStream = outputMessage.getBody();
        // ...직접 출력 로직...
    }
}
  • 복잡한 작업을 간단하게 처리해주기 위해 `HttpMessageConverter`를 직접 구현하지 않고 ` AbstractHttpMessageConverter` 추상 클래스를 상속받아서 훨씬 편리하고 안전하게 custom converter를 만들 수 있습니다.
메서드 역할
supports(Class<?> clazz) 이 컨버터가 처리할 수 있는 타입인지 확인
readInternal(...) HTTP 요청 본문 → Java 객체로 변환 (역직렬화)
writeInternal(...) Java 객체 → HTTP 응답 본문으로 변환 (직렬화)

 

 

2_1. extendMessageConverters(List<httpmessageconverter<?>> converters) 방식</httpmessageconverter<?>

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(new MyCustomMessageConverter());
    }
}
  • `@Configuration`: Spring에게 이 클래스를 Bean 설정 파일로 등록
    • 내부에서 정의된 설정(예: MessageConverter, Interceptro 등)을 자동으로 적용하게 됩니다. 
    • `@Configuration`을 붙여야 Bean으로 등록되어 사용할 수 있습니다.
  • 기존 Spring의 기본 컨버터 리스트에 커스텀 컨버터를 추가하였습니다.
  • 자동 설정된 기본 컨버터는 그대로 유지됩니다.

 

 

2_2. configureMessageConverters(List<httpmessageconverter<?>> converters) 방식</httpmessageconverter<?>

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(new MyCustomMessageConverter());
    }
}
  • 커스텀 컨버터만 직접 명시합니다.
  • Spring이 기본으로 제공하는 컨버터는 등록되지 않습니다.
  • 전체 메시지 컨버터를 직접 컨트롤하고 싶을 때만 사용합니다.

✨ 주의 : 기본 JSON 컨버터(Jackson 등)도 포함되지 않기 때문에, 필요한 컨버터를 모두 수동으로 등록해야합니다.

 

 

더보기

custom 말고, 기본 HttpMessageConverter들은 자동 설정(Auto Configuration)을 통해 다음처럼 등록됩니다.

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
    ...
    
    protected final void addDefaultHttpMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
        messageConverters.add(new MappingJackson2HttpMessageConverter());
        messageConverters.add(new StringHttpMessageConverter());
        messageConverters.add(new ByteArrayHttpMessageConverter());
        // 등등
    }
    
    ...
}

 


 

Custom MessageConverter 필요 상황

상황 설명
기존 컨버터가 지원하지 않는 포맷 예: CSV, YAML, 커스텀 바이너리, 고유한 텍스트 포맷 등
특정 DTO만 별도로 처리하고 싶을 때 일부 클래스에만 커스텀 JSON 포맷 적용 등
보안이나 암호화된 요청/응답 처리 입력값 복호화 또는 응답 암호화
외부 시스템 연동 (특수 API 형식) 예: 외부 시스템이 application/vnd.xxx+json 같은 형식을 요구
헤더나 구조가 정형화된 전용 응답 필요 응답에 반드시 특정 구조 ({status: ..., data: ...}) 강제할 때
파일 또는 바이너리 처리 (비표준 방식) 이미지, blob 등 커스텀 이진 데이터 처리
레거시 시스템 대응 오래된 시스템과 통신 시, JSON 구조가 이상한 경우 대응 필요