Type Converter란 쉽게 우리가 데이터를 파라미터로 받아서 사용할 때 중간에서 변환시켜주는 녀석을 말한다. 코드로 예를 들면
@RestController
public class HelloController {
@GetMapping("/hello-v1")
public String helloV1(HttpServletRequest request){
String data = request.getParameter("data");
Integer integer = Integer.valueOf(data);
System.out.println("integer = " + integer);
return "ok";
}
}
다음과 같은 코드에 요청을 할경우
다음과 같이 integer를 얻을 수 있다. 하지만 타입을 String으로 받았다가 다시 Integer로 변환해야하는 귀찮은 상황이 생긴다.
@RestController
public class HelloController {
@GetMapping("/hello-v2")
public String helloV2(@RequestParam Integer data){
System.out.println("integer = " + data);
return "ok";
}
}
Spring이 제공하는 @RequestParam
을 통해 data parameter를 받을 경우 더이상 변환해주는 코드 없이 바로 integer type으로 받을 수 있다. 여기서 Type Converter가 작동하는 것인데 우리는 따로 신경쓰지 않아도 Spring에서 자동으로 Type Converter를 통해 Type을 변환해주고 있는 것이다.
이 내용에 대해 좀 더 자세하게 공부해보자!
우리가 학습할 Spring Converter는
org.springframework.core.converter.converter.Converter
이다.
@Slf4j
public class StringToIntegerConverter implements Converter<String, Integer> {
@Override
public Integer convert(String source) {
log.info("convert = {}", source);
return Integer.valueOf(source);
}
}
@Slf4j
public class IntegerToStringConverter implements Converter<Integer, String> {
@Override
public String convert(Integer source) {
log.info("convert = {}", source);
return String.valueOf(source);
}
}
우리가 사용하는 Converter Interface는 제너릭 안에 <S, T>의 값을 넣게 되는데 S는 입력할 값 T는 반환되는 값이다. 'S type을 넣으면 T로 반환해준다.'로 이해하면 쉽다.
public class ConverterTest {
@Test
void stringToInteger(){
StringToIntegerConverter converter = new StringToIntegerConverter();
Integer result = converter.convert("10");
assertEquals(result, 10);
}
@Test
void integerToString(){
IntegerToStringConverter converter = new IntegerToStringConverter();
String result = converter.convert(10);
assertEquals(result, "10");
}
}
다음과 같이 테스트 코드를 통해 실제 값이 잘 변환되는지 확인할 수 있다.
@Getter
@EqualsAndHashCode
@AllArgsConstructor
public class IpPort {
private String ip;
private int port;
}
@Slf4j
public class StringToIpPortConverter implements Converter<String, IpPort> {
@Override
public IpPort convert(String source) {
log.info("convert = {}", source);
//127.0.0.1:8080 -> 127.0.0.1 8080 나누기
String[] split = source.split(":");
String ip = split[0];
int port = Integer.parseInt(split[1]);
return new IpPort(ip, port);
}
}
@Slf4j
public class IpPortToStringConverter implements Converter<IpPort, String> {
@Override
public String convert(IpPort source) {
log.info("converter = {}", source);
return source.getIp() + ":" + source.getPort();
}
}
public class ConverterTest {
...
@Test
void stringToIpPort(){
IpPortToStringConverter converter = new IpPortToStringConverter();
IpPort source = new IpPort("127.0.0.1", 8080);
String result = converter.convert(source);
assertEquals(result, "127.0.0.1:8080");
}
@Test
void ipPortToIpString(){
StringToIpPortConverter converter = new StringToIpPortConverter();
String source = "127.0.0.1:8080";
IpPort result = converter.convert(source);
assertEquals(result, new IpPort("127.0.0.1", 8080));
}
}
똑같이 잘 변환되고 테스트도 잘 통과하는 것을 확인할 수 있다.
지금까지 직접 Converter를 만들어서 사용해봤다. 하지만 지금 사용하는 Converter는 적용하기가 매우 귀찮아 보이고 거의 메서드를 만들어서 사용하는거나 다름없다... 이제 다음 시간에는 Spring에 등록해서 자동으로 변환되는 ConversionService에 대해 공부해보자!