지도 기반 프로젝트를 진행하면서 RestClient를 사용해서 카카오맵 API를 통해 리버스 지오코딩을 하고 있다.

지오코딩(geocoding)은 주소를 좌표로 변환하는 작업, 리버스 지오코딩은 반대로 좌표를 주소로 변환하는 것을 말한다. 

 

카카오맵 API는 기본적으로 Json 형식으로 응답을 하는데 응답받은 데이터를 사용하기 위해 역직렬화하여 객체로 변환하는 작업이 필요하며 이를 위해 JsonDeserializer를 사용해보았다.

 

먼저 스프링에서 HTTP RequestBody, ResponseBody의 데이터를 직렬화, 역직렬화하는 기능은 메시지 컨버터가 처리한다.

 

아래 공식 문서 내용을 보면 RestClient를 builder()로 생성할 수 있고, 메시지 컨버터를 포함한 여러 설정을 할 수 있다.

스프링에서 제공하는 메시지 컨버터 인터페이스 HttpMessageConverter는 클라이언트 사이드(ex. RestClient)와 서버 사이드(ex. RestController)에서 HTTP 요청, 응답의 body를 읽고 쓰는 역할을 하며 다양한 구현체들이 있다.

 

 

RestClient는 기본적으로 등록되어있는 메시지 컨버터를 사용하고 추가로 확장할 수도 있다. 등록된 메시지 컨버터 중에 canRead()를 통해 변환이 가능한 컨버터를 찾아서 처리를 한다.

MappingJackson2MessageConverter는 기본적으로 내장된 컨버터로 json 데이터를 변환하는 작업을 해주며 내부적으로 ObjectMapper(Jackson 라이브러리)를 사용한다. ObjectMapper도 canDeserialize()를 통해 deserialize가 가능한지를 체크한다.

 

카카오맵 API의 Json 응답 예시를 보면 SnakeCase 표기법으로 되어 있는데 기본적으로는 CamelCase 표기법으로 읽기 때문에ObjectMapper에 별도로 setPropertyNamingStrategy()로 설정을 해줘야 한다. 

 

Jackson 라이브러리는 이러한 설정을 간편하게 할 수 있도록 @JsonNaming과 같은 애노테이션을 지원해준다.

ObjectMapepr는 직렬화시 Getter가 있어야 하고 역직렬화 시 기본 생성자와 Setter가 있어야 하는 등의 조건이 있는데(필수는 아니지만) Jackson 2.12 버전부터 Record 타입을 지원해 주면서 편하게 불변으로 사용할 수 있다. 

 

이런 식으로 key-value에 맞춰서 클래스를 생성해 주면 되는데 depth가 깊어지면 복잡해지기 때문에 JsonDeserializer를 구현해서 직접 역직렬화를 해줄 수 있다. JsonDeserializer를 extends하고 deserialize()을 Override해준다.

 

jsonParser.getCode()을 통해 ObjectCodec(ObjectMapper 부모 클래스)의 readTree()를 호출하면 트리 구조의 JsonNode를 받을 수 있다. (해당 노드는 Json 데이터를 파싱한 것이다)

 

_children은 Json 각 객체({}) 내부 key-value를 LinkedHashMap으로 관리하기 때문에 순서를 보장해 주며 같은 depth에 같은 key가 여러 개면 마지막 key만 담긴다.

 

findValue()는 특정 key의 value를 찾아서 가장 먼저 나오는 결과를 반환해 주는 메서드로 결과가 없으면 null을 반환한다.

 

하위 _children의 entry를 반복문으로 도는데 각각의 entry를 재귀 호출하기 때문에 depth 우선이 아닌 객체({}) 기준으로 가장 먼저 나오는 key의 value를 반환한다.

 

내 경우에는 가장 상단에 있는 값이 필요해서 findValue()를 사용했다.

 

마지막으로 위에서 구현한 JsonDeserializer를 필요한 클래스에 애노테이션으로 선언해 주면 된다.

 

이렇게 @JsonDeserialize 애노테이션을 선언해주면 MappingJackson2HttpMessageConverter에서 내부적으로 @JsonDeserialize 애노테이션을 찾아서 적용을 해준다.

 

[참고]

 

 

Jackson 라이브러리 기본기능 정리 - json 직렬화와 역직렬화

Jackson Annotation 예제 본 글은 다음 원문을 번역 및 수정한 글입니다. https://www.baeldung.com/jackson-annotations 전체 코드는 다음 레파지토리에 있습니다. 필요하다면 클론 받으셔서 test 패키지에 있는 Jack

pjh3749.tistory.com

 

Jackson Release 2.12

Main Portal page for the Jackson project. Contribute to FasterXML/jackson development by creating an account on GitHub.

github.com

 

Jackson Deserializer 코드 분석해보기 | 카카오페이 기술 블로그

Json 공백 문자 제거 및 파싱을 개발하면서 Jackson Deserializer 코드를 분석해봅니다.

tech.kakaopay.com

 

+ Recent posts