Updated:

1. 개요

개발을 하다보면, 문자를 숫자로 또는 숫자를 문자로 변경하는 경우와 같이 타입을 변경해야 하는 경우가 많이 생긴다. 스프링은 Type Converter를 통해 자동으로 타입을 변경해주고, 새로운 타입을 만들어서 자동으로 변환되도록 추가할 수도 있다. 이번에는 스프링에서 Type Converter를 통해 자동으로 타입을 변경하는 방법에 대해 알아보도록 하자.

2. 개발 환경

  • Java 11

  • Spring Boot 2.7.5

3. Type Converter

스프링은 Converter라는 인터페이스를 제공하는데, 해당 인터페이스를 구현하여 다양한 컨버터를 만들 수 있다. 또한 스프링은 Conversion Service를 통해 여러 컨버터들을 모아서 편리하게 사용할 수 있도록 기능을 제공한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package org.springframework.core.convert.converter;

@FunctionalInterface
public interface Converter<S, T> {

	@Nullable
	T convert(S source);

	default <U> Converter<S, U> andThen(Converter<? super T, ? extends U> after) {
		Assert.notNull(after, "After Converter must not be null");
		return (S s) -> {
			T initialResult = convert(s);
			return (initialResult != null ? after.convert(initialResult) : null);
		};
	}
}

3-1. 예제 코드

[StringToIpPortConverter.java]

1
2
3
4
5
6
7
8
9
10
11
12
13
@Slf4j
public class StringToIpPortConverter implements Converter<String, IpPort> {

    @Override
    public IpPort convert(String source) {
        log.info("convert source={}", source);
        // "127.0.0.1:8080"
        String[] split = source.split(":");
        String ip = split[0];
        int port = Integer.parseInt(split[1]);
        return new IpPort(ip, port);
    }
}

[IpPortToStringConverter.java]

1
2
3
4
5
6
7
8
9
10
@Slf4j
public class IpPortToStringConverter implements Converter<IpPort, String> {

    @Override
    public String convert(IpPort source) {
        log.info("convert source={}", source);
        // IpPort 객체 -> "127.0.0.1:8080"
        return source.getIp() + ":" + source.getPort();
    }
}

[WebConfig.java]

1
2
3
4
5
6
7
8
9
@Configuration
public class WebConfig implements WebMvcConfigurer {

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

Line 4 ~ 8 : Conversion Service를 통해 컨버터 등록

[HelloController.java]

1
2
3
4
5
6
7
8
9
10
@RestController
public class HelloController {

    @GetMapping("/ip-port")
    public String ipPort(@RequestParam IpPort ipPort) {
        System.out.println("ipPort.getIp() = " + ipPort.getIp());
        System.out.println("ipPort.getPort() = " + ipPort.getPort());
        return "ok";
    }
}

3-2. 실행 결과

4. Formatter

Formatter는 객체를 문자로 또는 문자를 객체로 변환하는 상황에서 주로 사용한다. Converter와 마찬가지로 Conversion Service를 통해 여러 포매터들을 모아서 편리하게 사용할 수 있도록 기능을 제공한다.

1
2
3
package org.springframework.format;

public interface Formatter<T> extends Printer<T>, Parser<T> {}

4-1. 예제 코드

[MyNumberFormatter.java]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Slf4j
public class MyNumberFormatter implements Formatter<Number> {

    @Override
    public Number parse(String text, Locale locale) throws ParseException {
        log.info("text={}, locale={}", text, locale);
        //"1,000" -> 1000
        NumberFormat format = NumberFormat.getInstance(locale);
        return format.parse(text);
    }

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

[WebConfig.java]

1
2
3
4
5
6
7
8
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addFormatter(new MyNumberFormatter());
    }
}

Line 4 ~ 7 : Conversion Service를 통해 포매터 등록

[HelloController.java]

1
2
3
4
5
6
7
8
9
@RestController
public class HelloController {

    @GetMapping("/hello-v2")
    public String helloV2(@RequestParam Integer data) {
        System.out.println("data = " + data);
        return "ok";
    }
}

4-2. 실행 결과

Updated:

Leave a comment