웹 애플리케이션을 개발하다 보면 시간대 처리는 생각보다 복잡한 문제다. 특히 전 세계 사용자를 대상으로 하는 서비스라면 더욱 그렇다. Django는 이런 시간대 문제를 해결하기 위해 django.utils.timezone 모듈을 제공한다.
왜 시간대 처리가 중요한가?
한국에서 오후 3시에 작성한 글이 미국 사용자에게는 몇 시로 표시되어야 할까? 서버는 UTC로 저장하고, 각 사용자의 지역 시간으로 변환해서 보여주는 것이 일반적이다. Django는 이런 복잡한 처리를 쉽게 할 수 있도록 도와준다.
django.utils.timezone 핵심 기능
1. make_aware() - Naive datetime을 Aware datetime으로 변환
Python의 datetime 객체는 두 가지 종류가 있다:
- Naive datetime: 시간대 정보가 없는 datetime
- Aware datetime: 시간대 정보가 포함된 datetime
from datetime import datetime
from django.utils.timezone import make_aware, get_current_timezone
# Naive datetime (시간대 정보 없음)
naive = datetime(2025, 4, 23, 15, 0, 0)
print(naive)
# 출력: 2025-04-23 15:00:00
# Aware datetime으로 변환
aware = make_aware(naive, get_current_timezone())
print(aware)
# 출력: 2025-04-23 15:00:00+09:00 ← 타임존 정보 추가됨
2. get_current_timezone() - 현재 타임존 가져오기
Django 설정에서 정의한 TIME_ZONE을 가져온다.
from django.utils.timezone import get_current_timezone
tz = get_current_timezone()
print(tz)
# 출력: Asia/Seoul (settings.py의 TIME_ZONE이 'Asia/Seoul'인 경우)
3. now() - 현재 시간을 Aware datetime으로 가져오기
from django.utils import timezone
# 현재 시간 (aware datetime)
current_time = timezone.now()
print(current_time)
# 출력: 2025-04-23 15:30:00+00:00 (UTC)
# 로컬 타임존으로 변환
local_time = timezone.localtime(current_time)
print(local_time)
# 출력: 2025-04-24 00:30:00+09:00 (한국 시간)
4. is_aware()와 is_naive() - datetime 타입 확인
from django.utils import timezone
from datetime import datetime
naive = datetime.now()
aware = timezone.now()
print(timezone.is_naive(naive)) # True
print(timezone.is_aware(aware)) # True
settings.py 시간대 설정
Django 프로젝트의 시간대 처리는 settings.py에서 설정한다.
# settings.py
# 타임존 활성화 (권장)
USE_TZ = True
# 기본 타임존 설정
TIME_ZONE = 'Asia/Seoul'
# 날짜/시간 형식 (선택사항)
DATE_FORMAT = 'Y년 m월 d일'
TIME_FORMAT = 'H:i'
DATETIME_FORMAT = 'Y년 m월 d일 H:i'
USE_TZ 설정의 의미
- USE_TZ = True (권장)
- 모든 시간을 UTC로 데이터베이스에 저장
- 템플릿과 폼에서는 TIME_ZONE 설정에 따라 자동 변환
- 여러 시간대를 지원하는 애플리케이션에 적합
- USE_TZ = False
- TIME_ZONE에 설정된 시간대로 저장
- 단일 시간대만 사용하는 로컬 애플리케이션에 적합
활용 예제
1. 모델에서 시간대 처리
from django.db import models
from django.utils import timezone
class Article(models.Model):
title = models.CharField(max_length=200)
# auto_now_add는 자동으로 timezone.now() 사용
created_at = models.DateTimeField(auto_now_add=True)
# 커스텀 저장 시간
published_at = models.DateTimeField(default=timezone.now)
def is_published(self):
return self.published_at <= timezone.now()
2. 뷰에서 시간대 처리
from django.utils import timezone
from django.shortcuts import render
from .models import Article
def article_list(request):
# 현재 시간 기준으로 게시된 글만 조회
articles = Article.objects.filter(
published_at__lte=timezone.now()
)
context = {
'articles': articles,
'current_time': timezone.localtime(timezone.now())
}
return render(request, 'articles/list.html', context)
3. 템플릿에서 시간대 표시
<!-- 자동으로 사용자의 TIME_ZONE으로 변환되어 표시 -->
<p>작성일: {{ article.created_at|date:"Y년 m월 d일 H:i" }}</p>
<!-- 특정 타임존으로 변환 -->
{% load tz %}
{% timezone "US/Eastern" %}
<p>뉴욕 시간: {{ article.created_at|date:"Y-m-d H:i" }}</p>
{% endtimezone %}
4. 폼에서 시간 입력받기
from django import forms
from django.utils import timezone
class EventForm(forms.Form):
title = forms.CharField(max_length=200)
event_date = forms.DateTimeField()
def clean_event_date(self):
event_date = self.cleaned_data['event_date']
# 과거 날짜는 허용하지 않음
if event_date < timezone.now():
raise forms.ValidationError("과거 날짜는 선택할 수 없습니다.")
return event_date
자주 발생하는 문제와 해결법
1. RuntimeWarning: DateTimeField received a naive datetime
# 문제 코드
from datetime import datetime
article.published_at = datetime.now() # Naive datetime
# 해결 방법
from django.utils import timezone
article.published_at = timezone.now() # Aware datetime
2. 시간 비교 시 TypeError
# 문제 코드
from datetime import datetime
if article.created_at > datetime.now(): # Aware와 Naive 비교
pass
# 해결 방법
from django.utils import timezone
if article.created_at > timezone.now(): # 둘 다 Aware
pass
3. 특정 시간대로 datetime 생성하기
from django.utils import timezone
import pytz
# 한국 시간으로 특정 시간 생성
korea_tz = pytz.timezone('Asia/Seoul')
specific_time = korea_tz.localize(datetime(2025, 4, 23, 15, 0, 0))
# 또는
from django.utils.timezone import make_aware
specific_time = make_aware(
datetime(2025, 4, 23, 15, 0, 0),
timezone=pytz.timezone('Asia/Seoul')
)
Django의 timezone 모듈은 복잡한 시간대 처리를 간단하게 만들어준다. 핵심은 다음과 같다:
- USE_TZ = True로 설정하여 시간대 지원 활성화
- timezone.now()를 사용하여 현재 시간 가져오기
- make_aware()로 naive datetime을 aware로 변환
- 데이터베이스에는 UTC로 저장, 사용자에게는 로컬 시간으로 표시
728x90
'Backend study > Django' 카테고리의 다른 글
Django 언어 설정과 국제화(i18n) - LANGUAGE_CODE (3) | 2025.07.11 |
---|---|
Django 프로젝트에서 자동 생성되는 데이터베이스 테이블 (0) | 2025.07.08 |
APIView와 ViewSet (0) | 2025.07.02 |
Django 프로젝트 구조와 명령어 완벽 가이드 (0) | 2025.06.27 |
Django란? (0) | 2025.06.27 |