데이터 구조나 오브젝트 상태를 동일하거나 다른 컴퓨터 환경에 저장하고 나중에 재구성할 수 있는 포맷으로 변환하는 과정
자바 직렬화란 자바 시스템 내부에서 사용되는 객체 또는 데이터를 외부의 자바 시스템에서도 사용할 수 있도록 바이트(byte) 형태로 데이터 변환하는 기술과 바이트로 변환된 데이터를 다시 객체로 변환하는 기술(역직렬화)을 아울러서 말합니다.
시스템 적으로는 JVM(Java Virtual Machine)의 메모리에 상주(heap 또는 stack) 되어 있는 객체 데이터를 바이트 형태로 변환하는 기술과 직렬화된 바이트 형태의 데이터를 객체로 변환해서 JVM으로 상주시키는 형태를 말합니다.
ISO-8601
날짜,시간과 관련된 데이터 교환을 다루는 국제 표준
문제 발견
프론트에서 스프링부트 기반의 서버로 AJAX 요청을 해서 동일한 2가지 시간 값을 받았는데, 하나는 UTC형식(ISO-8601을 통한 직렬화), 하나는 스트링형식으로 오는 문제가 발견됐다..! (내가 원하는건 한국표준시의 시간이다.)
한국표준시로 바꾸면 둘의 시간은 같다.
- UTC 형식의 데이터 : 2023-10-23T01:50:00.000+00:00
- String 형식의 데이터 : 2023-10-23 10:50:00.0
두 데이터의 차이점? 두 시간 모두 UTC+0시로 저장된 데이터를 +9시를 더해서 DB에서 한국표준시로 쿼리해오는 공통점이 있지만 SELECT 시 차이점이 있었다.
UTC형식의 데이터는 TO_DATE(...) / 스트링 형식의 데이터는 TO_CHAR(...) 메서드로 쿼리를 해서 데이터를 가져오고 있었고 이를 스프링에서는 각각 TIMESTAMP와 STRING형태로 받고 있다. CONTROLLER에서 리턴할 때 까지 두 값의 TIMEZONE이 동일한지 같은 시간을 나타낸다.
front에서 dayjs() 라이브러리를 활용해 받은 시간의 포멧을 년/월/일 시:분으로 바꿔준다. 이 때 UTC+0은 접속한 컴퓨터의 Timezone에 따라서 시간을 더해준다. 만약 대만이라면 +8시간을 더하면서 스트링 형식의 데이터와 1시간의 차이가 발생해버린다. 스트링으로 내려온 데이터는 문자 받은데로 시간을 표기해준다(한국표준시)
해결
해결방법 1
스프링 부트의 직렬화,역직렬화 과정에서 jackson 라이브러리가 관여를 하는데 설정값을 통해 이를 변경할 수 있다.
스프링부트 설정파일(.yml)에 다음 값을 추가해서 타임존을 강제로 지정해준다.
yml파일의 경우 설정방법
spring.jackson.deserialization.adjust-dates-to-context-time-zone : jackson 라이브러리에 시간대를 조정하지 않도록 하는 옵션
spring.jackson.time-zone : jackson의 타임존을 지정하는 옵션
해결방법 2 🎉채택🎉
날짜 데이터를 String 형태로 내려준다.
채택 이유 : 해결방법1에서 타임존을 서울로 지정해도 프론트에서 ISO-8601포멧이기 때문에 UTC로 내려와서 변환을 해줘야하는데 이건 앞의 dayjs문제가 발생한다
dayjs의 timezone을 설정하는 라이브러리가 있긴한데 패스했따.
요약
직렬화,ISO-8601포멧이 범인임
스프링부트2 , 스프링5이상에서 직렬화,역직렬화를 하는 라이브러리가 바뀜(jackson-databind > spring-boot-starter-json)
timestamp(long) 형식으로 직렬화 > ISO-8601 포멧으로 직렬화 하는걸로 바뀜