[Spring] API 응답과 DB의 시간대 불일치 2

하원·2025년 2월 11일
post-thumbnail

안녕하세요, 하원입니다.
저번에 API 시간대 오류 관련 포스팅을 올린 적이 있었는데요, 이번에 한 번 더 유사한 오류가 발생해서 포스팅을 하나 더 올려보려고 합니다.


문제 상황

  • API 응답으로 온 LocalDateTime이 한국 시간대(KST)가 아닌 미국 시간대(UTC)로 출력되고 있는 상황

DB 시간대 확인

select NOW();
  • MySQL의 시간대를 확인할 수 있습니다.
  • 정상적인 경우에는 현재 한국 시간대가 출력됩니다.

select @@global.time_zone, @@session.time_zone;
  • global은 MySQL 서버의 기본 시간대를 의미하고, session은 연결된 클라이언트에서만 유효한 시간대를 의미합니다.
  • 정상적인 경우에는 Asia/Seoul이라고 출력됩니다.

시도한 방법

1. 일시적으로 시간대 변경

set time_zone = 'Asia/Seoul';
set GLOBAL time_zone = 'Asia/Seoul';
  • 세션 및 글로벌 시간대를 변경하는 코드입니다.
  • 일시적으로 시간대를 변경하는 것이기 때문에 MySQL 서버를 재시작하면 다시 초기화됩니다.

2. MySQL 설정 파일 수정

sudo vim /etc/mysql/my.cnf
  • MySQL의 글로벌 시간대를 영구적으로 변경하기 위해 MySQL의 설정 파일인 my.cnf 파일을 수정해 줍니다.
[mysqld]
default-time-zone = 'Asia/Seoul'
  • my.cnf 파일에 위와 같은 코드를 추가하면 타임존이 설정된다고 합니다.

해결 X

  • 위 과정을 모두 시도해 보면서 MySQL의 세션 및 글로벌 시간을 모두 KST로 변경하였음에도 불구하고 API의 LocalDateTime이 여전히 UTC로 전달되고 있었습니다.

해결 방법

@PostConstruct 사용

@SpringBootApplication
public class BeApplication {

	@PostConstruct
	public void started() {
		TimeZone.setDefault(TimeZone.getTimeZone("Asia/Seoul"));
	}

	public static void main(String[] args) {
		SpringApplication.run(BeApplication.class, args);
	}
}

@PostConstruct

  • 메서드에 @PostConstruct를 붙이면 Spring Bean이 초기화된 후 실행됩니다.
  • 위 코드에서는 스프링 컨텍스트가 실행되면서 started()가 실행됩니다.
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Seoul"));
  • 위 코드는 JVM의 시간대를 설정하는 코드입니다.

결론

분명 JVM 시간대도 KST로 설정하고, MySQL 시간대도 KST로 설정했는데 계속 UTC 시간대로 설정되는 것 같았습니다. Spring Application이 실행될 때 JVM의 시간대가 UTC로 설정될 수도 있다고 하여 @PostConstruct를 사용하여 강제로 JVM의 시간대를 KST로 설정하였습니다.

결과적으로 이제 API 응답에 KST 시간대로 전달되었습니다. 블로그를 찾아보니 저와 같은 현상을 겪으신 분들이 꽤 있으셔서 도움이 되었으면 합니다.


마무리

API 시간대 오류 포스팅을 2개나 작성하게 되었다. 오류는 언제 어디에서나 발생할 수 있다는 사실을 유념해야겠다. 사실 이런 경험들을 쌓아나가는 것도 한편으로는 다행이라고 생각한다.


참고

profile
호기심 저장소

0개의 댓글