Spring

[Spring]Converter 보다 세부적으로 타입변경하는 법

코딩로봇 2025. 4. 16. 20:54

Formatter

♐ Formatter 이란?

  • 주로 사용자 지정 포맷을 적용해 데이터 변환을 처리할 때 사용된다. 
  • Formatter는 ConversionService와 비슷한 목적을 가지지만 문자열을 객체로 변환하거나 객체를 문자열로 변환하는 과정에서 포맷팅을 세밀하게 제어할 수 있다.

공식문서

https://docs.spring.io/spring-framework/reference/core/validation/format.html

 

Spring Field Formatting :: Spring Framework

As discussed in the previous section, core.convert is a general-purpose type conversion system. It provides a unified ConversionService API as well as a strongly typed Converter SPI for implementing conversion logic from one type to another. A Spring conta

docs.spring.io

 

♐ Formatter Interface

  • Printer, Parser 상속
  • 객체를 문자로 변환하고 문자를 객체로 변환하는 두가지 기능을 모두 가지고 있다.

1️⃣ Printer

  • Object를 String으로 변환한다.

2️⃣ Parser

  • String을 Object로 변환한다.

 

실습 

  • 숫자(10000)를 금액 형태(10,000)로 변환하는 Formatter 방법
@Slf4j
public class PriceFormatter implements Formatter<Number> {
	
	@Override
  public Number parse(String text, Locale locale) throws ParseException {
    log.info("text = {}, locale={}", text, locale);
		
		// 변환 로직
		// NumberFormat이 제공하는 기능
		NumberFormat format = NumberFormat.getInstance(locale);
		// "10,000" -> 10000L
		return format.parse(text);
  }

  @Override
  public String print(Number object, Locale locale) {
			log.info("object = {}, locale = {}", object, locale);
			// 10000L -> "10,000"
      return NumberFormat.getInstance(locale).format(object);
  }
	
}

 

테스트 코드

class PriceFormatterTest {

		PriceFormatter formatter = new PriceFormatter();

    @Test
    void parse() throws ParseException {
        // given, when
        Number result = formatter.parse("1,000", Locale.KOREA);

        // then
        // parse 결과는 Long
        Assertions.assertThat(result).isEqualTo(1000L);
    }

    @Test
    void print() {
        // given, when
        String result = formatter.print(1000, Locale.KOREA);

        // then
        Assertions.assertThat(result).isEqualTo("1,000");
    }
}

 

결과

 

 

Spring에 활용되는 Formatter

♐FormattingConversionService

  • ConversionService와 Formatter를 결합한 구현체
  • 타입 변환과 포맷팅이 필요한 모든 작업을 한 곳에서 수행할 수 있도록 설계되어 있어서 다양한 타입의 변환과 포맷팅을 쉽게 적용할 수 있다.

♐DefaultFormattingConversionService

  • FormattingConversionService 통화, 숫자관련 Formatter를 추가한것

 

사용 예시

public class FormattingConversionServiceTest {

    @Test
    void formattingConversionService() {

        // given
        DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();

        // Converter 등록
        conversionService.addConverter(new StringToPersonConverter());
        conversionService.addConverter(new PersonToStringConverter());
        // Formatter 등록
        conversionService.addFormatter(new PriceFormatter());

        // when
        String result = conversionService.convert(10000, String.class);

        // then
        Assertions.assertThat(result).isEqualTo("10,000");

    }

}

 

 

 Spring에 활용되는 Format Annotation

♐@ NumberFormat ,@DateFormat

  • 숫자 관련 지정 Formatter 사용
  • 날짜 관련 지정 Formatter 사용
@Data
public class FormatForm {

    @NumberFormat(pattern = "#,###.##")
    private BigDecimal price;

    @DateTimeFormat(pattern = "dd-MM-yyyy")
    private LocalDate orderDate;
    
}
@RestController
public class FormatController {

    @PostMapping("/format")
    public ResponseEntity<String> format(@ModelAttribute FormatForm form) {
        return new ResponseEntity<>(
                "form.getPrice() = " + form.getPrice() +
                        " form.getOrderDate() = " + form.getOrderDate(),
                HttpStatus.OK
        );
    }
}

 

결과

 

  •  

@JsonFormat

  • `@JsonFormat`은 날짜 형식이나 숫자 포맷을 지정할 수 있다.
  •  콤마를 포함한 숫자는 Jackson이 자동으로 변환하지 않으므로 커스텀 처리가 필요하다.
  • 커스텀 데이터의 변환이 필요한 경우 `Deserialize` 사용
@Data
public class JsonFormatDtoV2 {

    @JsonDeserialize(using = CurrencyDeserializer.class)
    private BigDecimal price;

    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy")
    private LocalDate orderDate;

}
@PostMapping("/json-format/annotation")
public ResponseEntity<String> jsonFormatAnnotation(@RequestBody JsonFormatDtoV2 dto) {
    return new ResponseEntity<>(
            "dto.getPrice() = " + dto.getPrice() +
                    " dto.getOrderDate() = " + dto.getOrderDate(),
            HttpStatus.OK
    );
}

 

 

공식문서

https://docs.spring.io/spring-framework/reference/core/validation/format.html#format-CustomFormatAnnotations

 

Spring Field Formatting :: Spring Framework

As discussed in the previous section, core.convert is a general-purpose type conversion system. It provides a unified ConversionService API as well as a strongly typed Converter SPI for implementing conversion logic from one type to another. A Spring conta

docs.spring.io