웹 어플리케이션에서 객체를 문자로, 문자를 개체로 변환하는 예
Integer
-> String
출력 시점에 1000 -> "1,000" 이렇게 쉼표를 넣거나, 반대로 "1,000" -> 1000 와 같이 변경해야 할 때가 많다.Locale
여기에 추가로 날짜 숫자의 표현 방법은 Locale
현지화 정보가 사용될 수 있다.
이렇게 객체를 특정한 포맷에 맞추어 문자로 출력하거나 또는 그 반대의 역할을 하는 것에 특화된 기능이 포멧터(Formatter
)이다.
Converter vs Formatter
Converter
는 범용(객체 -> 객체)Formatter
는 문자에 특화(객체 -> 문자, 문자 -> 객체) + 현지화(Locale
)포맷터는 객체를 문자로 변경하고, 문자를 객체로 변경하는 두 가지 기능 모두 수행한다.
String print(T object, Locale locale)
: 객체를 문자로 변경한다.
T parse(String text, Locale locale)
: 문자를 객체로 변경한다.
"1,000" 처럼 숫자 중간에 쉼표를 찍으려면 자바가 기본으로 제공하는 NumberFormatter
객체를 사용하면 된다.
이 객체는 Locale
정보를 활용해서 나라별로 다른 숫자 포맷을 만들어준다.
parse()
를 사용해서 문자를 숫자로 변환한다. 참고로 Number
타입은 Integer
, Long
과 같은 숫자 타입의 부모 클래스이다.
print()
를 사용해서 객체를 문자로 변환한다.
테스트를 해보면 이와 같이 출력되는 것을 확인할 수 있다.
formatter에 대한 자세한건 여기
https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#format
컨버전 서비스는 컨버터만 등록할 수 있고, 포맷터를 등록할 수는 없다. 그런데 생각해보면 포맷터는 객체 -> 문자, 문자 -> 객체로 변환하는 특별한 컨버터일 뿐이다.
포맷터를 지원하는 컨버전 서비스를 사용하면 컨버전 서비스에 포맷터를 추가할 수 있다. 내부에서 어댑터 패턴을 사용해서 Formatter
가 Converter
처럼 동작하도록 지원한다.
DefaultFormattingConversionService 상속 관계
FormattingConversionService 상속 관계
는 ConversionService
관련 기능을 상속받기 때문에 결과적으로 컨버터도 포맷터도 모두 등록할 수 있다.
먼저 우선순위가 높은 Converter를 주석처리해줘야한다.
그 후에 포맷터를 추가한다.
그럼 이와 같이 컨버터가 적용되는 것을 확인할 수 있다.
포맷터 인터페이스의 구현 클래스는 저암ㄹ 많은 종류의 포맷터가 제공되는 것을 알 수 있다.
그런데 포맷터는 기본 형식이 지정되어 있기 때문에, 객체의 각 필드마다 다른 형식으로 포맷을 지정하기는 어렵다.
이를 해결하기 위한 어노테이션!
@NumberFormat
: 숫자 관련 형식 지정 포맷터 사용
@DataTimeFormat
: 날짜 관련 형식 지정 포맷터 사용
@NumberFormat
, @DateTimeFormat
과 관련된 자세한 내용
https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#format-CustomFormatAnnotations