본문 바로가기

스프링/Spring

스프링 타입 컨버터 - Converter

 

Integer 값을 String으로 변환해주는 타입 컨버터

스프링 타입 컨버터란?

스프링을 사용해 애플리케이션을 개발할 때 문자를 숫자로 변환하거나, 반대로 숫자를 문자로 변환해야 하는 것처럼 타입을 변환할 때 사용하는 도구입니다.

 

스프링 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

)에 대해서 알아보겠습니다.