피드로 돌아가기
컬리 기술블로그Backend
원문 읽기
하이버네이트의 시간은 거꾸로 간다
컬리 배송팀이 스프링부트 3.x 업그레이드 후 하이버네이트 LocalTime 변환 로직의 타임존 기반 음수 나노초 버그로 인한 로그인 장애 발생 및 임시 Converter 적용으로 해결
AI 요약
Context
AWS MSK 버전 업그레이드에 대응하기 위해 스프링부트를 2.6.4에서 3.2.4로 업그레이드했습니다. 배포 후 QA를 통과했으나 다음 날 자정 직전에 샛별 배송 시간대에 배송 매니저의 컬리버드 앱 로그인이 불가능한 장애가 발생했습니다.
Technical Solution
- 하이버네이트 버전 업그레이드에 따른 LocalTime 저장 로직 변경 파악: 하이버네이트 5.6.5에서 6.5.5로 업그레이드되면서 LocalTimeJavaType.unwrap 메서드에서 나노초를 무시하던 방식에서 LocalTime의 나노초를 Time 객체의 밀리초에 반영하는 방식으로 변경
- 타임존 기반 음수 fastTime 발생 메커니즘 규명: LocalTime을 Time으로 변환 시 기본 날짜(1970-01-01 00:00:00 UTC)를 기준으로 하는데, KST 타임존에서 UTC 기준 맞춤을 위해 9시간을 빼면서 0~8시 구간에서 fastTime이 음수가 되고, 이를 1,000으로 나눈 나머지로 계산된 ms 값이 음수가 되는 구조 파악
- LocalTime 조회 시 음수 나노초 예외 발생 조건 특정: KST 타임존 + 0~8시 시간대 + 나노초 존재 + 소수점 3자리 나노초 조합에서만 java.time.DateTimeException 발생 확인
- 임시 해결책으로 Converter 구현 적용: LocalTimeConverter를 구현하여 데이터 저장 및 조회 시 ChronoUnit.SECONDS로 truncatedTo 처리하여 나노초를 제거하는 방식으로 문제 회피
- 향후 영구 해결책 대기: 하이버네이트에서 수정된 버그 픽스 버전이 릴리즈되면 하이버네이트 버전 업그레이드 예정
Key Takeaway
메이저 버전 업그레이드 시 라이브러리의 내부 변환 로직 변경이 특정 환경(타임존, 시간대) 조합에서 예상 밖의 버그를 야기할 수 있으므로, 인수 테스트와 통합 테스트를 통해 배포 전 다양한 시나리오를 검증하는 것이 중요합니다.
실천 포인트
LocalTime 같은 시간 타입을 사용하는 JPA Entity를 운영하는 팀에서 Hibernate 메이저 버전 업그레이드 시, 타임존별·시간대별로 나노초를 포함한 데이터의 저장 및 조회 테스트를 수행하면 유사한 타임존 기반 변환 버그를 조기에 발견할 수 있습니다.