[Spring] 스프링 Converter와 Formatter를 이용한 데이터 바인딩(Converter, Formatter : Spring Data Binding)

2021. 3. 8. 01:26 Spring Framework/Spring 입문 - 개념 및 핵심

| 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"));
    }
}



출처: https://engkimbs.tistory.com/738?category=767795 [새로비]