기존까지는 GIS 데이터를 지도에 올릴 때 api를 요청하여 JSON 형태로 가져오거나, WMS 레이어로 데이터 자체를 레이어로 올렸다.
이번 프로젝트에서는 postgreSQL에서 지도 정보(폴리곤, 네트워크, poi 등)를 select 해 와 지도에 표출해야 했다.
postgreSQL의 데이터는 프론트에서 조회하여 처리하는 것보다 백엔드인 SpringBoot를 사용하여 처리하는 것이 더 효율적이기에 Jackson을 사용하여 데이터를 조회하고, 조회한 데이터를 JSON 형태로 변환하여 프론트엔드로 전달하였다.
해당 포스팅은 Jackson 사용 과정에서 발생했던 오류와 해결 과정을 정리하려고 한다.
프로젝트 환경
- SpringBoot frame work 3.3.0
- JDK 17
- IntelliJ 2023.1
- MongoDB
- JavaScript
- node.js
- vite
발생 이슈 확인 및 원인 파악
Jackson은 간단하게 설명하자면 다음의 과정을 매우 편리하게 해주는 라이브러리이다.
- 직렬화(Serialize): Java 클래스 → JSON
- 역직렬화(Deserialize): JSON → Java 클래스
하지만 Jackson을 사용할 때 Java 8 이상의 버전을 사용하면 LocalDate, LocalTime, LocalDateTime 데이터의 직렬화/역직렬화가 정상적으로 처리되지 않는다.
이 문제는 Jackson이 Java 8 LocalDateTime을 지원하지 않기 때문이다.
[ERROR][o.a.c.c.C.[.[.[.[dispatcherServlet]:175][] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class java.time.LocalDateTime]] with root cause com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type java.time.LocalDateTime not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through reference chain: java.util.ArrayList[0]->org.(생략)["createDt"])
에러 창을 잘 확인해보면 add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" 라고 친절하게 jackson-datatype-jsr310 설정을 주입하라고 알려준다.
이슈 해결
gralde 파일의 dependencies에 필요한 모듈을 추가한다.
버전은 본인이 사용하는 프로젝트에 맞추어 변경하면 된다.
실제로 프로젝트를 같이 진행했던 동료 분과 필자의 인텔리제이의 버전 차이 때문에 gradle 설정이 동일하게 적용되지 않는 상황이 있었다.
// Jackson for JSON processing
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.16.1'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310'
✨ com.festerxml.jackson.core:jackson-databind
JSON 구조 데이터에 대한 데이터 바인딩을 Java 객체에 제공하는 핵심 라이브러리이다.
JSON 데이터 → Java Object 또는 Java Object → JSON 데이터로 직렬화/역직렬화를 가능하게 한다.
✨ com.festerxml.jackson.datatype:jackson-datatype-jsr310
Jackson에서 Java 8 LocalDate, LocalTime, LocalDateTime API를 지원하는 확장 라이브러리이다.
해당 날짜/시간 개체를 JSON 데이터로 직렬화/역직렬화 할 수 있다.
해당 라이브러리를 gradle에 추가한 후, 이슈가 발생하는 LocalDateTime이 존재하는 객체 파일을 수정한다.
@Getter
@Setter
@ToString
public class timeDateSample {
@Id
private String id;
@JsonSerialize(using = LocalDateTimeSerializer.class) // 직렬화 시 필요
@JsonDeserialize(using = LocalDateTimeDeserializer.class) // 역직렬화 시 필요
@JsonFormat(pattern = "yyyy-MM-dd kk:mm:ss") // 원하는 형태의 LocalDateTime 설정
// "2024-07-08 09:59:01"
private LocalDateTime createDt;
}
위와 같이 LocalDateTime 형의 데이터에 어노테이션을 사용하면 에러 없이 프론트 엔드와 백엔드가 서로 날짜/시간 데이터를 잘 주고 받는다.
특히, @JsonFormat을 어떻게 설정하였는지에 따라, 날짜/시간 데이터의 직렬화/역직렬화 형태가 달라진다. 포맷 형태를 @JsonFormat(pattern = "yyyy-MM-dd")라고 작성하면 "2024-07-08"로 출력된다.
버전이나 사용법에 따라 어노테이션의 사용이 다를 수 있다.
필자가 진행하고 있는 프로젝트는 프론트엔드에서 넘어온 LocalDateTime을 가지고 백엔드에서 mongoDB의 데이터를 조회하여 반환하는 기능을 구현하였다.
이때, @JsonFormat 어노테이션만 사용하였다.
model 파일 수정까지 완료 후, 프로젝트 내에서 LocalDateTime을 자동으로 변환하여 사용할 수 있게 되었다.
[ 참고 ]
- https://perfectacle.github.io/2018/01/16/jackson-local-date-time-serialize/
- https://green-bin.tistory.com/63
- https://velog.io/@jay_be/JAVA-8-LocalDateTime-직렬화역직렬화-문제-해결
'공부 기록 > Java' 카테고리의 다른 글
[Java] Javadoc에 대해서 알아보자 (0) | 2023.07.21 |
---|---|
[Spring Boot] @RequestParam 사용하기 (0) | 2023.06.29 |
[Java] lambda식을 이용하여 map 사용하기 (0) | 2023.05.02 |
SDK와 JDK의 차이 (0) | 2023.04.25 |
Streams를 사용하여 Map 활용하기 (0) | 2023.04.10 |