JPA (Hibernate)

[JPA (Hibernate)] ZonedDateTime 사용시 UTC 값으로 저장되는 이슈

DevHyo 2024. 1. 13. 14:52

문제

spring boot 3.2.1 버전을 사용하고 있으며, 이에 따라 org.hibernate.orm:hibernate-core:6.4.1.FINAL 버전을 사용하고 있었다. JVM 및 MySQL TimeZone 설정이 Asia/Seoul 값으로 되어 있음에도 UTC 값으로 저장되는 이슈였다.

Hibernate 로그 살펴보기

application.yml 파일에 아래 옵션들을 추가하고, hibernate sql 로그를 살펴보기로 했다.

logging:
  level:
    org:
      springframework:
        orm.jpa: debug
      hibernate:
        SQL: debug
        orm.jdbc.bind: trace # Spring Boot 3.x 이상 부터는 'orm.jdbc.bind' 를 사용해야 바인딩 된 쿼리 파라미터를 볼 수 있다.

TIMESTAMP_UTC?

로그를 살펴보던 도중 아래 이미지처럼 (7:TIMESTAMP_UTC) 로그를 확인했다.

TIMESTAMP_UTC 값으로 바인딩 파라미터가 되었다.

Hibernate time_zone을 변경했으나, 실패

hibernate.jdbc.time_zone 설정을 Asia/Seoul 값으로 지정했으나, 역시 실패했다.

spring:
  jpa:
    properties:
      hibernate:
        jdbc.time_zone: Asia/Seoul

우연히 찾게 된 hibernate.timezone.default_storage 옵션

Spring Boot 3.1 버전부터는 Hibernate 6.2 버전을 사용하는데, 가장 큰 변경점이 Hibernate에서 시간대(time zone) 정보를 다루는 방식이 달라졌다고 한다. Hibernate 6.2 버전부터 시간대 관련 정보는 hibernate.timezone.default_storage 옵션으로 다룬다는 점을 확인했다. 이 옵션은 내부적으로 TimeZoneStorageType 값과 매핑되고, 이를 통해 Hibernate가 시간 관련 정보를 실제 DB 테이블에 저장하고 데이터를 읽을 때, 시간 데이터를 어떤 식으로 보간하는지 조정할 수 있다고 했다.

 

만일 별다른 옵션을 주지 않았다면 hibernate.timezone.default_storage=DEFAULT 값으로 설정되고 다음과 같이 작동한다.

  • DB 레벨에서 시간대 정보를 관리할 수 있도록 지원하는 경우, 절대 시간과 시간대 정보가 DB 테이블에 함께 저장된다.
    • TimeZoneStorageType.NATIVE
  • DB 레벨에서 시간대 정보를 관리하지 않는 경우, UTC 시간대로 보간해서 시간 정보가 저장된다.
    • TimeZoneStorageType.NORMALIZE_UTC

더 자세한 정보는 https://techblog.lycorp.co.jp/ko/how-to-migrate-to-spring-boot-3 링크에서 확인하면 된다.

hibernate.timezone.default_storage=NORMALIZE 적용

NORMALIZE 옵션을 적용하기로 했는데, 이유는 다음과 같다.

  • 기존에 저장된 데이터와의 정합성을 보장하고, 애플리케이션 로직의 하위 호환성을 고려해서 NORMALIZE 적용
  • NORMALIZE 옵션은 시간대 정보를 6.2 이전 버전과 동일한 방식으로 설정하는 옵션으로, 데이터소스 연결 정보에 설정한 시간대 또는 JVM 기본 시간대 정보를 사용하기 때문에 이전과 동일한 방식으로 DB 테이블에 데이터를 저장할 수 있다.

@TimeZoneStorage & @TimeZoneColumn Annotations 사용해서 컬럼에 각각 매핑할 수도 있다.

결과

아래와 같은 결과를 얻을 수 있었고, DB 테이블에도 정상적인 ZoneDateTime 값이 저장되었다.

TIMESTAMP 값으로 바인딩 파라미터가 되었다.

참고 문서

https://techblog.lycorp.co.jp/ko/how-to-migrate-to-spring-boot-3

 

실전! Spring Boot 3 마이그레이션

들어가며 안녕하세요. LINE Plus에서 태국 LINE BK 채널 서버 개발 및 운영 업무를 맡고 있는 이석재입니다. LINE BK에서는 지난 9월에 LINE BK 보험 중개 서...

techblog.lycorp.co.jp

https://www.woolha.com/tutorials/hibernate-using-timezonestorage-timezonecolumn-annotations

 

Hibernate - Using @TimeZoneStorage & @TimeZoneColumn Annotations

Examples of how to use Hibernate @TimeZoneStorage and @TimeZoneColumn.

www.woolha.com