스프링 타입 컨버터란?
스프링을 사용해 애플리케이션을 개발할 때 문자를 숫자로 변환하거나, 반대로 숫자를 문자로 변환해야 하는 것처럼 타입을 변환할 때 사용하는 도구입니다.
스프링 MVC가 제공하는 @RequestParam을 사용해 타입을 변환해보겠습니다.
@GetMapping("/hello-v2")
public String helloV2(@RequestParam Integer data) {
System.out.println("data = " + data);
return "ok";
}
요청
http://localhost:8080/hello-v2?data=10
HTTP 쿼리 스트링으로 전달하는 data=10 부분에서 10은 숫자 10이 아니라 문자 10입니다.
스프링이 제공하는 @RequestParam을 사용하면 이 문자 10을 Integer 타입의 숫자 10으로 편리하게 받을 수 있습니다.
=> 스프링이 중간에서 타입을 변환해주었기 때문입니다.
이러한 예는 @ModelAttribute , @PathVariable 에서도 확인할 수 있습니다.
@ModelAttribute 타입 변환 예시
@ModelAttribute UserData data
class UserData {
Integer data;
}
@RequestParam와 같이, 문자 data=10을 숫자 10으로 받을 수 있습니다.
@PathVariable 타입 변환 예시
/users/{userId}
@PathVariable("data") Integer data
URL 경로는 문자입니다.
/users/10 여기서 10도 숫자 10이 아니라 그냥 문자 "10"이다. data를 Integer
타입으로 받을 수 있는 것도 스프링이 타입 변환을 해주기 때문입니다.
스프링의 타입 변환 적용 예
- 스프링 MVC 요청 파라미터 (@RequestParam , @ModelAttribute , @PathVariable)
- @Value 등으로 YML 정보 읽기
- XML에 넣은 스프링 빈 정보를 변환
- 뷰를 렌더링 할 때
만약 개발자가 새로운 타입을 만들어서 변환하고 싶으면 어떻게 하면 될까?
package org.springframework.core.convert.converter;
public interface Converter<S, T> {
T convert(S source);
}
스프링은 확장 가능한 컨버터 인터페이스를 제공합니다.
개발자는 스프링에 추가적인 타입 변환이 필요하면 이 컨버터 인터페이스를 구현해서 등록하면 됩니다.
필요하면 X => Y 타입으로 변환하는 컨버터 인터페이스를 만들고, 또 Y => X 타입으로 변환하는 컨버터 인터페이스를 만들어서 등록하면 됩니다.
타입 컨버터 - Converter
가장 단순한 형태인 문자를 숫자로 바꾸는 타입 컨버터를 만들어보겠습니다.
package hello.typeconverter.converter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.convert.converter.Converter;
@Slf4j
public class StringToIntegerConverter implements Converter<String,Integer> {
@Override
public Integer convert(String source) {
log.info("convert source={}", source);
return Integer.valueOf(source);
}
}
이번에는 숫자를 문자로 변환하는 타입 컨버터입니다.
package hello.typeconverter.converter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.convert.converter.Converter;
@Slf4j
public class IntegerToStringConverter implements Converter<Integer, String> {
@Override
public String convert(Integer source) {
log.info("convert source={}", source);
return String.valueOf(source);
}
}
테스트 코드를 통해서 타입 컨버터가 어떻게 동작하는지 확인해보겠습니다.
@Test
void stringToInteger(){
StringToIntegerConverter converter = new StringToIntegerConverter();
Integer result = converter.convert("10");
assertThat(result).isEqualTo(10);
}
@Test
void integerToString() {
IntegerToStringConverter converter = new IntegerToStringConverter();
String result = converter.convert(10);
assertThat(result).isEqualTo("10");
}
사용자 정의 타입 컨버터
127.0.0.1:8080과 같은 IP, PORT를 입력하면 IpPort 객체로 변환하는 컨버터를 만들어보겠습니다.
package hello.typeconverter.type;
import lombok.EqualsAndHashCode;
import lombok.Getter;
@Getter
@EqualsAndHashCode
public class IpPort {
private String ip;
private int port;
public IpPort(String ip, int port) {
this.ip = ip;
this.port = port;
}
}
127.0.0.1:8080 같은 문자를 입력하면 IpPort 객체를 만들어 반환합니다.
package hello.typeconverter.converter;
import hello.typeconverter.type.IpPort;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.convert.converter.Converter;
@Slf4j
public class StringToIpPortConverter implements Converter<String, IpPort> {
@Override
public IpPort convert(String source) {
log.info("convert source={}", source);
String[] split = source.split(":");
String ip = split[0];
int port = Integer.parseInt(split[1]);
return new IpPort(ip, port);
}
}
IpPort 객체를 입력하면 127.0.0.1:8080 같은 문자를 반환합니다.
package hello.typeconverter.converter;
import hello.typeconverter.type.IpPort;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.convert.converter.Converter;
@Slf4j
public class IpPortToStringConverter implements Converter<IpPort,String> {
@Override
public String convert(IpPort source) {
log.info("convert source={}", source);
return source.getIp() + ":" + source.getPort();
}
}
테스트를 통해 컨버팅을 검증해보겠습니다.
@Test
void stringToIpPort() {
StringToIpPortConverter converter = new StringToIpPortConverter();
String source = "127.0.0.1:8080";
IpPort result = converter.convert(source);
assertThat(result).isEqualTo(new IpPort("127.0.0.1", 8080));
}
@Test
void ipPortToString() {
IpPortToStringConverter converter = new IpPortToStringConverter();
IpPort source = new IpPort("127.0.0.1", 8080);
String result = converter.convert(source);
assertThat(result).isEqualTo("127.0.0.1:8080");
}
이렇게 타입 컨버터를 하나하나 직접 사용하면, 개발자가 직접 컨버팅 하는 것과 큰 차이가 없습니다.
타입 컨버터를 등록하고 관리하면서 편리하게 변환 기능을 제공하는 역할을 하는 것이 필요합니다.
다음에는 개별 컨버터를 모아두고 그것들을 묶어서 편리하게 사용할 수 있는 기능을 제공하는 컨버젼 서비스(ConversionService
)에 대해서 알아보겠습니다.
'스프링 > Spring' 카테고리의 다른 글
스프링 포맷터(Formatter), 포맷터를 지원하는 ConversionService (0) | 2021.12.30 |
---|---|
컨버전 서비스 사용하기 - ConversionService (타임리프, 폼) (0) | 2021.12.30 |
@SessionAttribute 어노테이션을 사용해서 세션 조회하기 (0) | 2021.10.26 |
[SpringBoot] 서블릿의 HttpSession을 사용해 세션 구현하기 (0) | 2021.10.26 |
[SpringBoot] 스프링부트에서 비동기 처리하기 (0) | 2021.10.25 |