데이터 바인딩 추상화 - Converter와 Formatter
참고문헌
Converter
- S 타입을 T 타입으로 변환할 수 있는 매우 일반적인 변환기
 - 상태 정보 없음
    
- == Stateless
 - == Thread-safe (쓰레드-세이프하다)
 
 - ConverterRegistry에 등록해서 사용
    
- @Configuration 자바파일에서 WebConversionService의 addConverter를 사용하면 등록됨
 - addConverter 메서드 -> ConversionService에 등록 -> ConversionService에서 실제 변환 작업
 
 
Formatter
- PropertyEditor의 대체재
 - Object와 String 간의 변환을 담당한다.
 - 문자열을 Locale에 따라 다국화하는 기능도 제공한다 (optional)
 - FormatterRegistry에 등록해서 사용
    
- @Configuration 자바파일에서 WebConversionService의 addFormatter를 사용하면 등록
 - addFormatter를 메서드 -> ConversionService에 등록 -> ConversionService에서 실제 변환 작업
 
 
ConversionService
- 실제 변환 작업은 이 인터페이스를 통해 쓰레드-세이프하게 사용할 수 있음
 - 스프링 MVC, 빈(value) 설정, SpEL에서 사용함
 - DefaultFormattingConversionService 클래스가 주로 사용됨
    
- FormatterRegistry 기능도 하고 (이 인터페이스를 ConversionService가 구현했음)
 - ConversionService 기능도 함 (이 인터페이스를 ConversionService가 구현했음)
 - 여러 기본 Converter와 Formatter를 등록해줌.
 
 
구조

- 
    
ConverterRegistry는 FormatterRegistry를 상속받고 있음
 - 
    
스프링 부트
- 웹 애플리케이션인 경우에 DefaultFormattingConversionSerivce를 상속하여 만든 WebConversionService를 빈으로 등록해 준다.
        
 - Formatter와 Converter 빈을 찾아 자동으로 등록해 준다.
        
- Formatter와 Converter는 쓰레드-세이프하므로, 빈으로 등록해서 사용해도 된다.
 

 - 테스트
        
- @WebMvcTest를 붙이면, Web에 필요한 빈만 가져온다. (주로 Controller들)
 - 가져올 클래스를 명시해주면 해당 클래스 빈들도 가져온다.
 

 
 - 웹 애플리케이션인 경우에 DefaultFormattingConversionSerivce를 상속하여 만든 WebConversionService를 빈으로 등록해 준다.
        
 
예시
Converter
EventConverter.java
public class EventConverter {
    public static class StringToEventConverter implements Converter<String, Event> {
        @Override
        public Event convert(String source) {
            Event event = new Event();
            event.setId(Integer.parseInt(source));
            return event;
        }
    }
        public static class EventToString implements Converter<Event, String> {
        @Override
        public String convert(Event source) {
            return source.getId().toString();
        }
    }
}
WebConfig.java
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new EventConverter.StringToEventConverter());
    }
}
EventControllerTest.java
@RunWith(SpringRunner.class)
@WebMvcTest
public class EventControllerTest {
    @Autowired
    MockMvc mockMvc;
    @Test
    public void getTest() {
        mockMvc.perform(get("/event/1"))
                .andExpect(status.isOk())
                .andExpect(content().string("1"));
    }
}
Formatter
EventFormatter.java
public class EventFormatter implements Formatter<Event> {
    @Override
    public Event parse(String text, Locale locale) throws ParseException {
        Event event = new Event();
        int id = Integer.parseInt(text);
        event.setId(id);
        return event;
    }
    @Override
    public String print(Event object, Locale locale) {
         return object.getId().toString();
    }
}
WebConfig.java
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addFormatter(new EventFormatter());
    }
}
첨언
- 일반적인 경우 : Formatter 사용을 추천함
 - JPA를 사용한다면 : @Entity 안에 이미 Converter가 있음
 - 앱에서 쓰이고 있는 Converter, Formatter 목록 보려면 : conversionService를 출력하면 됨
    
 

