Spring/강의

[📘 심화 Spring] 1. Converter, Formatter

가지코딩 2025. 6. 9. 16:39

📘 목차

  1. HttpMessageConverter
  2. ArgumentResolver
  3. ReturnValueHandler
  4. TypeConverter
  5. Converter
  6. ConversionService
  7. Converter 적용 (실습)
  8. Formatter
  9. Spring Formatter

1. HttpMessageConverter

 

HttpMessageConverter

  • HTTP 요청(Request) 또는 응답(Response)의 바디(body)를 자바 객체로 변환하거나, 자바 객체를 HTTP 메시지 바디로 변환하는 역할을 한다.
  • JSON, XML, 바이너리 데이터 ↔ 자바 객체

 

역할

  • 컨트롤러 메서드의 @RequestBody, @ResponseBody 처리를 담당
  • 클라이언트와 서버 간 데이터 직렬화/역직렬화 담당

 

 

주요 구현체

  • MappingJackson2HttpMessageConverter: JSON ↔ 자바 객체 (Jackson 라이브러리 사용)
  • StringHttpMessageConverter: 문자열 ↔ HTTP 메시지
  • ByteArrayHttpMessageConverter: 바이트 배열 ↔ HTTP 메시지

 

동작 방식

  • 요청이 들어오면 Content-Type 헤더를 보고 어떤 Converter를 사용할지 결정,
  • 응답 시 Accept 헤더나 반환 객체 타입을 보고 적절한 Converter를 선택해서 처리한다.

 

사용처

  • HTTP 요청 : @RequestBody, HttpEntity<>, RequestEntity<>
  • HTTP 응답 : @ResponseBody, HttpEntity<>, ResponseEntity<>

 

우선순위

  1. byte[]
  2. String
  3. JSON

2. ArgumentResolver

ArgumentResolver

  • 컨트롤러 메서드의 파라미터를 어떻게 채울지 결정하는 컴포넌트
  • @RequestParam, @PathVariable, @RequestBody 같은 어노테이션이 붙은 파라미터 값을 어떻게 주입할지 결정한다.

 

역할

  • HTTP 요청 데이터를 자바 메서드 파라미터에 맞게 변환 및 주입
  • 다양한 데이터 소스(쿼리 파라미터, 경로 변수, 헤더, 바디 등)로부터 값을 추출

 

사용 예

  • HandlerMethodArgumentResolver 인터페이스를 구현해서 커스텀 파라미터 바인딩 가능

3. ReturnValueHandler

ReturnValueHandler

  • 컨트롤러 메서드가 반환한 값을 어떻게 처리할지 결정하는 컴포넌트

 

역할

  • 컨트롤러 메서드의 반환값을 HTTP 응답(Response)으로 변환하거나, 뷰 이름으로 변환하는 역할을 수행
  • 반환된 객체를 적절히 가공해 클라이언트에게 전달하는 과정 담당

 

주요 구현체

  • RequestResponseBodyMethodProcessor: 주로 @ResponseBody가 붙은 경우 HTTP 메시지 변환 수행
  • ModelAndViewMethodReturnValueHandler: 뷰 이름이나 모델을 반환하는 경우 처리
  • ViewNameMethodReturnValueHandler: 문자열 뷰 이름 반환 처리

 

동작 방식

  • 스프링 MVC는 컨트롤러 반환값의 타입과 어노테이션을 보고 알맞은 ReturnValueHandler를 선택해 처리한다.
  • ex. 반환값에 @ResponseBody가 있으면 RequestResponseBodyMethodProcessor가 동작하여 HttpMessageConverter를 통해 응답을 생성한다.

 

커스터마이징

  • HandlerMethodReturnValueHandler 인터페이스를 구현하여 개발자가 직접 반환값 처리 로직을 확장할 수 있다.

4. TypeConverter

TypeConverter

  • 주로 스프링 내부에서 객체 타입 변환을 담당하는 기본 컴포넌트
  • 문자열 "123"을 정수 123으로 변환하는 등의 간단한 타입 변환 기능을 제공한다.

 

역할

  • 간단한 타입 변환 처리 (특히 프론트엔드에서 넘어오는 문자열 파라미터 변환)
  • 프로퍼티 설정, 바인딩 시 타입 변환 지원

 

특징

  • 주로 BeanWrapper와 연동되어 사용된다.
  • 스프링 MVC 외에도 다양한 스프링 내부 기능에서 사용

5. Converter

Converter

  • 스프링에서 제공하는 타입 변환 인터페이스
  • 두 타입 간의 변환을 위한 범용 인터페이스로, Converter<S, T> 형태로 정의

 

역할

  • 개발자가 직접 두 타입 간 변환 로직을 구현해 등록 가능
  • ConversionService에서 활용되어 여러 타입 변환을 유연하게 처리

 

사용 예

public class StringToUserConverter implements Converter<String, User> {
    @Override
    public User convert(String source) {
        // String -> User 변환 로직 구현
    }
}

6. ConversionService

ConversionService

  • 여러 Converter를 등록하고 관리하는 스프링의 타입 변환 허브
  • 변환 요청이 들어오면 적합한 Converter를 찾아 실행한다.

 

역할

  • 타입 변환 요청 중개자 역할
  • 컨버터들을 등록하고 관리하여 일관성 있는 타입 변환 보장
  • 스프링 내부 바인딩, 메시지 변환, 데이터 변환에 널리 사용

 

주요 구현체

  • DefaultFormattingConversionService: 기본 컨버터 및 포매터 등록
  • 개발자가 필요에 따라 커스텀 Converter 등록 가능

7. Converter 적용 (실습)

Converter 적용

  1. Spring은 내부적으로 ConversionService를 제공한다.
  2. WebMvcConfigurer가 제공하는 addFomatters() 를 사용하여 Converter를 등록하면 된다.
  3. 클라이언트 측에서 컨버터를 사용하면 된다.

 

WebConfig

@Configuration
public class WebConfig implements WebMvcConfigurer {
	
    @Override
    public void addFomatters(FormatterRegistry registry) {
        // registry.addConverter(new "${등록할 Converter}");
        registry.addConverter(new StringToPersonConverter());
        registry.addConverter(new PersonToStringConverter());
    }
}

 

* StringToIntegerConverter와 같이 Spring이 기본적으로 제공하는 컨버터들이 존재하지만, 개발자가 StringToIntegerConverter 를 따로 커스텀하게 구현하여 컨버터로 추가하면 추가한 컨버터가 기본 제공된 컨버터보다 높은 우선순위를 가진다.

 

 

TypeConverterController

@Slf4j
@RestController
public class TypeConverterController {

    @GetMapping("/type-converter")
    public void typeConverter(@RequestParam Person person) {
        log.info("person.getName() = {}", person.getName());
        log.info("person.getAge() = {}", person.getAge());
    }

}

 

 

Argument Resolver

  • @RequestParam 을 처리하는 RequestParamMethodArgumentResolver 에서 ConversionService 를 사용하여 타입을 변환한다.
  • 내부적으로 굉장히 복잡하게 메서드들이 호출되기 때문에 그림으로 이해하면 된다.


8. Formatter

Formatter

  • 문자열과 특정 객체 타입 간 변환을 처리하는 포매터 인터페이스
  • 보통 Converter보다 더 복잡한 형식 변환이나 포맷팅(형식화)에 사용된다.

 

역할

 

  • 문자열 → 객체, 객체 → 문자열 양방향 변환 지원
  • 날짜, 숫자, 사용자 정의 타입 등 복잡한 형식 변환 처리
  • toString(), valueOf() 이상의 맞춤형 포맷팅 가능

 

주요 인터페이스

public interface Formatter<T> {
    T parse(String text, Locale locale);  // 문자열 → 객체
    String print(T object, Locale locale); // 객체 → 문자열
}

 

 

 

적용 방법

  • 스프링 설정 시 FormattingConversionService에 Formatter를 등록
  • @InitBinder 메서드에서 특정 필드에 Formatter 적용 가능
  • 폼 바인딩, 요청 파라미터 변환 시 자동으로 적용됨

 

장점

  • 국제화(Locale) 지원 가능
  • 일관된 포맷팅 정책 관리
  • 복잡한 타입 변환을 깔끔하게 처리 가능

9. Spring Formatter

FormattingConversionService

 

  • 스프링에서 Formatter와 Converter를 모두 지원하는 통합 타입 변환 서비스
  • FormattingConversionService는 ConversionService의 확장판으로, Formatter를 등록하고 관리한다.
  • 기본적으로 날짜, 숫자 포맷터 등이 내장되어 있으며, 커스텀 Formatter도 추가 가능하다.

 

Spring이 제공하는 Formatter

 

  • DateFormatter: 날짜 타입을 문자열로 포맷팅하고 역변환 처리
  • NumberFormatter: 숫자 타입 포맷팅
  • CurrencyFormatter: 통화 포맷팅
  • PercentFormatter: 퍼센트 포맷팅
  • 기타 국제화(Locale) 지원을 위한 다양한 포맷터 기본 제공