[Spring] @JsonCreator 없이 immutable하게 역직렬화하기

배경지식

 Spring Boot에서 json으로 rest api 통신을 하기 위해서 DTO를 이용하는데, http통신시에 직렬화, 역직렬화되는 과정에 대해서 원래 다음과 같은 사실들을 알고 있었다.

 

- 직렬화, 역직렬화를 위해서 Jackson이라는 라이브러리가 많이 사용되며, Jackson 내부에서는 ObjectMapper가 Java Reflection을 사용한다.

- Jackson이 직렬화, 역직렬화를 하기 위해서는 DTO에 default constructor와 getter, setter가 필요하다. Default constructor를 통해서 객체 접근/생성이 이루어지고, getter와 setter를 통해서 field들에 대한 접근이 이루어진다.

- Setter를 사용하게 되면 객체의 불변성을 유지할 수 없다는 문제가 있다. 객체의 불변성을 유지하면서 역직렬화가 정상적으로 동작하기 위해서는 다른 생성자로 대체하여 접근하는 과정이 필요한데, 이 과정에서 @JsonCreator와 @JsonProperty 어노테이션을 사용할 수 있다.

- @JsonCreator를 파싱을 원하는 생성자에 붙여주고, @JsonProperty(name="var")와 같이 파라미터에 매핑할 필드명을 세팅해주면 Jackson이 파싱한 데이터를 적절한 위치에 넣어줄 수 있다.

 

 

 그런데 프로젝트 진행 중에 DTO에 기본 생성자가 없어도 역직렬화 과정에서 오류가 나지 않는 것을 발견했다.

 

 

기본 생성자가 없어도 오류가 나지 않는데?

 

위에 있는 LoggingResponse는 분명 기본 생성자가 존재하지 않지만, 통신시에 정상적으로 통신이 되는 것을 볼 수 있었다. 

 

 

코틀린에 내가 모르는 기능이 있을까 싶어 자바로도 간단하게 테스트해보았는데도 결과는 동일했다. @Getter만 존재하는데 어떻게 데이터가 역직렬화되는걸까?

 

 

 

해결

찾아본 이유를 간단하게 요약하면 다음과 같다.

 

- 앞서 말했듯 Jackson라이브러리는 ObjectMapper를 사용하는데, ObjectMapper는 java reflection 패키지를 사용하기 때문에(동적 바인딩을 통해서 클래스 정보를 가져올 수 있기 때문에) 기본 생성자가 없어도 된다.

- '기본생성자가 없어도 된다'라는 말은 두 가지 가능성이 있는데, Jackson 라이브러리가 기본 생성자 없이도 다른 생성자로 대체하여 역직렬화를 수행할 수 있게 해주고 있거나(현재 DTO에 @AllArgsConstructor가 존재한다), java reflection을 통해서 동적으로 기본 생성자를 사용하고 있을 것이다라고 예상했다.

- 아래 문서에서, jackson-modules-java8의 parameter-names라는 모듈에서 기본 생성자가 없이도 다른 생성자로 대체하여 역직렬화를 수행할 수 있게 해줌을 알 수 있었다.

 

https://elvisciotti.medium.com/jackson-deserialize-immutable-objects-with-lombok-value-annotation-without-jsonproperty-f7ee1babf51e

 

 

 

 

 

참고: https://elvisciotti.medium.com/jackson-deserialize-immutable-objects-with-lombok-value-annotation-without-jsonproperty-f7ee1babf51e

 

Jackson: deserialize immutable objects with Lombok Value annotation (without JsonProperty)

The problem

elvisciotti.medium.com

https://github.com/FasterXML/jackson-modules-java8/tree/2.16/parameter-names

https://codingwell.tistory.com/182

 

테스트 깃헙: https://github.com/eckrin/various-tests

 

GitHub - eckrin/various-tests: 스프링과 자바 공부를 위한 테스트 프로젝트

스프링과 자바 공부를 위한 테스트 프로젝트. Contribute to eckrin/various-tests development by creating an account on GitHub.

github.com