Spring #13 - Converter와 Formatter

업데이트:

데이터 바인딩

데이터 바인딩 추상화 : Converter와 Formatter

서론

  • Spring MVC에서 아래와 같이 웹 컨트롤러 단에서 Stirng으로 들어오는 값이 어떻게 Event로 바인딩 될까?

    @RestController
    public class EventController {
      
        @GetMapping("/event/{event}")
        public String getEvent(@PathVariable Event event) {
            System.out.println(event);
            return event.getId().toString();
        }
    }
    
  • 내부적으로 데이터 바인딩이 있고, Converter, Formatter, PropertyEditor로 변환이 된다.

Converter

  • S (source) 타입을 T (target) 타입으로 변환할 수 있는 매우 일반적인 변환기이다.

  • 이전의 PropertyEditor와 다르게 Stateless하여 Thred Safe하다. 그러므로 빈으로 등록해서 사용해도 괜찮다.

  • Controller단에서 데이터를 받을 때 Integer, long 타입과 같이 Spring에 기본적으로 등록되어 있는 것들은 그냥 사용하면 된다. 하지만 스프링에 있지 타입 Convert의 경우에는 아래와 같이 커스텀으로 만들 수 있다.

    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();
            }
        }
    }
    
  • SpringBoot가 아닌 Spring MVC에서는 ConverterRegistry에 등록해서 사용한다.

Formatter

  • PropertyEditor의 대체제이며, ObjectString의 변환을 담당한다.

  • 문자열을 Locale에 따라 다국화하는 기능도 제공한다.

  • 웹 애플리케이션에서는 Converter보다 Formatter사용을 권장한다.

    @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();
        }
    }
    

ConversionService

  • SpringBootFomatterConverter가 빈으로 등록되어 있다면 따로 WebConfig 설정 없이 자동으로 찾아서 등록해준다.

  • 웹 애플리케이션인 경우에 DefaultFormattingConversionSerivce를 상속하여 만든

    WebConversionService를 빈으로 등록해 준다.

WebMvcTest

  • @WebMvcTest : 계층형 테스트로 웹과 관련된 빈만 등록을 해주는 테스트이다.

  • 주로 컨트롤러만 등록이 되어 사용하는데, ConverterFormatter의 경우 빈으로 제대로 등록이 안되면 테스트가 깨질 수 있다.

  • 테스트에 필요한 클래스를 아래와 같이 빈으로 명시적으로 등록하여 사용할 수 있다.

    @ExtendWith(SpringExtension.class)
    @WebMvcTest({EventFormatter.class, EventController.class,
        EventConverter.StringToEventConverter.class})
    class EventControllerTest {
      
        @Autowired
        MockMvc mockMvc;
      
        @Test
        public void getTest() throws Exception {
            mockMvc.perform(get("/event/1"))
                .andExpect(status().isOk())
                .andExpect(content().string("1"));
        }
    }
    

댓글남기기