스프링/스프링 MVC 패턴

포맷터 - Formatter

chanhee01 2023. 3. 7. 17:12

보통 문자 -> 다른 타입 혹은 다른 타입 -> 문자의 변환을 많이 사용한다.

스프링에서는 포맷터라는 문자의 자동 변환 기능을 제공한다.

 

 

MyNumberFormatter.class

@Slf4j
public class MyNumberFormatter implements Formatter<Number> {

    // Number는 integer, double, long 등 숫자 형태 타입의 부모
    @Override
    public Number parse(String text, Locale locale) throws ParseException {
        log.info("text={}, locale={}", text, locale);
        // "1,000" -> 1000
        NumberFormat format = NumberFormat.getInstance(locale);
        Number parse = format.parse(text);
        return parse;
    }

    @Override
    public String print(Number object, Locale locale) {
        log.info("object={}, locale={}", object, locale);
        NumberFormat instance = NumberFormat.getInstance(locale);
        String format = instance.format(object);
        return format;
    }
}

Formatter을 implements를 한 구현체에서 parse와 print 2가지의 메서드를 구현할 수 있다.

변환을 할 객체의 타입과 Locale을 파라미터로 갖는다.

NumberFormate으로 locale의 instance를 받아오고, parse는 parse를, print는 format을 이용해서 객체 타입을 바꾼 다음에 return 해주면 된다.

 

 

포맷터의 적용

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new StringToIpPortConverter());
        // registry.addConverter(new StringToIntegerConverter());
        registry.addConverter(new IpPortToStringConverter());
        // registry.addConverter(new IntegerToStringConverter());

        // 포맷터 추가
        registry.addFormatter(new MyNumberFormatter());
    }
}

WebConfig에 registry.addFormatter(new MyNumberFormatter());를 이용해 포맷터를 추가해주었다.

이전에 해줬던 addConverter의 주석 2개는 우선순위때문에 주석처리 해 준 것이다.

 

 

 

localhost:8080/hello-v2?data=10,000 로 파라미터를 넘겨주면

@GetMapping("/hello-v2") // 이전에 만들었던 매핑 메서드
public String helloV2(@RequestParam Integer data) {
    System.out.println("data = " + data);
    return "ok";
}

2023-03-07T16:56:47.403+09:00  INFO 4988 --- [nio-8080-exec-5] h.t.formatter.MyNumberFormatter          : text=10,000, locale=ko
data = 10000

라는 로그가 찍힌다.

data로 들어올 때 문자가 아닌 integer 타입으로 들어온 것을 확인할 수 있었다.

 

 

 

스프링에서 제공하는 기본 포맷터

@NumberFormat : 숫자 관련 형식 지정 포맷터 사용
@DateTimeFormat : 날짜 관련 형식 지정 포맷터 사용

 

@Controller
public class FormatterController {

    @GetMapping("/formatter/edit")
    public String formatterForm(Model model) {
        Form form = new Form();
        form.setNumber(10000);
        form.setLocalDateTime(LocalDateTime.now());
        model.addAttribute("form", form);
        return "formatter-form.html";
    }

    @PostMapping("/formatter/edit")
    public String formatterEdit(@ModelAttribute Form form) {
        return "formatter-view";
    }

    @Data
    static class Form {
        @NumberFormat(pattern = "###,###")
        private Integer number;

        @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        private LocalDateTime localDateTime;
    }
}

포맷터를 사용하는 클래스이다. Form이라는 객체를 만들고 @NumberFormat, @DateTimeFormat 애노테이션을 사용하고 패턴을 지정해주면 해당 형태로 타입을 변환시켜준다.

 

 

formatter-view.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<ul>
    <li>${form.number}: <span th:text="${form.number}" ></span></li>
    <li>${{form.number}}: <span th:text="${{form.number}}" ></span></li>
    <li>${form.localDateTime}: <span th:text="${form.localDateTime}" ></span></li>
    <li>${{form.localDateTime}}: <span th:text="${{form.localDateTime}}" ></span></li>
</ul>
</body>
</html>

 

타입변환이 자동으로 잘 이루어진다.

 

나중에 타입 변환이 필요해서 컨버터를 사용해야할 때가 있을텐데 직접 만들어서 하기에는 번거로우니까 스프링에서 제공하는 포맷터를 사용하면 효율적으로 개발을 할 수 있을 것이라 생각된다.