| Converter와 Formatter
PropertyEditor는 스프링 초창기에 썼던 데이터 바인딩 인터페이스였지만 후에 이를 대체할 Converter와 Formatter란 데이터 바인딩 인터페이스가 나오게 되었다.
Converter는 S타입을 T 타입으로 변환할 수 있는 일반적인 변환기이며 Thread-safe하다. Formatter는 Object와 String간의 변환을 담당하며 문자열을 Locale에 따라 다국화하는 기능을 제공한다. 웹 어플리케이션을 제작할 때는 주로 Formatter를 사용한다.
| Converter 구현
Converter는 제네릭으로 두 개의 인자, Source와 Target을 받아서 구현한다. 또한 Converter는 PropertyEditor와는 다르게 Thread-safe하기 때문에 스프링 빈으로 등록해서 사용 가능하다.
public class EventConverter {
public static class StringToEventConverter implements Converter<String, Event> {
@Override
public Event convert(String source){
return new Event(Integer.parseInt(source));
}
}
public static class EventToStringConverter implements Converter<Event, String>{
@Override
public String convert(Event source){
return source.getId().toString();
}
}
}
위에서 작성했던 Converter를 등록하려면 스프링MVC에서는 WebMvcConfigurer 인터페이스를 구현한 클래스를 작성해야 한다. WebMvcConfigurer 인터페이스의 addFormatters 메서드를 오버라이딩하여 Converter를 등록할 수 있다.
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new EventConverter.StringToEventConverter());
}
}
| Formatter 구현
Formatter는 제네릭으로 한 개의 인자만을 받는다. 왜냐하면 Object와 String간의 변환을 담당하기 때문에 다른 하나의 인자는 String으로 정해져 있기 때문이다.
public class EventFormatter implements Formatter<Event> {
@Override
public Event parse(String text, Locale locale) throws ParseException {
return new Event(Integer.parseInt(text));
}
@Override
public String print(Event object, Locale locale) {
return object.getId().toString();
}
}
Converter와 마찬가지로 WebMvcConfigurer 인터페이스를 구현한 클래스에 Formatter를 등록할 수 있다.
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatter(new EventFormatter());
}
}
| ConversionService
Converter와 Formatter 이 두 데이터 바인딩 인터페이스는 위에서 WebMvcConfigurer의 메서드를 통해 ConversionService에 등록된다. ConversionService는 실제 데이터 변환이 일어나는 곳이며 이 ConversionService를 통해 데이터 바인딩이 일어나게 된다. 참고로 스프링 부트에서는 ConversionService는 WebConversionService 스프링 빈으로 자동 주입된다. (WebConversionService는 DefaultFormattingConversionService를 상속받은 클래스)
@Component
public class AppRunner implements ApplicationRunner {
@Autowired
ConversionService conversionService;
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println(conversionService.getClass().toString());
}
}
class org.springframework.boot.autoconfigure.web.format.WebConversionService
| WebConversionService
스프링 부트가 제공하는 클래스인 WebConversionService는 Formatter와 Converter를 자동으로 등록해준다. 따라서 위에 Converter와 Formatter를 등록하기 위해 만들었던 WebMvcConfigurer를 작성할 필요가 없다. (즉, Formatter와 Converter를 스프링 빈으로 등록하면 자동적으로 ConversionService에 등록되게 된다)
@Component
public class EventFormatter implements Formatter<Event> {
@Override
public Event parse(String text, Locale locale) throws ParseException {
return new Event(Integer.parseInt(text));
}
@Override
public String print(Event object, Locale locale) {
return object.getId().toString();
}
}
public class EventConverter {
@Component
public static class StringToEventConverter implements Converter<String, Event> {
@Override
public Event convert(String source){
return new Event(Integer.parseInt(source));
}
}
@Component
public static class EventToStringConverter implements Converter<Event, String>{
@Override
public String convert(Event source){
return source.getId().toString();
}
}
}
@RestController
public class EventController {
@GetMapping("/event/{event}")
public String getEvent(@PathVariable Event event){
System.out.println(event);
return event.getId().toString();
}
}
아래의 테스트는 EventFormatter를 스프링 빈으로 등록하여 테스트를 진행하는 코드다. 위에서 언급했던 코드를 정상적으로 작성했다면 아래 테스트를 무리없이 통과할 수 있을 것이다.
@RunWith(SpringRunner.class)
@WebMvcTest({EventFormatter.class, EventController.class})
public class EventControllerTest {
@Autowired
MockMvc mockMvc;
@Test
public void getTest() throws Exception {
mockMvc.perform(get("/event/1"))
.andExpect(status().isOk())
.andExpect(content().string("1"));
}
}
'Spring > Spring 입문 - 개념 및 핵심' 카테고리의 다른 글
이 글을 공유하기