- JPA 에서 DATETIME 변수를 다룰 때는 자동으로 TimeZone 을 맞춰줍니다.
예를들어 JPA 가 돌아가는 Springboot 의 타임존 설정이 UTC,
데이터베이스가 KST 시간을 사용중이라고 했을 때,
JPA 에서 UTC 시간인 2024-05-02 03:38:46.026 를 데이터베이스에 입력하면,
데이터베이스에는 실제로는 KST 시간인 2024-05-02 12:38:46.026 가 저장이 되며,
데이터베이스에서 KST 시간인 2024-05-02 12:38:46.026 를 조회하면,
UTC 시간을 사용중인 스프링부트 시스템에 맞춰서 JPA 는,
2024-05-02 03:38:46.026 라고 데이터를 변환해줄 것입니다.
- Springboot 에서의 타임존 설정은,
@SpringBootApplication
class ApplicationMain {
@Bean
fun init() = CommandLineRunner {
// 서버 타임존 설정
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Seoul"))
}
}
fun main(args: Array<String>) {
// 서버 실행
runApplication<ApplicationMain>(*args)
}
위와 같이 Springboot Main 파일 안에서 TimeZone.setDefault 를 하면 설정이 됩니다.
- Database 에서의 타임존 설정은 해당 데이터베이스 내에서 설정을 하면 됩니다.
이에 연결하는 Springboot 는 해당 설정을 알수 없으므로, JPA 연결시 이를 설정해주어야 합니다.
만약 데이터베이스 타임존을 Asia/Seoul 로 했다면,
JPA 에서 데이터베이스에 연결할 때 사용하는 URL 에,
jdbc:mysql://localhost:3306/first_schema?serverTimezone=UTC
위와 같이 해당 데이터베이스가 사용중인 타임존 설정을 serverTimezone 파라미터에 입력 해주면 됩니다.
- 위의 예시에서 Springboot 는 Asia/Seoul, 데이터베이스 및 JPA 설정에는 UTC 로 설정되어있다고 가정하겠습니다.
서버 코드로 LocalDatetime.now() 로 현재 시간을 가져온다면 이는 Asia/Seoul 의 현 시간인데,
이를 UTC 기준 데이터베이스에 입력하려면 당연히 타임존 변환 후 저장을 해야겠죠?
만약 지금이 Asia/Seoul 기준 19시라면, UTC 기준으로는 -9시간을 하여 10시가 되는 것입니다.
원래라면 이렇게 변환을 거쳐서 입력을 하고,
또한 UTC 로 저장된 날짜 데이터를 조회할 때에는 +9 를 하여 다뤄야 하지만,
JPA 에서 serverTimezone 을 설정하여 데이터베이스의 타임존을 설정해주었다면,
입 출력시에 자동으로 변환이 됩니다.
- 테스트를 하고 싶다면, 앞서 설명대로,
Springboot 타임존을 Asia/Seoul 로 설정하고,
datasource.{데이터베이스}.jdbcUrl 에 serverTimezone 설정을 UTC 로 설정한 상태에서,
JpaRepository 를 사용하여 save 해보세요.
만약
@Column(name = "test_datetime", nullable = false, columnDefinition = "DATETIME(3)")
@Comment("테스트용 일시 데이터")
var testDatetime: LocalDateTime
위와 같은 DATETIME 변수에,
2024_05_02_T_19_00_00_000
을 입력했다고 합시다.
아니, LocalDateTime.now() 로 현재 시간(Springboot 기준의 KST 타임존 현재 시간)이 위와 같다고 합시다.
이렇게 JpaRepository 를 거쳐서 저장된 날짜값은 KST 기준 날짜가 UTC 기준으로 변환된(-9시간)
2024_05_02_T_10_00_00_000 이 저장되어 있는 것을 볼 수 있습니다.
- 주의할 점은, serverTimezone 설정은 실제 데이터베이스 설정과 동기화 되지 않습니다.
무슨 의미냐면, 실제로 데이터베이스가 KST 시간을 써도, serverTimezone 설정을 UTC 로 적는다면,
JPA 날짜 변환 기준은 본 서버 타임존과 serverTimezone 설정을 기준으로 한다는 것으로 이 설정을 수동으로
데이터베이스에 맞추는 것이 중요하다는 것입니다.
데이터베이스에서 현재 설정된 타임존을 알기 위해서는,
select @@global.time_zone, @@session.time_zone;
데이터베이스 타임존을 설정하기 위해서는
SET GLOBAL time_zone='+00:00';
SET time_zone='+00:00';
위와 같이 입력하면 됩니다.
- 추가로, serverTimezone 설정을 적지 않는다면,
JPA 는 데이터베이스의 타임존이 서버 타임존과 일치한다고 간주할 것입니다.
- 마지막으로 날짜 데이터 관련 팁입니다.
저는 날짜 데이터를 사용시 타임존을 같이 표시하고 있습니다.
예를들어 일시를 기반으로 파일명을 작명하거나, 혹은 날짜 데이터를 기록할 때,
yyyy_MM_dd_'T'_HH_mm_ss_SSS_z
위와 같은 표현 방식을 사용합니다.
이는 2024_05_02_T_14_22_23_272_KST
이렇게 일시 표현이 되며,
이를 통하여 해당 시간의 기준이 되는 타임존을 한눈에 알 수 있기에 오해를 방지할 수 있습니다.
또한, 위에서 명확한 일시 표현을 위하여,
yyyy-MM-dd_'T'_HH:mm:ss.SSS_z
이련 형식을 사용할 수도 있겠지만,
일시 데이터가 파일명으로 사용될 수 있을 경우를 생각하여 분리자를 '_' 로 표현한 것이므로,
상황에 따라 다를 테지만 거의 공통적으로 위와 같인 표현방식을 사용하면 일관성으로 인하여 편할 것이라고 생각합니다.
년, 월, 일, 시, 분, 초, 밀리초 의 경우 어디까지 표현할지에 대한 것은 상황에 맞게 선택하세요.
저는 보통 시간 저장시 밀리초 3자리 까지 저장하는데, 때에 따라 달라질 수도 있습니다.
- 이상입니다.
'Springboot' 카테고리의 다른 글
Springboot JavaMailSender 로 이메일 보내기 (PlainText 발송, 첨부파일 발송, Thymeleaf HTML 이메일 발송) (2) | 2024.10.08 |
---|---|
Springboot 에서 AWS S3 다루기 (1) | 2024.10.08 |
Springboot MongoDB 설정하기 (멀티 소스 데이터베이스 접속, MongoDB ReplicaSet 접속 및 트랜젝션 Annotation 작성) (0) | 2024.10.08 |
Springboot JPA 설정하기 (멀티 소스 데이터베이스 접속 및 트랜젝션 Annotation 작성) (2) | 2024.10.08 |
Springboot 프로젝트 Docker 로 배포하기 (1) | 2024.09.30 |