🤔 오류 내용
사용자가 Seoul 오전 9시에 알림을 설정했으나 오후 6시(18:00)에 메일이 발송되는 9시간 오차 버그.
DB 조회 결과 review_cycle.scheduled_at이 18:00으로 저장됨 (의도는 09:00).
운영(EC2) 및 로컬 환경 모두에서 발생.
근본 원인 — 3중 타임존 불일치
Clock.systemDefaultZone() → JVM 타임존 환경에 의존 (운영은 Seoul, 로컬은 불확실)
calculateScheduledAt() → notification_time(Seoul 기준 LocalTime)을 UTC LocalDateTime에 타임존 변환 없이 .with(notificationTime) 직접 적용 → UTC 09:00으로 저장
serverTimezone=Asia/Seoul + hibernate.jdbc.time_zone 미설정 → JDBC가 LocalDateTime → Timestamp 변환 시 JVM TZ(UTC)와 MySQL TZ(Seoul) 불일치 → DB에 +9h된 18:00으로 저장
기대하는 성공 상황
Seoul 오전 9시 알림 설정 시 DB review_cycle.scheduled_at이 00:00 (UTC)으로 저장되고, UTC 00:00에 스케줄러가 트리거되어 메일이 정상 발송된다.
🚩 오류 발견 위치
src/main/java/com/recyclestudy/review/service/ReviewService.java — calculateScheduledAt()
src/main/java/com/recyclestudy/common/config/TimeConfig.java — Clock 빈
src/main/resources/application.yaml — hibernate.jdbc.time_zone 미설정
Dockerfile — JVM/컨테이너 타임존 Seoul 고정
src/main/java/com/recyclestudy/email/ReviewEmailSender.java — @Scheduled zone = "Asia/Seoul"
⚠ 에러 캡쳐
DB 직접 조회 시 아래와 같이 저장됨 (Seoul 09:00 알림 설정 기준)
SELECT scheduled_at FROM review_cycle ORDER BY id DESC LIMIT 1;
-- 결과: 2026-03-XX 18:00:00 (기대값: 09:00:00)
📆 버그 수정 계획
전체 시스템을 UTC 기반으로 통일하여 해결.
-
Clock 빈 → Clock.systemUTC() 고정
-
application.yaml → hibernate.jdbc.time_zone: UTC 추가
-
Dockerfile → Seoul 타임존 설정 제거, JVM -Duser.timezone=UTC 옵션 추가
-
ReviewEmailSender → @Scheduled(zone = "UTC")
-
calculateScheduledAt() → Seoul 특정 변환 로직 제거 (notification_time을 UTC 기준으로 저장하도록 프런트 계약 변경)
-
JacksonConfig 신규 추가 → API 응답 Instant + Z suffix로 통일
-
ReviewSaveResponse, NextReviewResponse, MemberFindResponse → LocalDateTime → Instant
-
Flyway 마이그레이션 추가 → 기존 PENDING 데이터 -9h 보정
-
기한 :
🤔 오류 내용
사용자가 Seoul 오전 9시에 알림을 설정했으나 오후 6시(18:00)에 메일이 발송되는 9시간 오차 버그.
DB 조회 결과
review_cycle.scheduled_at이18:00으로 저장됨 (의도는09:00).운영(EC2) 및 로컬 환경 모두에서 발생.
근본 원인 — 3중 타임존 불일치
Clock.systemDefaultZone()→ JVM 타임존 환경에 의존 (운영은 Seoul, 로컬은 불확실)calculateScheduledAt()→notification_time(Seoul 기준 LocalTime)을 UTCLocalDateTime에 타임존 변환 없이.with(notificationTime)직접 적용 → UTC 09:00으로 저장serverTimezone=Asia/Seoul+hibernate.jdbc.time_zone미설정 → JDBC가LocalDateTime→Timestamp변환 시 JVM TZ(UTC)와 MySQL TZ(Seoul) 불일치 → DB에 +9h된 18:00으로 저장기대하는 성공 상황
Seoul 오전 9시 알림 설정 시 DB
review_cycle.scheduled_at이00:00(UTC)으로 저장되고, UTC 00:00에 스케줄러가 트리거되어 메일이 정상 발송된다.🚩 오류 발견 위치
src/main/java/com/recyclestudy/review/service/ReviewService.java—calculateScheduledAt()src/main/java/com/recyclestudy/common/config/TimeConfig.java—Clock빈src/main/resources/application.yaml—hibernate.jdbc.time_zone미설정Dockerfile— JVM/컨테이너 타임존 Seoul 고정src/main/java/com/recyclestudy/email/ReviewEmailSender.java—@Scheduled zone = "Asia/Seoul"⚠ 에러 캡쳐
DB 직접 조회 시 아래와 같이 저장됨 (Seoul 09:00 알림 설정 기준)
📆 버그 수정 계획
전체 시스템을 UTC 기반으로 통일하여 해결.
Clock빈 →Clock.systemUTC()고정application.yaml→hibernate.jdbc.time_zone: UTC추가Dockerfile→ Seoul 타임존 설정 제거, JVM-Duser.timezone=UTC옵션 추가ReviewEmailSender→@Scheduled(zone = "UTC")calculateScheduledAt()→ Seoul 특정 변환 로직 제거 (notification_time을 UTC 기준으로 저장하도록 프런트 계약 변경)JacksonConfig신규 추가 → API 응답Instant+Zsuffix로 통일ReviewSaveResponse,NextReviewResponse,MemberFindResponse→LocalDateTime→InstantFlyway 마이그레이션 추가 → 기존 PENDING 데이터 -9h 보정
기한 :