TypeConverter
📌 Spring에서 객체의 타입을 서로 변환하는 데 사용되는 인터페이스로 Spring의 데이터 바인딩 과정에서 문자열을 특정 객체로 변환하거나 하나의 객체 타입을 다른 타입으로 변환할 때 사용한다.
- 문자를 숫자로, 숫자를 문자로 변환하는 등 Web Application을 만들다보면 Type을 변환해야 하는 경우가 많이 발생한다.
- 결론
- 요청 파라미터로 전달하는 10 값은 실제로는 문자열(String) 10이다.
- @RequestParam을 사용하면 문자 10을 Integer 타입의 숫자 10으로 변환된다.
- @ModelAttribute, @PathVariable 에서도 타입 변환을 확인할 수 있다.
- Spring 내부에서 누군가가 타입을 자동으로 변환한다.
Converter Interface
- Spring이 제공하는 인터페이스
- implements하여 Converter로 등록하면 된다.
- Converter는 모든 타입(T)에 적용할 수 있다.
- 개발자가 새로운 Type을 만들어서 사용할 수 있도록 만든다.
- 변환하고자 하는 타입에 맞춰서 Type Converter를 구현하고 등록하면 된다.
Converter
📌 데이터 타입 간 변환을 처리하는 인터페이스 , 주로 웹 요청 파라미터를 Java 객체로 변환하거나 그 반대로 변환할 때 사용되며 커스텀 변환 로직을 정의할 수 있다.
- 주의점
- org.springframework.core.convert.converter
- Spring의 Converter와 같은 이름을 가진 Interface가 많으니 주의해야 한다.
- 코드 예시
- String → Integer
- Converter<S, T> 에서 S는 변환할 Source T는 변환할 Type으로 설정하면 된다.
@Slf4j
public class StringToIntegerConverter implements Converter<String, Integer> {
@Override
public Integer convert(String source) {
log.info("source = {}", source);
// 검증
return Integer.valueOf(source);
}
}
- 파라미터로 들어온 source가 Interger로 변환된다.
- Integer → String
@Slf4j
public class IntegerToStringConverter implements Converter<Integer, String> {
@Override
public String convert(Integer source) {
log.info("source = {}", source);
return String.valueOf(source);
}
}
- 파라미터로 들어온 source가 String으로 변환된다.
- String → Person
@Getter
public class Person {
// 이름
private String name;
// 나이
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
- 요청 예시
- localhost:8080/type-converter?person=wonuk:1200
public class StringToPersonConverter implements Converter<String, Person> {
// source = "wonuk:1200"
@Override
public Person convert(String source) {
// ':' 를 구분자로 나누어 배열로 만든다.
String[] parts = source.split(":");
// 첫번째 배열은 이름이다. -> wonuk
String name = parts[0];
// 두번째 배열은 개월수이다. -> 1200
int months = Integer.parseInt(parts[1]);
// 개월수 나누기 12로 나이를 구하는 로직 (12개월 단위만 고려)
int age = months / 12;
return new Person(name, age);
}
}
public class PersonToStringConverter implements Converter<Person, String> {
@Override
public String convert(Person source) {
// 이름
String name = source.getName();
// 개월수
int months = source.getAge * 12;
// "wonuk:1200"
return name + ":" + months;
}
}
- TypeConverter 사용
- 구현은 단순하게 직접 메서드를 구현하여 모듈화 하면된다.
- TypeConverter 를 생성하여 직접 사용하면 컨트롤러에서 변환하는 방식과 큰 차이가 없다.
PersonToStringConverter converter = new PersonToStringConverter();
String source = "wonuk:1200";
converter.convert(source);
- Converter를 편리하게 등록하고 사용할 수 있도록 만들어주는 기능이 필요하다.
- Spring은 String, Integer, Enum등 자주 사용되는 타입에 대한 컨버터를 제공하고 사용할 수 있도록 등록되어 있다.
Spring의 다양한 Converter
📌 Spring에서 제공하는 다양한 Converter 인터페이스가 존재하며 이들은 Spring의 데이터 바인딩, 요청/응답 처리, 속성 값 주입 등에 사용되고 ConversionService를 통해 등록 및 관리된다.
- Converter
- 기본적인 변환을 담당하는 인터페이스
- 단일 타입에서 단일 타입으로 변환할 때 사용한다.
- Converter<Source, Type>
- ConverterFactory
- 클래스 계층 구조가 복잡한 경우 사용
- 기본 타입과 다양한 서브 타입 간의 변환을 지원한다.
- GenericConverter
- 다양한 타입 간의 유연한 변환을 지원한다.
- 복잡한 타입 변환 로직을 구현할 때 유리하다.
- ConditionalGenericConverter
- GenericConverter 의 확장형으로 특정 조건에서만 타입 변환을 수행한다.
- 추가적으로 matches() 를 통해 변환 가능 여부를 판단할 수 있다.
ConversionService
📌 Spring은 Converter를 모아서 편리하게 관리하고 사용할 수 있게 해주는 기능을 제공한다. 이것이 Conversion Service 이다.
ConversionService 인터페이스
- canConvert()
- Convert 가능 여부를 확인하는 기능
- convert()
- 실제 변환하는 기능
DefaultConversionService
📌 Spring의 표준 ConversionService로 기본 제공 Converter와 확장 가능성을 통해 다양한 타입 변환을 유연하게 처리할 수 있도록 지원한다.
- DefaultConversionService
- ConversionService를 구현한 구현체
ConvertRegistry에 다양한 Converter를 등록한다.
- ConverterRegistry
- Converter를 등록하고 관리하는 기능을 제공한다.
import static org.assertj.core.api.Assertions.*;
public class ConversionServiceTest {
@Test
void defaultConversionService() {
// given
DefaultConversionService dcs = new DefaultConversionService();
dcs.addConverter(new StringToPersonConverter());
Person wonuk = new Person("wonuk", 100);
// when
Person stringToPerson = dcs.convert("wonuk:1200", Person.class);
// then
assertThat(stringToPerson.getName()).isEqualTo(wonuk.getName());
assertThat(stringToPerson.getAge()).isEqualTo(wonuk.getAge());
}
}
- 컨버터를 사용할 때는 종류를 몰라도된다.
- 컨버터는 ConversionService 내부에서 숨겨진채 제공된다.
- 반환 타입, 파라미터 타입, 제네릭 등으로 ConversionService가 컨버터를 찾는다.
- 즉, 클라이언트는 ConversionService 인터페이스만 의존하면 된다.
- 컨버터 등록과 사용의 분리
ISP(인터페이스 분리 원칙, Interface Segregation Principal)
📌 클라이언트가 자신이 사용하지 않는 메서드에 의존하지 않도록 인터페이스를 분리하는 원칙
- DefaultConversionService
- ConversionRegistry : 컨버터 등록
- ConversionService ****: ****컨버터 사용
- 인터페이스를 분리하면 컨버터를 사용하는 클라이언트는 필요한 메서드만 알면된다.
- ConversionRegistry 가 변경되어도 ConversionService와 연관이 없다.
- Spring은 내부적으로 위와같이 등록, 사용이 분리된 인터페이스들이 아주 많다.
Spring은 내부적으로 ConversionService를 사용해 타입을 변환한다. 대표적으로 @RequestParam , @PathVariable, @ModelAttribute 등이 해당 기능을 사용한다. |
Converter 요약
Spring의 **Converter**는 데이터 타입 간 변환을 처리하는 인터페이스입니다. 주로 Spring의 데이터 바인딩 또는 사용자 정의 변환 작업에 사용됩니다. 간단한 입력 값 변환에서부터 복잡한 객체 변환까지 유연하게 지원합니다.
Converter의 주요 특징
- 데이터 타입 변환:
- 소스 타입(Source Type)에서 대상 타입(Target Type)으로 변환.
- 예: String → Integer, String → LocalDate.
- 간결한 인터페이스:
- 구현이 간단하며 특정 변환 작업에 집중.
- 범용 사용 가능:
- Spring의 데이터 바인딩, 요청 파라미터 변환, 커스텀 변환 로직 등에 사용.
- 확장 가능:
- Spring이 기본으로 제공하는 변환기 외에도 사용자 정의 변환기를 구현할 수 있음.
Converter 인터페이스
public interface Converter<S, T> {
T convert(S source);
}
- S: 소스 데이터 타입 (변환 전 데이터 타입).
- T: 대상 데이터 타입 (변환 후 데이터 타입).
Converter의 사용 사례
1. 문자열을 날짜로 변환 (String → LocalDate)
public class StringToLocalDateConverter implements Converter<String, LocalDate> {
@Override
public LocalDate convert(String source) {
// 문자열을 LocalDate로 변환
return LocalDate.parse(source, DateTimeFormatter.ISO_DATE);
}
}
Spring에서 Converter 등록
Spring에서는 변환기를 전역적으로 등록하거나, 특정 컨텍스트에서 사용할 수 있습니다.
1. 전역 등록
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
// 커스텀 Converter 등록
registry.addConverter(new StringToLocalDateConverter());
}
}
Spring의 기본 Converter
Spring은 이미 다양한 기본 변환기를 제공합니다:
- Primitive 타입 변환: String → int, String → double 등.
- Java 날짜/시간 변환: String → LocalDate, String → LocalDateTime.
- Enum 변환: String → Enum.
Converter와 일상적인 비유
비유: 데이터를 변환하는 "도구 상자"
- Converter는 한 가지 타입의 데이터를 다른 타입으로 변환하는 간단한 도구입니다.
- 예를 들어, 숫자 데이터를 텍스트로 변환하는 계산기처럼, Converter는 입력 값을 원하는 형태로 만들어줍니다.
Converter 사용 예제
컨트롤러에서 사용
@RestController
@RequestMapping("/api")
public class ExampleController {
@GetMapping("/date")
public String getDate(@RequestParam String date, Converter<String, LocalDate> converter) {
LocalDate localDate = converter.convert(date);
return "Converted date: " + localDate.toString();
}
}
요청 예
GET /api/date?date=2023-12-25
결과
Converted date: 2023-12-25
Converter와 관련된 확장
- Formatter:
- Converter의 확장형으로, 데이터를 특정 형식(포맷)으로 변환하고 역변환도 지원.
- 예: 날짜를 특정 형식으로 변환하거나 파싱.
- GenericConverter:
- 보다 범용적인 변환을 지원하는 고급 형태의 Converter.
- ConversionService:
- 여러 변환기를 한데 모아 관리하고, 필요한 변환기를 자동으로 찾아주는 Spring의 변환 관리 서비스.
Converter와 HttpMessageConverter의 차이
- Converter:
- 데이터 타입 간 변환.
- String → Integer, String → LocalDate 등 간단한 데이터 변환에 초점.
- HttpMessageConverter:
- HTTP 요청/응답 데이터를 변환.
- JSON → Java 객체, Java 객체 → JSON 등, 네트워크 통신에 초점.
결론
Spring의 Converter는 데이터 타입을 변환하는 단순하고 강력한 도구입니다. 데이터를 변환하는 간단한 작업부터, 프로젝트 전반에서 데이터 바인딩에 활용됩니다.
비유: 필요한 데이터를 원하는 형태로 "가공"하는 변환기입니다.
'Back-End (Web) > Spring' 카테고리의 다른 글
API 예외처리 (0) | 2025.01.19 |
---|---|
Formatter (0) | 2025.01.11 |
HttpMessageConverter (0) | 2025.01.09 |
ArgumentResolver (0) | 2025.01.08 |
[Spring] 스프링 정리 (0) | 2025.01.07 |