Published on

Python logging 모듈로 로그 남기고 5가지 유형 알아보기

Authors

개발에서 로그는 중요합니다.

Python에서 제공하는 강력한 logging 모듈은 프로그램의 실행 중에 발생하는 이벤트를 추적하는 데 기본&필수적인 도구입니다.

이번에는 Python의 logging 모듈의 기본 사용법과 log level 5가지를 알아보겠습니다.

또 print와 비교해서 알아보도록 하겠습니다.

1. Basic logging

logging에 대한 공식문서 로 이동합니다.

1.1. logging 모듈의 기본설정

Python 에서 logging 모듈은 로그 메세지를 생성하고, 다양한 출력 대상에 전달하는 기능을 제공합니다.

가장 기본적인 사용방식은 다음과 같습니다.

import logging

logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

logger.debug("디버그 메시지")
logger.info("정보 메시지")
logger.warning("경고 메시지")
logger.error("에러 메시지")
logger.critical("심각한 에러 메시지")

basicConfig 함수는 로그 시스템의 기본 구성을 설정합니다.

이 설정은 로깅 시스템 전체에 영향을 미치고, 프로그램 시작 시 한번만 호출 되어도 전체 logging 시스템에 적용됩니다.

getLogger(__name__)은 현재 모듈에 대한 로거 인스턴스를 반환 합니다.

'어디에서 에러가 발생했는지?', '어디에서 어떤 데이터 구조를 가지고 있는지?' 등을 직관적으로 확인 할 수 있게 됩니다.

1.2. Log Level 5가지

로그레벨은 로그 메세지의 중요도를 나타냅니다. logging에는 다음과 같은 다섯 가지 표준 로그 레벨이 있습니다.

  1. DEBUG
  2. INFO
  3. WARNING
  4. ERROR
  5. CRITICAL

DEBUG 는 상세한 정보나, 문제를 찾는 과정 말 그대로 디버깅시 지정합니다.

INFO 는 일반적인 정보를 나타내며, 저는 print 대신 많이 사용합니다.

WARNING 은 예상치 못한 상황에서 사용하며, 오류는 아니지만 주의가 필요한 때에 사용합니다.

ERROR 는 에러를 발생하는 구간에 사용합니다.

CRITICAL 은 매우 심각한 문제에 사용합니다.

1.3. Handler, Formatter 적용

로그 메세지는 기본적으로 콘솔에서 출력됩니다.

이렇게 출력되는 메세지들은 네트워크 서버에서도 기록하게 됩니다.

이를 위한 기능이 handler 와 formatter(핸들러와 포매터)입니다.

handler = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)

StreamHandler 는 콘솔에 로그를 출력하는 기본 핸들러 입니다.

Formatter 는 로그 메세지의 형식을 지정합니다.

2. print VS logging

Python 에서 logging 모듈을 사용하는 것이 print 문을 사용하는 것보다 여러면에서 더 나은 선택입니다.

만약 Application 을 개발한다거나,

내가 만든 Python 프로젝트를 Production 환경에 배포하는 경우에도

logging 하는 습관을 가지는 것이 좋다고 생각합니다.

2.1. 레벨에 따른 유연성과 필터링

위에서 설명한 것처럼 다양한 로그 레벨을(DEBUG, INFO, WARNING, ERROR, CRITICAL) 갖고 있기 때문에, 특정 레벨을 겨냥해서 필터링 할 수 있습니다.

만약 Production 환경에서 ERROR Level의 로그만 보고 싶을 경우에 바로 적용이 되는 것 이죠.

2.2. Logging Format Customizing

로그 메세지의 포맷을 자유롭게 커스텀 할 수도 있습니다.

formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - [%(filename)s:%(lineno)d] %(message)s')

  • %(asctime)s: 로그 이벤트가 발생한 시각을 문자열로 표시합니다. 기본적으로 2003-07-08 16:49:45,896 (연-월-일 시:분:초,밀리초) 형식으로 출력됩니다. 형식은 datefmt 인자를 통해 커스터마이징할 수 있습니다.
  • %(name)s: 로거의 이름을 나타냅니다. 이는 일반적으로 logging.getLogger(name) 형태로 로거를 생성할 때 사용된 name (모듈의 이름) 값입니다.
  • %(levelname)s: 로그 레벨의 이름을 문자열로 표시합니다. 예를 들어, DEBUG, INFO, WARNING, ERROR, CRITICAL 등이 있습니다.
  • %(filename)s: 로그를 호출한 소스 파일의 파일명을 나타냅니다. 예를 들어, 로그가 example.py 파일에서 생성되었다면, example.py가 출력됩니다.
  • %(lineno)d: 로그 메시지가 호출된 소스 코드의 라인 번호를 나타냅니다. 이는 디버깅 시 매우 유용한 정보입니다.
  • %(message)s: 로그 메시지의 실제 텍스트를 나타냅니다. 이는 logger.info("이것은 로그 메시지입니다")와 같이 로그 메서드를 호출할 때 지정된 메시지입니다.

2.3. 보안

개발을 하면서 휴먼에러는 발생하기 매우 쉬운 에러 중 하나입니다. 그 중 print 관련 실수도 마찬가지 입니다.

물론 절대로 일어나면 안되겠지만, logging을 사용하는 것 만으로도 해결될 수 있습니다.

logging 을 사용해서 위에 설명한대로 보여주는 level 을 정해둔다면, 애초에 콘솔에 출력될 것이 정해져있으니 보안을 지킬 수도 있겠습니다.

hongreat 블로그의 글을 봐주셔서 감사합니다!