Python logging 모듈 완벽 가이드: 기본 설정부터 고급 활용까지

1. Python의 logging 모듈이란

Python의 logging 모듈은 프로그램의 동작 상태와 오류 정보를 기록하고, 디버깅이나 운영 시 모니터링에 활용하기 위한 표준 도구입니다。print 문과의 차이는 logging 모듈이 더 다양한 기능을 제공하며, 로그의 레벨이나 출력 위치, 형식을 세밀하게 제어할 수 있다는 점입니다。이를 통해 개발자는 프로그램의 이상 및 상태를 효율적으로 파악할 수 있습니다。

로그 레벨의 종류와 용도

  • DEBUG: 상세한 디버깅 정보. 주로 개발 단계에서 사용합니다。
  • INFO: 일반적인 동작 정보. 정상 동작 확인에 사용합니다。
  • WARNING: 경미한 문제나 주의 사항. 프로그램의 동작에 영향을 미치지는 않지만 잠재적인 문제를 나타냅니다。
  • ERROR: 일부 기능이 정상적으로 동작하지 않을 때의 오류 메시지. 프로그램 실행에 지장이 생기는 상황을 나타냅니다。
  • CRITICAL: 중대한 오류. 프로그램 전체의 실행을 계속할 수 없는 치명적인 문제를 나타냅니다。
각 로그 레벨을 적절히 구분해 사용하면, 로그로부터 얻는 정보의 품질을 높이고 효율적인 디버깅과 모니터링이 가능해집니다。

2. 기본적인 logging 사용법

logging 모듈을 사용하여 로그를 출력하는 기본적인 방법을 살펴보겠습니다。
import logging

# 로그 레벨과 포맷을 설정
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')

# 레벨별 로그 출력
logging.debug('디버그 정보: 상세한 진단 정보')
logging.info('정보 메시지: 정상 동작 확인')
logging.warning('경고 메시지: 주의가 필요한 상태')
logging.error('에러 메시지: 문제 발생')
logging.critical('크리티컬 메시지: 시스템 정지')
logging.basicConfig()에서 로그의 출력 대상(기본값은 표준 출력)、로그 레벨、포맷을 설정합니다。위의 예제에서는 level=logging.DEBUG로 설정되어 있으므로, DEBUG 레벨 이상의 모든 로그가 출력됩니다。

3. 로그 출력 대상과 포맷 커스터마이징

기본 출력 대상을 변경하거나 로그 포맷을 커스터마이징하는 것도 가능합니다. 예를 들어, 로그를 파일로 출력하려면 FileHandler를 사용합니다。

파일 출력과 포맷

import logging

# 파일 핸들러 설정
file_handler = logging.FileHandler('app.log')
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)

# 로거 설정
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
logger.addHandler(file_handler)

# 로그 출력
logger.debug('파일로 출력하는 디버그 정보')
logger.info('파일로 출력하는 정보 메시지')
위의 코드에서는、FileHandler를 사용하여 로그를 app.log에 출력합니다。Formatter로 지정된 포맷에 따라 로그 메시지가 기록됩니다。

4. 로그 파일 로테이션

장기간 운영에서는 로그 파일이 너무 커지지 않도록 하기 위해 파일 로테이션이 중요합니다。RotatingFileHandler를 사용하면 로그 파일의 크기와 파일 수를 제어할 수 있습니다。

RotatingFileHandler의 사용 예

import logging
from logging.handlers import RotatingFileHandler

# 로테이팅 핸들러 설정
handler = RotatingFileHandler('app.log', maxBytes=5000, backupCount=3)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)

# 로거 설정
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
logger.addHandler(handler)

# 로그 출력
for i in range(100):
    logger.debug(f'로테이션 테스트 {i}')
이 코드에서는、maxBytes로 로그 파일의 최대 크기를 5000바이트로 설정하고, backupCount로 백업 파일의 수를 3개로 설정합니다. 로그 파일이 지정된 크기를 초과하면 새 파일에 로그를 기록하고, 오래된 파일을 백업합니다。
侍エンジニア塾

5. 로그 레벨별 파일 출력

특정 로그 레벨마다 서로 다른 파일에 로그를 출력하면 로그의 가독성과 분석 효율을 높일 수 있습니다. 이를 위해 사용자 정의 필터와 여러 개의FileHandler를 사용합니다。

로그 레벨별 파일 출력 예

import logging

class ErrorFilter(logging.Filter):
    def filter(self, record):
        return record.levelno == logging.ERROR

# ERROR 레벨의 로그를 별도 파일로 출력
error_handler = logging.FileHandler('error.log')
error_handler.setLevel(logging.ERROR)
error_handler.addFilter(ErrorFilter())
error_handler.setFormatter(formatter)

# 로거 설정
logger.addHandler(error_handler)

# 로그 출력
logger.error('ERROR 레벨의 로그가 파일에 출력됩니다')
이 예에서는 ErrorFilter 클래스를 만들어 ERROR 레벨의 로그만 필터링하여 error.log로 출력합니다. 이렇게 하면 오류 로그만 별도의 파일로 분리하여 기록할 수 있습니다.

6. 모범 사례와 유의사항

로그를 적절히 활용하려면, 다음의 모범 사례와 유의사항을 고려해야 합니다.

로그 레벨의 적절한 사용

  • 개발 중에는 DEBUG 레벨을 활용해 상세한 정보를 기록하고, 운영 시에는 INFOWARNING 레벨로 전환하여 중요한 정보만 기록합니다.
  • 과도한 로그 출력은 성능 저하를 초래할 수 있으므로, 필요한 정보만 기록하도록 합니다.

로그의 보안과 개인정보 보호

  • 로그에 개인정보나 기밀 정보를 기록하지 않도록 주의합니다. 필요에 따라 데이터를 마스킹하는 등의 조치가 필요합니다.
  • 로그 파일은 적절한 권한을 설정하여, 무단 접근을 방지합니다.

7. 정리

logging 모듈은 프로그램의 동작 상태를 효율적으로 기록하여 디버깅이나 운영 시에 매우 유용합니다. 로그 레벨, 출력 대상, 포맷, 로테이션 등을 적절히 설정하고 프로그램의 운영 현황을 상세히 파악하면 문제의 조기 발견과 해결로 이어질 수 있습니다. 모범 사례를 활용하여 적절한 로그 관리를 실천합시다。