6.2 KiB
6.2 KiB
타임존 설정 작업 계획
개요
프로젝트 전체에 서울 타임존(Asia/Seoul, UTC+9)을 일관되게 적용합니다.
현재 상태
완료된 설정
| 구성 요소 | 상태 | 비고 |
|---|---|---|
| MySQL 데이터베이스 | ✅ 완료 | DB 생성 시 Asia/Seoul로 설정됨 |
| config.py | ✅ 완료 | TIMEZONE = ZoneInfo("Asia/Seoul") 설정됨 |
| SQLAlchemy 모델 | ✅ 정상 | server_default=func.now() → DB 타임존(서울) 따름 |
문제점
- Python 코드에서
datetime.now()(naive) 또는datetime.now(timezone.utc)(UTC) 혼용 - 타임존이 적용된 현재 시간을 얻는 공통 유틸리티 없음
수정 대상 파일
| 파일 | 라인 | 현재 코드 | 문제 |
|---|---|---|---|
app/user/services/jwt.py |
26, 51, 109 | datetime.now() |
naive datetime |
app/user/services/auth.py |
170, 225, 485, 510 | datetime.now() |
naive datetime |
app/user/api/routers/v1/auth.py |
437 | datetime.now(timezone.utc) |
UTC 사용 (서울 아님) |
app/social/services.py |
408, 448, 509, 562, 578 | datetime.now() |
naive datetime |
app/social/worker/upload_task.py |
73 | datetime.now() |
naive datetime |
app/utils/logger.py |
89, 119 | datetime.today() |
naive datetime |
작업 단계
1단계: 타임존 유틸리티 생성 (신규 파일)
파일: app/utils/timezone.py
"""
타임존 유틸리티
프로젝트 전역에서 일관된 서울 타임존(Asia/Seoul) 시간을 사용하기 위한 유틸리티입니다.
모든 datetime.now() 호출은 이 모듈의 함수로 대체해야 합니다.
"""
from datetime import datetime
from config import TIMEZONE
def now() -> datetime:
"""
서울 타임존(Asia/Seoul) 기준 현재 시간을 반환합니다.
Returns:
datetime: 서울 타임존이 적용된 현재 시간 (aware datetime)
Example:
>>> from app.utils.timezone import now
>>> current_time = now() # 2024-01-15 15:30:00+09:00
"""
return datetime.now(TIMEZONE)
def today_str(fmt: str = "%Y-%m-%d") -> str:
"""
서울 타임존 기준 오늘 날짜를 문자열로 반환합니다.
Args:
fmt: 날짜 포맷 (기본값: YYYY-MM-DD)
Returns:
str: 포맷된 날짜 문자열
Example:
>>> from app.utils.timezone import today_str
>>> today_str() # "2024-01-15"
>>> today_str("%Y/%m/%d") # "2024/01/15"
"""
return datetime.now(TIMEZONE).strftime(fmt)
2단계: 기존 코드 수정
모든 datetime.now(), datetime.today(), datetime.now(timezone.utc)를 타임존 유틸리티 함수로 교체합니다.
2.1 app/user/services/jwt.py
# Before
from datetime import datetime, timedelta
expire = datetime.now() + timedelta(...)
# After
from datetime import timedelta
from app.utils.timezone import now
expire = now() + timedelta(...)
2.2 app/user/services/auth.py
# Before
from datetime import datetime
user.last_login_at = datetime.now()
if db_token.expires_at < datetime.now():
revoked_at=datetime.now()
# After
from app.utils.timezone import now
user.last_login_at = now()
if db_token.expires_at < now():
revoked_at=now()
2.3 app/user/api/routers/v1/auth.py
# Before
from datetime import datetime, timezone
user.last_login_at = datetime.now(timezone.utc)
# After
from app.utils.timezone import now
user.last_login_at = now()
2.4 app/social/services.py
# Before
from datetime import datetime, timedelta
buffer_time = datetime.now() + timedelta(minutes=10)
account.token_expires_at = datetime.now() + timedelta(...)
account.connected_at = datetime.now()
# After
from datetime import timedelta
from app.utils.timezone import now
buffer_time = now() + timedelta(minutes=10)
account.token_expires_at = now() + timedelta(...)
account.connected_at = now()
2.5 app/social/worker/upload_task.py
# Before
from datetime import datetime
upload.uploaded_at = datetime.now()
# After
from app.utils.timezone import now
upload.uploaded_at = now()
2.6 app/utils/logger.py
# Before
from datetime import datetime
today = datetime.today().strftime("%Y-%m-%d")
# After
from app.utils.timezone import today_str
today = today_str()
참고: logger.py에서는 날짜만 사용하는 것이 맞습니다. 로그 파일명이
{날짜}_app.log,{날짜}_error.log형식이므로 일별 로그 파일 관리에 적합합니다. 시간까지 포함하면 매 시간/분마다 새 파일이 생성되어 로그 관리가 어려워집니다.
작업 체크리스트
| 순서 | 작업 | 파일 | 상태 |
|---|---|---|---|
| 1 | 타임존 유틸리티 생성 | app/utils/timezone.py |
✅ 완료 |
| 2 | JWT 서비스 수정 | app/user/services/jwt.py |
✅ 완료 |
| 3 | Auth 서비스 수정 | app/user/services/auth.py |
✅ 완료 |
| 4 | Auth 라우터 수정 | app/user/api/routers/v1/auth.py |
✅ 완료 |
| 5 | Social 서비스 수정 | app/social/services.py |
✅ 완료 |
| 6 | Upload Task 수정 | app/social/worker/upload_task.py |
✅ 완료 |
| 7 | Logger 유틸리티 수정 | app/utils/logger.py |
✅ 완료 |
예상 작업 범위
- 신규 파일: 1개 (
app/utils/timezone.py) - 수정 파일: 6개
- 수정 위치: 약 15곳
참고 사항
naive datetime vs aware datetime
- naive datetime: 타임존 정보가 없는 datetime (예:
datetime.now()) - aware datetime: 타임존 정보가 있는 datetime (예:
datetime.now(TIMEZONE))
왜 서울 타임존을 사용하는가?
- 데이터베이스가 Asia/Seoul로 설정됨
- 서비스 대상 지역이 한국
- Python 코드와 DB 간 시간 일관성 확보
주의사항
- 기존 DB에 저장된 시간 데이터는 이미 서울 시간이므로 마이그레이션 불필요
- JWT 토큰 만료 시간 비교 시 타임존 일관성 필수
- 로그 파일명에 사용되는 날짜도 서울 기준으로 통일