본문 바로가기
[ JAVA ]/JAVA Spring

[ Spring ] Spring Type Converter

by 환이s 2024. 1. 29.


이전 포스팅에서 Spring Exception Handling에 대해 알아봤습니다.

오늘은 Spring Type Converter 정리를 해보겠습니다.

 


Spring Type Converter 

 

문자를 숫자로 변환하거나, 반대로 숫자를 문자로 변환해야 하는 것처럼 애플리케이션을 개발하다 보면

타입을 변환해야 하는 경우가 상당히 많다.

 

다음 예를 보자.

 

  • HelloController - 문자 타입을 숫자 타입으로 변경
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;

@RestController
public class HelloController {

     @GetMapping("/hello-v1")
     public String helloV1(HttpServletRequest request) {
     
         String data = request.getParameter("data"); //문자 타입 조회
         Integer intValue = Integer.valueOf(data); //숫자 타입으로 변경
         System.out.println("intValue = " + intValue);
         
    	 return "ok";
     }
}

 

분석해 보면

String data = request.getParameter("data")

 

HTTP 요청 파라미터는 모두 문자로 처리된다.

따라서 요청 파라미터를 자바에서 다른 타입으로 변환해서 사용하고 싶으면

 

다음과 같은 숫자 타입으로 변환하는 과정을 거쳐야 한다.

Integer intValue = Integer.valueOf(data)

 

이번에는 Spring MVC가 제공하는 @RequestParam을 사용해 보자.

 

  • HelloController - 추가
@GetMapping("/hello-v2")
public String helloV2(@RequestParam Integer data) {

     System.out.println("data = " + data);
     return "ok";
     
}

 

실행해서 data=10을 입력해 보면 아래와 같은 경로로 입력하면 된다.

글쓴이의 포트번호는 9090 이므로 

 

http://localhost:9090/hello-v2?data=10

 

data=10을 넘겨주었다.

 

앞서 보았듯이 HTTP Query  String으로 전달되는 data=10 부분에서 10은 숫자 10이 아니라 문자 10이다.

 

Spring이 제공하는 @RequestParam을 사용하면 이 문자 10을 Integer 타입의 숫자 10으로 편리하게 받을 수 있다.

 

이것은 Spring이 중간에서 타입을 변환해 주었기 때문이다.

 

이러한 예는 @ModelAttribute,@PathVariable에서도 확인할 수 있다.

 

  • @ModelAttribute 타입 변환 예시
@ModelAttribute UserData data

class UserData {
 	Integer data;
}

 

@RequestParam와 같이, 문자 data=10을 숫자 10으로 받을 수 있다.

 

  • @PathVariable 타입 변환 예시
/users/{userId}
@PathVariable("userId") Integer data

 

URL 경로는 문자다.

 

./users/10 -> 여기서 10도 숫자 10이 아니라 문자 "10"이다. 

data를 Integer 타입으로 받을 수 있는 것도 Spring이 타입 변환을 해주기 때문이다.

 

  • Spring의 타입 변환 적용 예
    • Spring MVC 요청 파라미터
      • @RequestParam, @ModelAttribute, @PathVariable
    • @Value 등으로 YML 정보 읽기
    • XML에 넣은 Spring Bean 정보를 변환
    • VIEW를 렌더링 할 때

 

 

Spring Type 변환

 

 

이렇게 타입을 변환해야 하는 경우는 상당히 많다.

 

개발자가 직접 하나하나 타입 변환을 해야 한다면, 생각만 해도 괴로울 것이다.

Spring이 중간에 타입 변환기를 사용해서 타입을 String -> Integer로 변환해 주었기 때문에

개발자는 편리하게 해당 타입을 바로 받을 수 있다.

 

앞에서는 문자를 숫자로 변경하는 예시를 들었지만, 반대로 숫자를 문자로 변경하는 것도 가능하고,

Boolean 타입을 숫자로 변경하는 것도 가능하다.

 

만약 개발자가 새로운 타입을 만들어서 변환하고 싶으면 어떻게 하면 될까?

 

  • Converter Interface
public interface Converter<S, T> {
	 T convert(S source);
}

 

Spring은 확장 가능한 Converter Interface를 제공한다.

 

개발자는 Spring에 추가적인 타입 변환이 필요하면 이 컨버터 인터페이스를 구현해서 등록하면 된다.

이 컨버터 인터페이스는 모든 타입에 적용할 수 있다.

 

필요하면 X -> Y 타입으로 변환하는 컨버터 인터페이스를 만들고,

또 Y -> X 타입으로 변환하는 컨버터 인터페이스를 만들어서 등록하면 된다.

 

예를 들어서 문자로 "true"가 오면 Boolean 타입으로 받고 싶으면 String -> Boolean 타입으로

변환되도록 컨버터 인터페이스를 만들어서 등록하고, 

 

반대로 적용하고 싶으면 Boolean -> String 타입으로 변환되도록 컨버터를 추가로 만들어서 등록하면 된다.

 

실제 코드를 통해서 Type Converter를 이해해 보자.

 


Type Converter

 

Type Converter를 어떻게 사용하는지 코드로 알아보자.

 

Type Converter를 사용하려면

org.springframework.core.convert.converter.Converter

 

Interface를 구현하면 된다.

 

여기서 주의할 점

Converter라는 이름의 Interface가 많으니 조심해야 한다.

org.springframework.core.convert.converter.Converter를 사용해야 한다.

 

  • Converter Interface
public interface Converter<S, T> {
 	T convert(S source);
}

 

먼저 가장 단순한 형태인 문자를 숫자로 바꾸는 Type Converter를 만들어보자.

 

  • StringToIntegerConverter - 문자를 숫자로 변환하는 타입 컨버터
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);
     }
}

 

String -> Integer로 변환하기 때문에 소스가 String이 된다.

이 문자를 Integer.valueOf(source)를 사용해서 숫자로 변경한 다음에 변경된 숫자를 반환하면 된다.

 

  • IntegerToStringConverter - 숫자를 문자로 변환하는 타입 컨버터
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);
     }
}

 

이번에는 숫자를 문자로 변환하는 Type Converter이다.

 

앞의 컨버터와 반대로 일을 한다.

이번에는 숫자가 입력되기 때문에 소스가 Integer가 된다.

 

String.valueOf(source)를 사용해서 문자로 변경한 다음 변경된 문자를 반환하면 된다.

 

Test Code를 통해서 타입 컨버터가 어떻게 동작하는지 확인해 보자.

 

  • ConverterTest - 타입 컨버터 테스트 코드
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.*;

class ConverterTest {

     @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");
     }
}

 

위 코드를 실행해 보면 Test가 정상적으로 진행되는 걸 확인할 수 있다.

 


사용자 정의 Type Converter

 

Type Converter 이해를 돕기 위해 조금 다른 컨버터를 준비해 보았다.

127.0.0.1:9090과 같은 IP, PORT를 입력하면 ipPort 객체로 변환하는 컨버터를 만들어보자.

 

  • IpPort
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;
     }
}

 

Lombok의 @EqualsAndHashCode를 넣으면 모든 필드를 사용해서 equals(), hashcode()를 생성한다.

 

따라서 모든 필드의 값이 같다면 a.equals(b)의 결과가 참이 된다.

 

  • StringToIpPortConverter - 컨버터
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);
     }
}

 

127.0.0.1:9090 같은 문자를 입력하면 IpPort 객체를 만들어 반환한다.

 

  • IpPortToStringConverter
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();
     }
}

 

IpPort 객체를 입력하면 127.0.0.1:9090 같은 문자를 반환한다.

 

  • ConverterTest - IpPort 컨버터 테스트 추가
    @Test
    void stringToIpPort() {
    
         StringToIpPortConverter converter = new StringToIpPortConverter();
         
         String source = "127.0.0.1:9090";
         IpPort result = converter.convert(source);
         
         assertThat(result).isEqualTo(new IpPort("127.0.0.1", 9090));
    }
    @Test
    void ipPortToString() {
    
         IpPortToStringConverter converter = new IpPortToStringConverter();
         
         IpPort source = new IpPort("127.0.0.1", 9090);
         String result = converter.convert(source);
         
         assertThat(result).isEqualTo("127.0.0.1:9090");
    }

 

Type Converter Interface가 단순해서 이해하기 어렵지 않을 것이다.

 

그런데 이렇게 Type Converter를 하나하나 직접 사용하면,

개발자가 직접 컨버팅 하는 것과 큰 차이가 없다.

 

Type Converter를 등록하고 관리하면서 편리하게 변환 기능을 제공하는 역할을 하는 무언가가 필요하다.

 

참고 )

Spring은 용도에 따라 다양한 방식의 타입 컨버터를 제공한다.

Converter -> 기본 타입 컨버터

ConverterFactory -> 전체 클래스 계층 구조가 필요할 때

GenericConverter -> 정교한 구현, 대상 필드의 애노테이션 정보 사용 가능

ConditionalGenericConverter -> 특정 조건이 참인 경우에만 실행


Spring은 문자, 숫자, 불린, Enum 등 일반적인 타입에 대한 대부분의 컨버터를 기본으로 제공한다.

IDE에서 Converter, ConverterFactory, GenericConverter의 구현체를 찾아보면
수많은 컨버터를 확인할 수 있다.

ConversionService

 

이렇게 타입 컨버터를 하나하나 직접 찾아서 타입 변환에 사용하는 것은 매우 불편하다.

 

그래서 Spring은 개별 컨버터를 모아두고 그것들을 묶어서 편리하게 사용할 수 있는 기능을 제공하는데,

이것이 바로 ConversionService이다.

 

  • ConversionService Interface
import org.springframework.lang.Nullable;

public interface ConversionService {

    boolean canConvert(@Nullable Class<?> sourceType, Class<?> targetType);
    
    boolean canConvert(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType);
    
    <T> T convert(@Nullable Object source, Class<T> targetType);
    
    Object convert(@Nullable Object source, @Nullable TypeDescriptor sourceType,TypeDescriptor targetType);
}

 

ConversionService Interface는 단순히 컨버팅이 가능한가?

확인하는 기능과, 컨버팅 기능을 제공한다.

 

사용 예를 확인해 보자.

 

  • ConversionServiceTest - 컨버젼 서비스 테스트 코드
import hello.typeconverter.type.IpPort;
import org.junit.jupiter.api.Test;
import org.springframework.core.convert.support.DefaultConversionService;
import static org.assertj.core.api.Assertions.*;

public class ConversionServiceTest {
     @Test
     void conversionService() {
     
     //등록
     DefaultConversionService conversionService = new DefaultConversionService();
     
     conversionService.addConverter(new StringToIntegerConverter());
     conversionService.addConverter(new IntegerToStringConverter());
     conversionService.addConverter(new StringToIpPortConverter());
     conversionService.addConverter(new IpPortToStringConverter());
     
     //사용
     assertThat(conversionService.convert("10",Integer.class)).isEqualTo(10);
     
     assertThat(conversionService.convert(10,String.class)).isEqualTo("10");
     
     IpPort ipPort = conversionService.convert("127.0.0.1:9090",IpPort.class);
     
     assertThat(ipPort).isEqualTo(new IpPort("127.0.0.1", 9090));

     String ipPortString = conversionService.convert(new IpPort("127.0.0.1",9090), String.class);
     
     assertThat(ipPortString).isEqualTo("127.0.0.1:9090");
     }
}

 

 

DefaultConversionServiceConversionService 인터페이스를 구현했는데,

추가로 컨버터를 등록하는 기능도 제공한다.

 

 

등록과 사용 분리

 

컨버터를 등록할 때는 StringToIntegerConverter 같은 타입 컨버터를 명확하게 알아야 한다.

 

반면에 컨버터를 사용하는 입장에서는 타입 컨버터를 전혀 몰라도 된다.

타입 컨버터들은 모두 컨버젼 서비스 내부에 숨어서 제공된다.

 

따라서 타입을 변환을 원하는 사용자는 컨버젼 서비스 인터페이스에만 의존하면 된다.

물론 컨버젼 서비스를 등록하는 부분과 사용하는 부분을 분리하고 의존관계 주입을 사용해야 한다.

 

// 컨버전 서비스 사용

Integer value = conversionService.convert("10", Integer.class)

 

 

■ ISP(Interface Segregation Principle) - 인터페이스 분리 원칙

 

인터페이스 분리 원칙은 클라이언트가 자신이 이용하지 않는 메서드에 의존하지 않아야 한다.

 

DefaultConversionService는 다음 두 인터페이스를 구현했다.

 

  • ConversionService : 컨버터 사용에 초점
  • ConverterRegistry : 컨버터 등록에 초점

 

이렇게 인터페이스를 분리하면 컨버터를 사용하는 클라이언트와

컨버터를 등록하고 관리하는 클라이언트의 관심사를 명확하게 분리할 수 있다.

 

특히 컨버터를 사용하는 클라이언트는 ConversionService만 의존하면 되므로,

컨버터를 어떻게 등록하고 관리하는지는 전혀 몰라도 된다.

 

결과적으로 컨버터를 사용하는 클라이언트는 꼭 필요한 메서드만 알게 된다.

이렇게 인터페이스를 분리하는 것을 ISP라 한다.

 

Spring은 내부에서 ConversionService를 사용해서 타입을 변환한다.

 

예를 들어서 앞서 살펴본 @RequestParam 같은 곳에서 이 기능을 사용해서 타입을 변환한다.

이제 컨버젼 서비스를 Spring에 적용해 보자.


Spring Converter 적용

 

웹 애플리케이션에 Converter를 적용해 보자.

 

  • WebConfig - Converter 등록
import hello.typeconverter.converter.IntegerToStringConverter;
import hello.typeconverter.converter.IpPortToStringConverter;
import hello.typeconverter.converter.StringToIntegerConverter;
import hello.typeconverter.converter.StringToIpPortConverter;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

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


Spring은 내부에서 ConversionService를 제공한다.

우리는 WebMvcConfigurer가 제공하는 addFormatters()를 사용해서 추가하고 싶은 컨버터를 등록하면 된다.

 

이렇게 하면 Spring은 내부에서 사용하는 ConversionService에 컨버터를 추가해 준다.

 

등록한 컨버터가 잘 동작하는지 확인해 보자.

 

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

 

동일하게 data=10을 넘겨주고 로그를 확인해 보자.

//http://localhost:9090/hello-v2?data=10
// [실행 Log]

StringToIntegerConverter : convert source=10
data = 10

 

? data=10의 쿼리 파라미터는 문자이고

이것을 Integer data로 변환하는 과정이 필요하다.

 

실행해 보면 직접 등록한 StringtoIntegerConverter가 작동하는 로그를 확인할 수 있다.

 

그런데 생각해 보면 StringToIntegerConverter를 등록하기 전에도 이 코드는 잘 수행되었다.

그것은 Spring이 내부에서 수많은 기본 컨버터들을 제공하기 때문이다.

 

컨버터를 추가하면 추가한 컨버터가 기본 컨버터 보다 높은 우선순위를 가진다.

 

 

 

이번에는 직접 정의한 타입인 IpPort를 사용해 보자.

 

  • HelloController - 추가
@GetMapping("/ip-port")
public String ipPort(@RequestParam IpPort ipPort) {

     System.out.println("ipPort IP = " + ipPort.getIp());
     System.out.println("ipPort PORT = " + ipPort.getPort());
     return "ok";
}

 

ipPort 값을 127.0.0.1:9090으로 넘겨주고 확인해 보자.

 

// [실행 Log]

StringToIpPortConverter : convert source=127.0.0.1:9090
ipPort IP = 127.0.0.1
ipPort PORT = 9090

 

?ipPort=127.0.0.1:9090 쿼리 스트링이 @RequestParam IpPort ipPort에서 객체 타입으로 잘 변환된 것을 확인할 수 있다.

 

 

처리 과정

 

@RequestParam@RequestParam을 처리하는 Argumentresolver

RequestParamMethodArgumentResolver에서 ConversionService를 사용해서 타입을 변환한다.

 

부모 클래스와 다양한 외부 클래스를 호출하는 등

복잡한 내부 과정을 거치기 때문에 대략 이렇게 처리되는 것으로 이해해도 충분하다.

 

만약 더 깊이 있게 확인하고 싶으면 IpPortConverter에 디버그 브레이크 포인트를 걸어서 확인해 보자.

 


뷰 템플릿에 컨버터 적용

 

이번에는 뷰 템플릿에 컨버터를 적용하는 방법을 알아보자.

타임리프는 렌더링 시에 컨버터를 적용해서 렌더링 하는 방법을 편리하게 지원한다.

 

이전까지는 문자를 객체로 변환했다면,

이번에는 그 반대로 객체를 문자로 변환하는 작업을 확인할 수 있다.

 

  • ConverterController
import hello.typeconverter.type.IpPort;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class ConverterController {

     @GetMapping("/converter-view")
     public String converterView(Model model) {
     
         model.addAttribute("number", 10000);
         model.addAttribute("ipPort", new IpPort("127.0.0.1", 9090));
         
     return "converter-view";
     }
}

 

Model에 숫자 10000ipPort 객체를 담아서 뷰 템플릿에 전달한다.

 

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

 

타임리프는 ${{...}}를 사용하면 자동으로 컨버젼 서비스를 사용해서 변환된 결과를 출력해 준다.

 

물론 Spring과 통합되어서 스프링이 제공하는 컨버젼 서비스를 사용하므로,

우리가 등록한 컨버터들을 사용할 수 있다.

 

변수 표현식 : ${...}

컨버전 서비스 적용 : ${{...}}

 

실행 결과를 확인해 보자.

 

// 실행 결과

 ${number}: 10000
 ${{number}}: 10000
 ${ipPort}: hello.typeconverter.type.IpPort@59cb0946
 ${{ipPort}}: 127.0.0.1:9090
 
 
 // 실행 결과 Log
 
 IntegerToStringConverter : convert source=10000
 IpPortToStringConverter : convert 
 source=hello.typeconverter.type.IpPort@59cb0946

 

${{number}} : 뷰 템플릿은 데이터를 문자로 출력한다.

따라서 컨버터를 적용하게 되면 Integer 타입인 10000String 타입으로 변환하는 컨버터인

IntegerToStringConverter를 실행하게 된다.

 

이 부분은 컨버터를 실행하지 않아도 타임리프가 숫자를 문자로 자동으로 변환하기 때문에 

컨버터를 적용할 때와 하지 않을 때가 같다.

 

${{ipPort}} : 뷰 템플릿은 데이터를 문자로 출력한다.

따라서 컨버터를 적용하게 되면 IpPort 타입을 String 타입으로 변환해야 하므로,

IpPortToStringConverter가 적용된다.

 

그 결과 127.0.0.1:9090가 출력된다.


Form 적용

 

이번에는 컨버터를 폼에 적용해 보자.

 

  • ConverterController - 코드 추가
import hello.typeconverter.type.IpPort;
import lombok.Data;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

@Controller
public class ConverterController {

     @GetMapping("/converter-view")
     public String converterView(Model model) {
     
         model.addAttribute("number", 10000);
         model.addAttribute("ipPort", new IpPort("127.0.0.1", 9090));
         
     return "converterView";
     }
     
     @GetMapping("/converter/edit")
     public String converterForm(Model model) {
     
         IpPort ipPort = new IpPort("127.0.0.1", 9090);
         
         Form form = new Form(ipPort);
         model.addAttribute("form", form);
     
     return "converterForm";
     }
     
     @PostMapping("/converter/edit")
     public String converterEdit(@ModelAttribute Form form, Model model) {
     
         IpPort ipPort = form.getIpPort();
         model.addAttribute("ipPort", ipPort);
         
     return "converterView";
     }
     
     @Data
     static class Form {
     
         private IpPort ipPort;
         
         public Form(IpPort ipPort) {
         	this.ipPort = ipPort;
         }
     }
}

 

Form 객체를 데이터를 전달하는 폼 객체로 사용한다.

 

  • GET /converter/edit : IpPort를 뷰 템플릿 폼에 출력한다.

 

  • POST /converter/edit : 뷰 템플릿 폼의 IpPort 정보를 받아서 출력한다.

 

 

  • converterForm.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
 <meta charset="UTF-8">
 <title>Title</title>
</head>
<body>
    <form th:object="${form}" th:method="post">
         th:field <input type="text" th:field="*{ipPort}"><br/>
         th:value <input type="text" th:value="*{ipPort}">(보여주기 용도)<br/>
    	 <input type="submit"/>
    </form>
</body>
</html>

 

타임리프의 th:fieldid, name를 출력하는 등 다양한 기능이 있는데,

여기에 컨버젼 서비스도 함께 적용된다.

 

결과를 확인해 보자.

http://localhost:9090/converter/edit

 

  • GET /converter/edit
    • th:field가 자동으로 컨버전 서비스를 적용해 주어서 ${{ipPort}}처럼 적용이 되었다.
    • 따라서 IpPort -> String으로 변환된다.
  • POST /converter/edit
    • @ModelAttribute를 사용해서 String -> IpPort로 변환된다.

마치며

 

오늘은 Spring Type Converter에 대해 정리해 보았습니다.

 

Converter는 입력과 출력 타입에 제한이 없는, 범용 타입 변환 기능을 제공합니다.

 

다음 포스팅에서는 객체를 특정한 포맷에 맞추어 문자로 출력하거나 또는 그 반대의 역할을 하는 것에 특화된 기능인 Formatter(포맷터)에 대한 정리글로 찾아뵙겠습니다.

 

위 포스팅은 김영한님의 Spring MVC 2편 - 백엔드 웹 개발 활용  강의를 참고했습니다.

 

스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 강의 - 인프런

웹 애플리케이션 개발에 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. MVC 2편에서는 MVC 1편의 핵심 원리와 구조 위에 실무 웹 개발에 필요한 모든 활용 기술들을 학습할 수 있

www.inflearn.com

 

728x90