모종닷컴

MongoDB 시간 관련 쿼리 주의할 점 본문

Programming/데이터베이스

MongoDB 시간 관련 쿼리 주의할 점

모종 2022. 8. 9. 23:22
반응형

mongodb에 특정 기간 안에 생성된 데이터를 검색해야 할 일이 있었습니다.

mongodb를 자주 다뤄보지는 않아 between 관련 쿼리를 구글에 검색해봤는데 어떤 글은 new Date를 사용하고 어떤 글에서는 ISODate를 이용해서 쿼리를 날린다고 합니다..

이 두 개의 차이가 뭘까 하고 알아보았는데 일단 mongodb에는 항상 UTC를 기준으로 시간 데이터가 입력된다고 합니다. 따라서 한국 20시 00분의 시간을 mongo에 저장하면 11시 00분이 들어가게 되는 것이죠. 이게 사실인지 확인해보기 위해 실습을 조금 해봤습니다.

Spring Boot  + Mongodb

의존성 추가

implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'

프로퍼티  추가

spring:
  data:
    mongodb:
      uri: mongodb://localhost:27017/test

Document 및 Repository 생성

@Document(collection = "post")
data class Post(
    @Id
    var id: Long,
    var title: String,
    var content: String,
    var createdAt: LocalDateTime
)
interface PostRepository : MongoRepository<Post, Long> 

테스트 코드로 삽입을 해보자.

@SpringBootTest
@RunWith(SpringRunner::class)
class PostTest {
    @Autowired
    private lateinit var postRepository: PostRepository

    @Test
    fun insert() {
        val post = Post(id = 2L, title = "모종닷컴", content = "몽고디비 테스트", createdAt = LocalDateTime.now())
        print(post)
        postRepository.save(post)
    }
}

위를 실행했을 때 어플리케이션에는 아래와 같이 출력이 됩니다. 애플리케이션에서 삽입한 시각이 22시 00분이네요. 

몽고디비 확인

몽고디비 클라이언트 혹은 터미널에 들어가서 데이터를 확인해봅시다. 저는 연습할 겸 터미널로 들어가겠습니다.

역시 UTC 를 기준으로 저장이 되어있는 모습이 보이고 글의 위에서 언급했던 "몽고에는 항상 UTC로 저장된다"라는 말은 진실로 판명되었습니다.

이제부터는 시간 관련 쿼리에 대해서 알아보자.

이제 우리는 몽고디비에 항상 UTC로 저장된다는 사실을 알게 되었습니다. 자 그러면 오늘의 메인 주제에 대한 내용이네요. new Date와 ISODate에 대해서 알아보도록 하겠습니다.

new Date()를 이용해서 쿼리 해보자. 

날짜 뒤에 Z가 붙으면 로컬 타임 기준으로 변환이 된다. 따라서 2022-08-09T 22:00:00Z라고 입력을 하면 검색하는 UTC 타임으로는 2022-08-10T07:00:00가 될 것입니다.

with ~ Z

{createdAt: {$gt: new Date("2022-08-09T22:00:00.000Z"), $lt: new Date("2022-08-09T23:00:00.000Z")}}

역시 결과가 나오지 않습니다. 

without ~Z

시간 뒤에 Z를 빼면 로컬 타임존(KST)의 실제 시간을 의미합니다. 아래의 쿼리는 한국 시간을 기준으로 22시에서 ~ 23시 사이의 데이터를 검색하는 쿼리입니다. 

{createdAt: {$gt: new Date("2022-08-09T22:00:00.000"), $lt: new Date("2022-08-09T23:00:00.000")}}

잘 나옵니다.

ISODate를 사용해보자

ISODate는 Z의 유무와 관계없이 무조건 UTC 기준으로 변환을 해버리는 모습이네요. 고로 ISODate를 이용해서 22 ~ 23시 사이의 데이터를 검색하고 싶다면 아래와 같이 쿼리를 짜야합니다.

결론

헷갈려하지 말고 정리해놨으니 이제 생각 안 나면 내 포스트 봐야지 ㅎㅎ

참조

https://www.mongodb.com/docs/manual/reference/method/Date/

반응형