[Java] jackson 라이브러리는 왜 non-static Inner class를 매핑하지 못할까?

2022. 3. 1. 23:21개발공부/Java

728x90

프런트와 http로 통신할 때 JSON 형식으로 데이터를 받는 경우가 많습니다. 객체지향언어인 Java에서 객체로 바인딩 하는 문제를 도와주는 라이브러리 중 하나인 jackson은 대표적인 ObjectMapper 클래스를 제공합니다.

ObjectMapper 클래스는 JSON을 읽기, 쓰기 기능 뿐만아니라 JSON Tree Model인 JsonNode 형태 가공해주기도 합니다.

기본적인 jackson 라이브러리에 대한 설명은 마치고, 다룰 주제인 non-static Inner class인 경우 convertValue(Object fromValue, Class<T> toValue) 메서드에서 왜 com.fasterxml.jackson.databind.exc.InvalidDefinitionException를 날리는지 알아보겠습니다.

Inner class? static?

jackson 외에 Hibernate 프레임워크에서도 non-static Inner class의 경우 데이터 바인딩을 해주지 못합니다.

Java Inner Class엔 3가지 종류가 있습니다. Anonymous, non-static, static 입니다. Anonymous는 익명 내부 클래스이며 하나의 인터페이스나 추상 클래스를 구현하는 용도로만 쓰입니다.

non-static과 static inner class는 동일한 하나의 copy가 쓰이는 정적이란(static) 외에도 차이가 있습니다. 바로 non-static inner class는 보이지 않는 변수(hidden variable)들이 생성자(hidden)를 통해 컴파일러가 추가한다는 것입니다.
그 결과로 사실상 final 전역변수가 있기 때문에 기본 생성자가 없는 상태에 놓이게 됩니다.


public class Period {

    class Monthly {
        public int getMonths() {
            return 1;
        };
    }
}

위와 같은 코드가 있다면, 컴파일러는 아래와 같이 생성해주게 됩니다.


public class Period { ... }

class Period$Monthly {

    private final Period parent;

    Period$Monthly(Period p) {
        parent = p;
    }

    public int getMonths() {
        return 1;
    };
}

왜냐하면 이렇게 될 경우 inner class인 Monthly 클래스가 외부 클래스인 Period 클래스의 모든 변수들(private 일지라도)에 대해 접근할 수 있는 권한을 가지기 때문입니다.

이와 달리 static inner class는 컴파일링 시 숨겨진 variable이나 생성자가 없습니다.

결국 jackson 라이브러리가 non-static inner class에 대해 exception을 던지는 이유는, 기본 생성자가 없어 객체를 초기화 시키지 못하기 때문입니다.(instantiate class) 따라서 inner 클래스를 JSON 매핑해줄 경우 static을 명시해야함을 알 수 있습니다.


참고자료