DOCS/journey/ideas/250828_UTC_aware_datetime_handling_strategy.md
Claude-51124 22557e7132 docs: 오래된 트러블슈팅 아카이브 및 구조 정리
- 7-8월 초기 구축 문서 12개를 _archive/troubleshooting/2025_07-08_initial_setup/로 이동
- book/300_architecture/390_human_in_the_loop_intent_learning.md를 journey/research/intent_classification/로 이동 (개발 여정 문서)
- 빈 폴더 제거 (journey/assets/*)
2025-11-17 14:06:05 +09:00

1.8 KiB

UTC Aware DateTime 처리 전략

작성일: 2025-08-28

작성자: 서버 관리자

카테고리: 아이디어/베스트 프랙티스


배경

  • Gmail 토큰 만료 체크 시 can't subtract offset-naive and offset-aware datetimes 오류 발생
  • 타임존 혼용으로 인한 반복적인 버그 발생 (250819, 250828 사례)

핵심 전략: 내부 UTC, 외부 KST

1. 저장 및 처리 (UTC)

# 모든 DB 저장은 UTC
expires_at = datetime.now(timezone.utc) + timedelta(hours=1)

# 비교도 UTC로 통일
if datetime.now(timezone.utc) > expires_at:
    refresh_token()

2. 한국 시간 이벤트 처리

from zoneinfo import ZoneInfo

def is_kst_hour(hour: int) -> bool:
    """KST 특정 시간 체크 (예: 9시 브리핑)"""
    return datetime.now(ZoneInfo("Asia/Seoul")).hour == hour

def kst_to_utc(kst_hour: int) -> datetime:
    """KST 시간을 UTC로 변환"""
    kst_now = datetime.now(ZoneInfo("Asia/Seoul"))
    kst_target = kst_now.replace(hour=kst_hour, minute=0, second=0)
    return kst_target.astimezone(timezone.utc)

3. 범용 변환 함수

def to_utc_aware(dt_str: str) -> datetime:
    """모든 datetime 문자열을 UTC aware로 통일"""
    if not dt_str:
        return None
    dt = datetime.fromisoformat(dt_str.replace('Z', '+00:00'))
    return dt.replace(tzinfo=timezone.utc) if dt.tzinfo is None else dt

적용 원칙

  1. DB Schema: TIMESTAMP WITH TIME ZONE 사용 권장
  2. API Response: ISO 8601 with Z suffix (예: 2025-08-28T00:00:00Z)
  3. Cron Jobs: 서버 타임존(KST) 기준, 코드에서 UTC 변환
  4. Frontend Display: 사용자 로컬 시간으로 표시

기대 효과

  • naive/aware datetime 충돌 완전 방지
  • 글로벌 서비스 확장 시 타임존 이슈 없음
  • 코드 일관성 및 유지보수성 향상