스프링 부트가 자동 설정을 지원하기 때문에 메이븐이나 그래들로 의존성만 추가해도 손쉽게 특정 기능을 아무런 설정없이 추가할 수 있습니다. 이런걸 보통 CoC, Convention over Configuration이라고 부르죠. 예전에 루비 온 레일즈가 스캐폴드 (기본 코드 및 디렉토리 자동완성) 기능으로 인기를 끌 때 부상했던 개념입니다. 모든 설정을 일일히 직접하도록 강요하기 보다는  센스있는 기본 값을 규약으로 제공해서 설정을 줄이고 개발 편의성과 속도도 증진시키자는 개념인데 그만한 장점에는 그런 규약을 이해하고 학습해야 하는 단점도 따르긴 하죠.

어쨌든 사설이 길었지만, 비슷하게 스프링 부트에서는 스프링 웹 MVC 설정을 하지 않아도 포매터를 등록하는 방법이 매우 간단합니다. 빈으로 등록만 하면 바로 쓸 수 있죠. Formatter는 문자열을 주고 받는 웹에 특화된 컨버터라고 생각할 수도 있는데, 어떤 객체 타입든 문자열로 변환하고, 또 어떤 문자열이든 특정한 객체 타입으로 변환하는 방법을 제공하는 객체라고 간단히 정리할 수 있습니다.

포매터는 매번 웹 요청에서 받아온 문자열을 특정한 객체 타입으로 변환하는 일을 자동화하고 싶을 때 쓸 수 있습니다. 가령, /book/keesun 이라는 요청이 왔을 때 keesun을 책 이름으로 가지고 있는 Book 객체로 요청을 받고 싶다면 다음과 같은 핸들러를 정의할 수 있겠죠.

@GetMapping("/book/{book}")
public Book getBook(Book book) {
    return book;
}

그리고 실제로 요청을 보내서 응답을 보면 title이 비어있는걸 볼 수 있습니다.

{
"title": null
}

제대로 바인딩을 받지 못한거죠.

포매터는 Foramtter<T> 를 구현하는 클래스를 만들면 되고, 빈으로 등록만 하면 스프링 부트를 쓸 때에는 별다른 설정없이 스프링 MVC에 설정이 됩니다. 따라서 별다른 웹 MVC 설정 없이도 포매터가 동작하는 것을 확인할 수 있습니다.

package me.whiteship.formatter;

import org.springframework.format.Formatter;
import org.springframework.stereotype.Component;

import java.text.ParseException;
import java.util.Locale;

@Component
public class BookFormatter implements Formatter<Book> {

    @Override
    public Book parse(String s, Locale locale) throws ParseException {
        Book book = new Book();
        book.setTitle(s);
        return book;
    }

    @Override
    public String print(Book book, Locale locale) {
        return book.getTitle();
    }
}
{
"title": "keesun"
}

그런데 사실 이렇게만 받을 거라면 굳이 포매터를 만들지 않고도 받을 수가 있는데...

@GetMapping("/book/{title}")
public Book getBook(Book book) {
    System.out.println(conversionService.getClass());
    return book;
}

이렇게 GetMapping에서 path variable 이름을 해당 클래스 타입의 특정 프로퍼티 이름으로 받는다면, 커스텀한 포매터를 만들지 않아도 기본으로 등록되어 있는 JavaBean 스팩(게터, 세터)을 따르는 컨버터를 통해서 Book 객체에 title로 받아올 수도 있습니다.

스프링 부트 개념과 활용 - 인프런
스프링 부트의 원리 및 여러 기능을 코딩을 통해 쉽게 이해하고 보다 적극적으로 사용할 수 있는 방법을 학습합니다.