문자를 숫자로 변환하거나, 반대로 숫자를 문자로 변환해야 하는 것 처럼 애플리케이션을 개발하다 보면
타입을 변환해야 하는 경우가 상당히 많다.
data=10
부분에서 10은 숫자 10이 아니라 문자 10이다. 스프링이 제공하는 @RequestParam
을 사용하면 이 문자 10을 Integer
타입의 숫자 10으로 편리하게 받을 수 있다.@RequestParam
,@ModelAttribute
, @PathVariable
@Value
등으로 YML 정보 읽기public interface Converter<S, T> {
T convert(S source);
}
"true"
가 오면 Boolean
타입으로 받고 싶으면 String
Boolean
타입으로 변환되도록 컨버터 인터페이스를 만들어서 등록하고, 반대로 적용하고 싶으면 Boolean
String
타입으로 변환되도록 컨버터를 추가로 만들어서 등록하면 된다.참고: 롬복의
@EqualsAndHashCode
를 넣으면 모든 필드를 사용해서equals()
,hashcode()
를 생성한다. 따라서 모든 필드의 값이 같다면a.equals(b)
의 결과가 참이 된다.
ConversionService
)이다.StringToIntegerConverter
같은 타입 컨버터를 명확하게 알아야 한다. 반면에 컨버터를 사용하는 입장에서는 타입 컨버터를 전혀 몰라도 된다. 타입 컨버터들은 모두 컨버전 서비스 내부에 숨어서 제공된다.Integer value = conversionService.convert("10", Integer.class)
인터페이스 분리 원칙 - ISP(Interface Segregation Principle)
인터페이스 분리 원칙은 클라이언트가 자신이 이용하지 않는 메서드에 의존하지 않아야 한다.
DefaultConversionService
는 다음 두 인터페이스를 구현했다.ConversionService
: 컨버터 사용에 초점ConverterRegistry
: 컨버터 등록에 초점 ConversionService
만 의존하면 되므로, 컨버터를 어떻게 등록하고 관리하는지는 전혀 몰라도 된다.ISP
라 한다.<ul>
<li>${number}: <span th:text="${number}" ></span></li>
<li>${{number}}: <span th:text="${{number}}" ></span></li>
<li>${ipPort}: <span th:text="${ipPort}" ></span></li>
<li>${{ipPort}}: <span th:text="${{ipPort}}" ></span></li>
</ul>
${{...}}
를 사용하면 자동으로 컨버전 서비스를 사용해서 변환된 결과를 출력해준다. 물론 스프링과 통합 되어서 스프링이 제공하는 컨버전 서비스를 사용하므로, 우리가 등록한 컨버터들을 사용할 수 있다.${...}
${{...}}
th:field
는 앞서 설명했듯이 id
, name
를 출력하는 등 다양한 기능이 있는데, 여기에 컨버전 서비스도 함께 적용된다.th:field
가 자동으로 컨버전 서비스를 적용해주어서 ${{ipPort}}
처럼 적용이 되었다. 따라서IpPort
-> String
으로 변환된다.Converter
는 입력과 출력 타입에 제한이 없는, 범용 타입 변환 기능을 제공한다.Formatter
)이다. 포맷터는 컨버터의 특별한 버전으로 이해하면 된다.FormattingConversionService
는 포맷터를 지원하는 컨버전 서비스이다. DefaultFormattingConversionService
는 FormattingConversionService
에 기본적인 통화, 숫자 관련 몇가지 기본 포맷터를 추가해서 제공한다.@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
//주석처리 우선순위
//registry.addConverter(new StringToIntegerConverter());
//registry.addConverter(new IntegerToStringConverter());
registry.addConverter(new StringToIpPortConverter());
registry.addConverter(new IpPortToStringConverter());
//추가
registry.addFormatter(new MyNumberFormatter());
}
}
@NumberFormat
: 숫자 관련 형식 지정 포맷터 사용, NumberFormatAnnotationFormatterFactory
@DateTimeFormat
: 날짜 관련 형식 지정 포맷터 사용, Jsr310DateTimeFormatAnnotationFormatterFactory
@Data
static class Form {
@NumberFormat(pattern = "###,###")
private Integer number;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime localDateTime;
}
주의!
메시지 컨버터(HttpMessageConverter
)에는 컨버전 서비스가 적용되지 않는다.
특히 객체를 JSON으로 변환할 때 메시지 컨버터를 사용하면서 이 부분을 많이 오해하는데,HttpMessageConverter
의 역할은 HTTP 메시지 바디의 내용을 객체로 변환하거나 객체를 HTTP 메시지
바디에 입력하는 것이다. 예를 들어서 JSON을 객체로 변환하는 메시지 컨버터는 내부에서 Jackson 같은
라이브러리를 사용한다. 객체를 JSON으로 변환한다면 그 결과는 이 라이브러리에 달린 것이다. 따라서
JSON 결과로 만들어지는 숫자나 날짜 포맷을 변경하고 싶으면 해당 라이브러리가 제공하는 설정을 통해서
포맷을 지정해야 한다. 결과적으로 이것은 컨버전 서비스와 전혀 관계가 없다.
컨버전 서비스는@RequestParam
,@ModelAttribute
,@PathVariable
, 뷰 템플릿 등에서 사용할 수
있다.