가장 흔한 시간대 버그
수년간의 개발자 고통 끝에 특정 시간대 버그들이 반복적으로 등장합니다. 가장 흔한 버그들과 수정 방법을 소개합니다.
버그 1: Naive Datetime 함정 (Python)
# 버그: naive와 aware datetime 비교
from datetime import datetime, timezone
deadline = datetime(2024, 3, 1, 0, 0) # naive — 시간대 없음!
now = datetime.now(timezone.utc) # aware UTC
print(now > deadline) # TypeError 발생!
# 수정: 항상 timezone-aware datetime 사용
deadline = datetime(2024, 3, 1, 0, 0, tzinfo=timezone.utc)
now = datetime.now(timezone.utc)
print(now > deadline) # 정상 작동
버그 2: DST 전환 — 없어지거나 두 번 나타나는 시간
# 버그: 시계가 앞당겨질 때 "오전 2시 30분"으로 스케줄링
# 미국에서 3월 두 번째 일요일: 오전 2시 → 오전 3시로 점프
# 오전 2시 30분은 존재하지 않습니다!
# 수정: UTC로 계산하고 표시용으로만 변환
# "현지 오전 2시 30분" 대신 UTC 오전 7시 30분으로 예약
버그 3: JavaScript Date 파싱 불일치
// 버그: 날짜만 있는 문자열은 UTC로 파싱되지만 현지 시간으로 표시
const d = new Date("2024-03-01");
// UTC 자정으로 파싱됨
// UTC-9에서는 2024-02-29로 표시됨!
// 수정: 항상 시간과 시간대 포함
const d = new Date("2024-03-01T00:00:00Z");
디버깅 기법
- 어디서나 UTC 출력: 디버깅 시 항상
datetime.now(timezone.utc).isoformat()로그 - 다른 시간대에서 테스트:
TZ=America/New_York환경 변수로 머신 변경 없이 다른 시간대 테스트 - DST 전환 시점에서 테스트: Python의
freezegun으로 특정 시간 시뮬레이션 - 데이터베이스 시간대 확인:
SHOW timezone;(PostgreSQL)
# Python: 다른 시간대에서 코드 테스트
TZ=America/New_York python my_script.py
# pytest + freezegun
from freezegun import freeze_time
@freeze_time("2024-03-10 06:59:00")
def test_dst_transition():
result = schedule_task("America/New_York", hour=2, minute=30)
assert result.hour != 2 # 2:30 AM이 존재하지 않으므로 적절히 처리해야 함
황금 체크리스트
- 모든 datetime이 timezone-aware (프로덕션에서 naive datetime 없음)
- 데이터베이스가 UTC 저장
- 서버 시간대가 UTC로 설정됨
- API 응답의 모든 타임스탬프 필드에 시간대 오프셋 포함
- 크론 잡이 UTC를 사용하거나 명시적으로 CRON_TZ 설정
- IANA 시간대 이름 사용 (원시 UTC 오프셋 +09:00 대신)
- DST 전환이 자동화 테스트에서 검증됨