Java에서 `TypeReference` 사용하기

YuJun Oh·2024년 11월 13일
0

Java에서 JSON 문자열을 ObjectMapper를 사용해 자바 객체로 변환할 때, 특히 ListMap 같은 제네릭 타입을 다룰 때 TypeReference는 꼭 필요한 도구입니다. 이 글에서는 TypeReference가 왜 필요한지, 이를 사용할 때 얻는 이점, 그리고 TypeReference를 활용한 예제를 통해 그 활용법을 알아보겠습니다.

TypeReference가 필요한 이유

Java에서는 제네릭 타입 정보가 컴파일 시점에 소거(Type Erasure)되므로, 런타임에서는 제네릭 타입에 대한 구체적인 정보를 알 수 없습니다. ObjectMapper는 JSON 데이터를 자바 객체로 매핑하는 과정에서 타입 정보를 기반으로 각 필드를 적절한 타입으로 변환합니다. 하지만 다음과 같은 경우 문제가 발생할 수 있습니다:

String json = "[{\"name\":\"Alice\", \"age\":30}, {\"name\":\"Bob\", \"age\":25}]";
List<Person> personList = objectMapper.readValue(json, List.class);

위 코드에서는 List<Person>로 변환하고자 했지만, ObjectMapper는 타입 정보를 충분히 알 수 없어 List의 원소를 LinkedHashMap으로 반환하게 됩니다. 이로 인해 Person 클래스의 필드에 접근하거나 관련 메서드를 호출하는 것이 불가능해집니다.

이럴 때 TypeReference를 사용하면 제네릭 타입 정보를 포함한 변환이 가능합니다.

TypeReference 사용 예제

아래의 예제에서는 ObjectMapperTypeReference를 사용해 JSON 데이터를 List<Person>으로 정확하게 변환해 보겠습니다.

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;

class Person {
    private String name;
    private int age;

    // Getters, Setters, toString()
}

public class TypeReferenceExample {
    public static void main(String[] args) throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();

        // JSON 문자열
        String json = "[{\"name\":\"Alice\", \"age\":30}, {\"name\":\"Bob\", \"age\":25}]";

        // TypeReference를 사용하여 JSON을 List<Person>으로 변환
        List<Person> personList = objectMapper.readValue(json, new TypeReference<List<Person>>() {});
        System.out.println("personList = " + personList);
    }
}

출력 결과

personList = [Person{name='Alice', age=30}, Person{name='Bob', age=25}]

위 예제에서 TypeReference<List<Person>>을 사용하여 JSON 문자열을 List<Person> 타입으로 변환했습니다. TypeReference가 없으면 ObjectMapperList 타입으로만 인식하게 되어 Person 객체로 변환하지 못합니다.

TypeReference의 장점

  1. 제네릭 타입 유지: TypeReference는 제네릭 타입 정보를 유지해 주므로, 원하는 구체 타입으로 정확히 매핑할 수 있습니다.
  2. 코드 가독성 향상: 제네릭 타입이 포함된 데이터를 변환할 때, TypeReference를 통해 원하는 타입을 명확히 지정하므로 코드의 가독성이 높아집니다.
  3. 타입 안정성 제공: 변환 과정에서 제네릭 타입을 유지함으로써 타입 안정성을 제공하고, 캐스팅 오류를 예방합니다.

TypeReference와 다른 활용 예

Map<String, List<Person>> 타입으로 변환하기

TypeReference는 중첩된 제네릭 타입도 변환할 수 있습니다. 예를 들어, JSON 데이터를 Map<String, List<Person>>으로 변환하는 경우입니다.

String json = "{\"teamA\":[{\"name\":\"Alice\",\"age\":30}], \"teamB\":[{\"name\":\"Bob\",\"age\":25}]}";

Map<String, List<Person>> teams = objectMapper.readValue(json, new TypeReference<Map<String, List<Person>>>() {});
System.out.println("teams = " + teams);

이 예제에서도 TypeReference를 사용하여 JSON 데이터를 중첩된 제네릭 타입 Map<String, List<Person>>으로 정확히 변환할 수 있습니다.

TypeReference 사용 시 주의사항

  • 익명 클래스 사용: TypeReference는 추상 클래스로, 인스턴스화할 때 항상 익명 클래스로 선언해야 합니다.
  • 성능: TypeReference 사용 시, ObjectMapper는 타입 분석을 위한 추가적인 처리가 필요할 수 있어 약간의 성능 비용이 있을 수 있습니다. 그러나 이는 제네릭 타입 변환의 정확성에 비해 미미한 비용입니다.

결론

TypeReference는 JSON 데이터를 복잡한 제네릭 타입으로 변환할 때 매우 유용합니다. 이를 통해 구체적인 타입을 정확히 지정할 수 있으며, 코드의 가독성과 안정성 또한 높일 수 있습니다.

0개의 댓글

관련 채용 정보