서론
spring에서 mongo DB에 Document의 LocalDateTime 필드를 저장하면 UTC의 시간으로 변환되어 들어간다.
아마 팀 컨벤션에 따라 다를 것 같은데, 우리는 mongo DB에서도 KST 한국 시간으로 보고 싶었다. 따라서 covnerter를 만들기로 했다.
기본적인 베이스는 spring이 제공하는 Spring Data MongoDB에 커스텀 컨버터를 추가하는 것이다.
https://docs.spring.io/spring-data/mongodb/reference/mongodb/mapping/custom-conversions.html
위에 잘 나와있는데 조금 더 설명을 보태자면, MongoCustomConversions이란 클래스에 커스텀 컨버터를 추가하는것이다.
그럼 컨버터는 어떤 형식으로 만들어야 할까?
살펴본 결과, Spring data mongodb는 entity를 바탕으로 Mongo DB에 저장하기 위한 Document 객체를 만들때, LocalDateTime을 Date 클래스로 변경한다.
이 때 애플리케이션 쪽에선 여전히 시간이 Local 설정을 따른다.
따라서 MongoDB에 데이터를 보내기 전까지는 여전히 KST인데.. MongoDB에 들어가면서 MongoDB가 해당 시간을 UTC로 변환시켜버린다.
즉, UTC는 KST - 9 이기 때문에, 우리가 보낸 시간에서 9시간을 빼버린다는 뜻이다.
그렇다면, 우리가 애초에 Date를 보낼 때 9시간을 추가해서 보내면.. MongoDB가 9시간을 빼면 KST가 되지 않을까?
즉, 우리가 KST로 2023-12-01 09:00:00로 Mongo DB에 저장하고 싶지만, 이대로 보내면 Mongo DB에는 2023-12-01 00:00:00으로 저장된다.
따라서, 2023-12-01 09:00:00에 9시간을 더한, 2023-12-01 18:00:00로 보내면
Mongo DB에는 9시간 빼면서 2023-12-01 09:00:00인 KST로 저장되지 않을까? 라는 것이다.
구현
위의 아이디어에 따라 WritingConverter를 만들었다.
package com.example.demo
import org.springframework.core.convert.converter.Converter
import org.springframework.data.convert.WritingConverter
import org.springframework.stereotype.Component
import java.sql.Timestamp
import java.time.LocalDateTime
import java.util.Date
@Component
@WritingConverter
class LocalDateTimeToDateKstConverter : Converter<LocalDateTime, Date> {
override fun convert(source: LocalDateTime): Date = Timestamp.valueOf(source.plusHours(9))
}
다음으로 ReadingConverter도 만들어야 DB에서 읽어올 때 제대로 읽어온다.
이유는, 우리가 KST 시간처럼 DB에 저장했지만 Mongo DB 입장에선 여전히 UTC이기 때문이다.
따라서 현재 저장된 2023-12-01 09:00:00는 우리가 애플리케이션으로 들여올 때 UTC -> KST로 변환하는 과정에서 9시간이 더해져 2023-12-01 18:00:00로 들여오게 된다.
따라서 해당 시간에서 9시간을 다시 빼주어야 정상적인 KST로 들여올 수 있다.
package com.example.demo
import org.springframework.core.convert.converter.Converter
import org.springframework.data.convert.ReadingConverter
import org.springframework.stereotype.Component
import java.time.LocalDateTime
import java.time.ZoneId
import java.util.Date
@Component
@ReadingConverter
class DateToLocalDateTimeKstConverter : Converter<Date, LocalDateTime> {
override fun convert(source: Date): LocalDateTime = source.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().minusHours(9)
}
이제 해당 컨버터들을 MongoCustomConversions에 추가해 Bean으로 등록해준다.
package com.example.demo
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.mongodb.core.convert.MongoCustomConversions
@Configuration
class MongoConfig {
@Bean
fun customConversions(
localDateTimeToDateKstConverter: LocalDateTimeToDateKstConverter,
dateToLocalDateTimeKstConverter: DateToLocalDateTimeKstConverter,
) = MongoCustomConversions(
listOf(
localDateTimeToDateKstConverter,
dateToLocalDateTimeKstConverter,
)
)
}
이제 저장/조회 전부 KST로 잘 되는 것을 볼 수 있다~
'Backend > Spring' 카테고리의 다른 글
CompositeCacheManager의 배치 시간 소요 문제 - CacheManager는 꼭 전부 Bean 등록하자 (0) | 2023.12.02 |
---|---|
Redis Jackson @JsonUnwrapped Unwrapped property requires use of type information 이슈 (0) | 2023.07.07 |