파이썬 로그 시간이 UTC 또는 예상과 다르게 찍힐 때는 먼저 asctime의 변환 방식과 실행 환경의 시간대를 확인한 뒤, 로그 소비자에 맞춰 UTC 또는 Asia/Seoul을 선택해야 합니다. logging.Formatter의 기본 시간 변환은 실행 환경의 로컬 시간 기준이며, Formatter별 converter를 바꾸면 UTC 같은 다른 변환을 지정할 수 있습니다. 따라서 화면에 보이는 시간만 보고 코드의 시각 계산이 틀렸다고 단정하기보다 변환 계층을 나누어 점검하는 편이 안전합니다.
asctime은 어디에서 시간을 바꾸나
포맷 문자열에 %(asctime)s가 있으면 Formatter가 formatTime()을 호출해 레코드의 생성 시각을 사람이 읽는 문자열로 바꿉니다. datefmt를 지정하면 그 형식에 따라 시각을 표현하고, 지정하지 않으면 Formatter의 기본 형식이 사용됩니다. 핵심은 날짜 형식과 시간대 변환이 같은 설정이 아니라는 점입니다.
기본 converter는 time.localtime()입니다. 그러므로 같은 Python 코드라도 로컬 PC, 서버, 예약 실행 프로세스, 컨테이너가 서로 다른 운영체제 시간대를 사용하면 표시되는 asctime이 달라질 수 있습니다. 운영 환경에서는 다음 순서로 확인하는 것이 좋습니다.
- 로그 포맷에
%(asctime)s와datefmt가 어떻게 지정되어 있는지 확인합니다. - 해당 Formatter의
converter를 별도로 바꾸었는지 확인합니다. - 실제 프로세스가 실행되는 환경의 시간대 설정을 확인합니다.
- 로그를 읽는 시스템이 시간대를 변환해 보여 주는지도 확인합니다.
UTC로 통일할 때와 Asia/Seoul로 표시할 때
여러 서버와 지역에서 수집한 로그를 하나의 순서로 비교해야 한다면 UTC를 일관되게 기록하는 방식이 관리하기 쉽습니다. 반대로 운영자가 한국 현지 시각을 기준으로 예약 실행과 장애 시점을 바로 대조해야 한다면 Asia/Seoul 표시가 읽기 편할 수 있습니다. 어느 하나가 모든 애플리케이션에 의무적인 답은 아니며, 로그를 소비하는 사람과 시스템의 운영 범위에 따라 결정해야 합니다.
무엇을 선택하든 로그에 시간대가 드러나게 하는 것이 좋습니다. 시간대 표기가 없는 문자열은 나중에 다른 시스템으로 옮겨졌을 때 해석이 어려워집니다. 날짜 모양만 바꾸고 시간대 의미를 바꾸었다고 생각하면 안 됩니다.
Formatter에서 UTC 변환을 지정하는 예
import logging
import time
logger = logging.getLogger("app")
handler = logging.StreamHandler()
formatter = logging.Formatter(
"%(asctime)s %(levelname)s %(message)s",
datefmt="%Y-%m-%dT%H:%M:%S%z",
)
formatter.converter = time.gmtime
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.INFO)
logger.info("작업을 시작합니다")
여기서 converter = time.gmtime은 해당 Formatter가 UTC 기준으로 변환하도록 하는 설정이고, datefmt는 그 결과를 어떤 문자열 모양으로 출력할지 정합니다. 둘을 별개의 계층으로 보면 설정을 읽고 문제를 좁히기 쉽습니다. 실제 운영에서는 같은 로그를 처리하는 Formatter마다 설정이 동일한지도 확인해야 합니다.
Asia/Seoul을 사용할 때 확인할 점
Asia/Seoul처럼 지역 이름을 가진 시간대를 코드에서 다루려면 zoneinfo.ZoneInfo가 사용할 시간대 데이터를 찾을 수 있어야 합니다. Python은 시간대 데이터를 먼저 TZPATH에서 찾고, 찾지 못하면 tzdata 패키지를 찾습니다. 데이터가 없으면 ZoneInfoNotFoundError가 발생할 수 있으므로 개발 PC에서만 동작하는지 서버나 컨테이너에서도 확인해야 합니다.
날짜와 시간 자체를 계산하거나 다른 시간대로 변환해야 한다면 시간대 정보가 있는 aware datetime을 사용하고, astimezone()으로 대상 시간대에 맞추는 편이 명확합니다. 시간대 정보가 없는 naive datetime은 그것이 UTC인지 로컬 시간인지 자체로 구분할 수 없습니다. 단순히 고정된 오프셋을 더하는 방식은 지역 시간대의 의미를 보존하지 못하므로 로그 표시 정책의 대체재로 삼기 어렵습니다.
마지막 점검 기준
로그 시간이 어긋났다면 다음 세 가지를 분리해 판단해 보십시오.
Formatter:asctime,datefmt,converter가 어떤 조합인지 확인합니다.- 실행 환경: 실제 프로세스가 어느 시간대에서 실행되는지 확인합니다.
- 시간대 데이터:
Asia/Seoul같은 지역 시간대를 사용할 경우 해당 데이터가 제공되는지 확인합니다.
저라면 운영 범위가 넓은 수집 로그는 UTC와 명시적인 시간대 표기를 우선 검토하고, 현지 운영자가 바로 읽어야 하는 별도 화면이나 보고서에는 Asia/Seoul 변환을 적용할지 결정하겠습니다. 중요한 것은 코드에 임의로 시간을 더하는 것이 아니라, 기록 시각·변환 방식·표시 형식을 같은 정책으로 맞추는 일입니다.
로그 파일 생성 자체가 문제라면 파이썬 로그 파일이 안 생기는 이유와 logging 설정 점검법에서 handler와 파일 설정을 이어서 확인할 수 있습니다.
근거 자료
- Python logging 공식 문서 —
Formatter,formatTime(),converter,datefmt의 동작 - Python zoneinfo 공식 문서 — 지역 시간대 데이터와
ZoneInfo동작 - Python datetime 공식 문서 — naive/aware datetime과
astimezone()