datetime 객체를 다루는 과정에서 타임존을 신경 쓰지 않으면, 날짜가 불일치하는 등의 문제가 발생할 수 있다. 날짜 객체들이 사용하기 어려운 건 아닌데, 소홀히 하기 쉬워서 오류가 발생하기 쉬운 것 같다. 이번 포스트에서는 데이터베이스에 저장된 UTC 시간을 가져와서 사용할 때 주의해야 할 사항을 정리해 보겠다.
[Prerequisite]
Naive & Aware datetime object
- naive : datetime object에 tzinfo(타임존 정보)가 없는 datetime 객체
- aware: datetime object에 tzinfo(타임존 정보)가 있는 datetime 객체
Django 프로젝트에서는 아래와 같이 세팅 파일에 USE_TZ = True로 설정하면, 모든 datetime 정보를 데이터베이스에 UTC로 저장해 준다.
USE_TZ = True
위처럼 설정해 놓으면 장고가 알아서 UTC로 저장해 주기 때문에, 타임존에 대해 무감각해질 수 있는데, 가져와서 변환하는 것은 우리의 몫이다. DB에 (UTC로) 저장되어 있는 datetime 필드를 가져와서 현재 날짜로 변환할 때, timezone 을 고려하여 변환해야 한다. 타임존을 고려하지 않으면 한국 시간은 UTC보다 9시간 빠르기 때문에, 일자가 쉽게 뒤바뀔 수 있다. 아래는 그 예시이다.
from django.utils import timezone
from myapp.models import Post # 필요한 모델을 import 합니다.
# 1. UTC로 저장되어있는 시간 데이터 가져오기 (위에서 Timezone support 를 enabled 했을 경우 데이터베이스에서 가져온 시간)
post = Post.objects.get(id=1)
print(post.created_at) # 결과는 2024-08-13 15:00:00+00:00 (UTC 시간으로 저장된 것으로 한국 시간으로 8월 14일 00시임)
# 2. UTC 시간을 고려하지 않고 변환하기
naive_created_at = post.created_at.strftime('%Y-%m-%d')
print(naive_created_at) # 결과는 2024-08-13 : 잘못된 값.
# 3. UTC 시간을 로컬 타임존으로 변환하기
aware_created_at = timezone.localtime(post.created_at).strftime('%Y-%m-%d')
print(aware_created_at) # 결과는 2024-08-14 (로컬 타임존 기준 날짜로 변환됨) : 의도한 결과
이번에 알게된 점)
2025년 1월 1일 00시에 생성된 Post Object가 있다면, UTC 시간 설정이 되어있는 db 에는 post.created_at 이 datetime.datetime(2024, 12, 31, 15, 0, tzinfo=datetime.timezone.utc) 로 저장되어있을 것이다. 따라서 2025년에 생성된 post 들을 모두 불러오기 위해서 단순히 year 로 필터링을 한다면 이 Post 는 결과에 포함되지 않을 것이라고 예상했다 (created_at__year=2025 이런식으로). 하지만 sql 을 보면 알아서 잘 timezone aware 하게 변환을 해주는 것을 알 수 있다.
TL;DR :
- Naive datetime 객체를 사용하면 UTC 시간대가 고려되지 않아 의도치 않은 결과가 나올 수 있다.
- Django 에서 타임존 서포트를 활성화하면 DB에 저장할 때 알아서 UTC로 저장해준다
- UTC로 저장된 날짜 정보를 사용할때는 django utils의 timezone.localtime()을 통해 로컬 타임존으로 변환해야 올바른 날짜를 얻을 수 있다.
datetime 객체를 조작할 때는 항상 일관된 접근 방식을 사용하여 예기치 않은 오류를 방지하자!
'Django' 카테고리의 다른 글
장고에서 auto_now_add=True 인 필드 값을 커스텀 값으로 넣고 싶을 때 (0) | 2024.08.13 |
---|