-
Spring MVC - Formatter 구현 및 사용 ( Formatter와 FormattingConversionService )Spring/Spring MVC 2022. 2. 17. 11:48728x90반응형
스프링에 Formatter 적용하기
Formatter
Formatter는 문자에 특화된 타입 변환 Converter의 특별한 버전이다. 객체와 문자, 문자와 객체의 타입 변환시 특정 포멧으로 Locale 정보에 따라 문자를 출력하거나 또는 그 반대의 역할을 하는 특화된 기능이 포함된 인터페이스이다.
Converter는 타입 변환이 범용적으로 쓰이는 타입 변환기라고 볼 수 있으며 Formatter는 문자에 특화된 타입 변환기라고 볼 수 있다.
ex) 날짜 객체 -> 2022-03-02 16:14:00
참고
@RequestParam, @ModelAttribute, @PathVariable 등에서 사용 가능
메시지 컨버터(JSON)에는 컨버전 서비스가 적용되지 않는다.Formatter 인터페이스
- Formatter 인터페이스는 Printer 인터페이스와 Parser 인터페이스를 상속 받는다.
- Printer<T>
- 객체를 문자로 변경하는 역할 - Parser<T>
- 문자를 객체로 변경하는 역할
@FunctionalInterface public interface Printer<T> { String print(T object, Locale locale); } @FunctionalInterface public interface Parser<T> { T parse(String text, Locale locale) throws ParseException; } public interface Formatter<T> extends Printer<T>, Parser<T> { }
Formatter 구현
간단하게 1000 단위로 쉼표가 들어가는 포맷이 적용되는 포맷터를 구현해보자.
@Slf4j public class MyNumberOfFormatter implements Formatter<Number> { @Override public Number parse(String text, Locale locale) throws ParseException { log.info("text={}, locale={}", text, locale); NumberFormat format = NumberFormat.getInstance(locale); return format.parse(text); } @Override public String print(Number object, Locale locale) { log.info("object={}, locale={}", object, locale); NumberFormat instance = NumberFormat.getInstance(locale); String format = instance.format(object); return format; } }
위에서 구현한 포맷터를 테스트를 해보면 타입 변환과 포맷이 잘 이루어진 것을 볼 수 있다.
@Test void parse() throws ParseException { MyNumberOfFormatter formatter = new MyNumberOfFormatter(); Number result = formatter.parse("1,000", Locale.KOREA); Assertions.assertThat(result).isEqualTo(1000L); } @Test void print() { MyNumberOfFormatter formatter = new MyNumberOfFormatter(); String result = formatter.print(1000, Locale.KOREA); Assertions.assertThat(result).isEqualTo("1,000"); }
FormattingConversionService
포맷터 역시 여러 포맷터가 있을 경우 관리 및 사용이 불편하기 때문에 스프링에서 포맷터를 모아서 편리하게 사용할 수 있는 기능을 제공하는데 그것이 바로 FormattingConversionService 이다.
포맷터도 타입 변환 기능에 포맷 기능이 추가된 특별한 컨버터 이므로 FormattingConversionService 내부를 보면 ConversionService을 구현하고 있다는 것을 알 수 있다.
DefaultFormattingConversionService 사용
- 컨버터 등록 및 사용과 포맷터 등록 및 사용 모두 구현한 클래스
- addConverter()
- 컨버터와 포맷터 등록 - convert()
- 컨버터와 포맷터 사용
위에서 예시로 만든 포맷터를 등록하고 사용하는 테스트 코드를 구현해보자.
public class ConversionServiceTest { @Test void conversionService(){ // 컨버전 등록 DefaultConversionService conversion = new DefaultConversionService(); conversion.addConverter(new StringToIntegerConverter()); conversion.addConverter(new StringToIpPortConverter()); conversion.addConverter(new StringToIpPortConverter()); conversion.addConverter(new IpPortToStringConverter()); // 컨버전 사용 Assertions.assertThat(conversion.convert("10", Integer.class)).isEqualTo(10); Assertions.assertThat(conversion.convert(10, String.class)).isEqualTo("10"); IpPort ipPort = conversion.convert("127.1.2.3:8080", IpPort.class); Assertions.assertThat(ipPort).isEqualTo(new IpPort("127.1.2.3", 8080)); String ipPortString = conversion.convert(new IpPort("127.0.0.1", 8080), String.class); Assertions.assertThat(ipPortString).isEqualTo("127.0.0.1:8080"); } }
DefaultFormattingConversionService 를 이용하면 컨버터뿐만아니라 포맷터까지 등록 및 사용이 가능하다는 것을 알 수 있다. 아래는 DefaultFormattingConversionService 의 상속 구조이다.
스프링에 Formatter 등록하고 사용하기
Formatter 등록
- Formatter를 등록하기 위해서는 WebMvcConfigurer가 제공하는 addFormatters()메서드를
사용하여 Formatter를 등록할 수 있다. - addFormatters(FormatterRegistry registry)
- FormatterRegistry : 인터페이스 ConveterRegistry의 구현 클래스 - 참고로 위에서 만든 컨버터(String→Integer)를 등록하면 기본 컨버터가 아닌
등록한 컨버터가 호출된다.
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addFormatters(FormatterRegistry registry) { registry.addConverter(new IpPortToStringConverter()); registry.addFormatter(new MyNumberOfFormatter()); } }
등록한 Formatter 사용
위에서 만든 포맷터인 MyNumberOfFormatter를 사용해보자.
@GetMapping("/converter") public String converterV1(@RequestParam Integer data){ log.info("data = {}", data); return "ok"; }
/converter?data=10,000 요청시 전달된 파라미터 문자열이 포맷이 적용된 타입 변환이 잘 이루어진 것을 볼 수있다.
스프링이 제공하는 기본 Formatter
포맷터는 기본형식이 지정되어 있기 때문에, 객체의 각 필드마다 다른 형식으로 포맷을 지정하기는 어렵다. 스프링에서는 이런 문제를 해결하기 위해 애노테이션 기반으로 원하는 형식을 지정해서 사용할 수 있는 매우 유용한 포맷터 두 가지를 기본으로 제공한다
- @NumberFormat : 숫자 관련 형식 지정 포맷터 사용
- @DateTimeFormat : 날짜 관련 형식 지정 포맷터 사용
@Data static class Form { @NumberFormat(pattern = "###,###") private Integer number; @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime localDateTime; }
해당 클래스 필드에 넘어온 값이 바인딩 될 때 각 필드에 지정된 포맷애노테이션에 따라 포맷터가 적용이 된다.
728x90반응형'Spring > Spring MVC' 카테고리의 다른 글
Spring MVC - Spring에서 제공하는 MultipartFile을 이용한 파일 업로드 (0) 2022.02.17 Spring MVC - Servlet의 파일 업로드 (0) 2022.02.17 Spring MVC - Converter 구현 및 사용 (Converter와 ConversionService) (0) 2022.02.17 String MVC - API 예외처리(ExceptionHandlerExceptionResolver, ResponseStatusExceptionResolver, DeFaultHandlerExceptionResolver) (0) 2022.02.14 String MVC - 직접 구현해보는 API 예외처리 (0) 2022.02.14