Django를 활용한 개발 시, 간단한 디버깅 용도로 print 메서드를 사용하는 것은 지양해야 한다. 디버깅 용도로 로그를 남길 때 로거를 사용하는 것을 더 추천한다. 로거는 print 메서드보다 속도가 빠르고 I/O 작업을 비동기적으로 처리하여 멀티스레드나 멀테 프로세스 환경에서 안전한게 로그를 기록할 수 있다. 또한 로그를 콘솔이 아닌 파일에 기록할 수 있고, 알림 등을 통해 문제 대응을 실시간을 할 수 있는 등 다양한 기능을 제공한다.
Django는 Python의 내장 로깅 모듈을 사용하고 확장하여 시스템 로깅을 수행한다. 따라서 장고의 로깅 설정을 살펴보기 앞서 Python의 내장 로깅 모듈에 대해 간단하게 살펴보자.
Python 로깅은 네 부분으로 구성된다. 각각의 구성은 다음과 같다.
로거는 로깅의 진입점으로, 메시지를 기록하는 데 사용된다. 로거는 다섯 가지 로그 수준을 제공하여 메시지의 중요도를 구분한다. 로거는 이 로그 수준을 기반으로 메시지가 추가 처리를 거칠지 또는 무시될지를 결정한다. 로거가 메시지를 처리해야 한다고 결정하면 메시지가 핸들러로 전달된다.
참고로 로그에는 다음과 같은 레벨이 존재한다.
DEBUG < INFO < WARNING < ERROR < CRITICAL
만약 로깅 레벨을 WARNING로 지정하면 WARNING, ERROR, CRITICAL 레벨의 로그가 출력된다.
핸들러는 로거로부터 받은 메시지를 어디에, 어떻게 기록할지 결정한다. 화면, 파일, 네트워크 소켓 등 다양한 출력 대상으로 메시지를 전송할 수 있다. 핸들러 역시 로그 수준을 가지며, 이는 메시지가 해당 핸들러에 의해 처리되는지 여부를 결정한다.
필터는 로거와 핸들러 사이의 추가적인 제어 수단을 제공한다. 특정 조건에 따라 로그 레코드를 필터링하거나 수정할 수 있다. 이를 통해 더 세밀한 로깅 제어가 가능해진다. 예를 들어 특정 소스의 ERROR 메시지만 내보내도록 허용하는 필터를 설치할 수 있다. 또한 여러 필터링 작업을 수행하기 위해 체인에서 여러 필터를 사용할 수 있다.
포맷터는 로그 레코드가 최종적으로 어떻게 표시될지 결정한다. 로그 메시지의 포맷을 지정하며, 필요에 따라 사용자 정의 포맷팅도 가능하다.
Django는 DEBUG 설정 값에 따라 다른 로깅 동작을 한다.
DEBUG = True : django 로거는 INFO 이상 수준의 메시지를 콘솔로 보낸다.DEBUG = False : django 로거는 ERROR 이상 수준의 메시지를 AdminEmailHandler로 보내어 관리자에게 이메일로 알린다. django.server 로거는 INFO 수준 이상의 메시지를 콘솔에 보낸다. django.server를 제외한 모든 로거는 루트 django 로거까지 상위 항목에 로깅을 전파한다.
참고로 Python의 기본 로깅 설정은 WARNING 이상 수준의 레코드를 콘솔로 출력한다.
Django의 기본 로깅 설정은 django.utils.log에 정의되어 있는 DEFAULT_LOGGING을 사용한다. 만약 새롭게 정의해서 사용하고 싶다면 설정 파일에 LOGGING 변수에 새롭게 작성하면 된다.
DEFAULT_LOGGING은 다음과 같다.
{
"version": 1,
"disable_existing_loggers": False,
"filters": {
"require_debug_false": {
"()": "django.utils.log.RequireDebugFalse",
},
"require_debug_true": {
"()": "django.utils.log.RequireDebugTrue",
},
},
"formatters": {
"django.server": {
"()": "django.utils.log.ServerFormatter",
"format": "[{server_time}] {message}",
"style": "{",
}
},
"handlers": {
"console": {
"level": "INFO",
"filters": ["require_debug_true"],
"class": "logging.StreamHandler",
},
"django.server": {
"level": "INFO",
"class": "logging.StreamHandler",
"formatter": "django.server",
},
"mail_admins": {
"level": "ERROR",
"filters": ["require_debug_false"],
"class": "django.utils.log.AdminEmailHandler",
},
},
"loggers": {
"django": {
"handlers": ["console", "mail_admins"],
"level": "INFO",
},
"django.server": {
"handlers": ["django.server"],
"level": "INFO",
"propagate": False,
},
},
}
version은 고정값 1을 사용해야 한다. 만약 다른 값을 입력하면 ValueError가 발생한다. 이 값은 의미 없어 보일 수도 있지만, logging 모듈이 업그레이드되어도 현재 설정을 보장해 주는 안전장치이다.
disable_existing_loggers 항목은 False로 설정했다. 만약 True로 설정하면 기존에 설정된 로거들을 사용하지 않게 된다.
필터는 특정 조건에서 로그를 출력하거나 출력하지 않기 위해서 사용된다. require_debug_false 필터는 DEBUG=False인지를 판단하는 필터이고, require_debug_true는 DEBUG=True 인지를 판단하는 필터이다. 조건 판단을 위해 각각 django.utils.log.RequireDebugFalse와 django.utils.log.RequireDebugTrue 클래스를 호출하여 DEBUG 항목의 True, False를 판단한다.
포맷터에는 로그를 출력할 형식을 정의한다. 포맷터에 사용될 수 있는 항목은 다음과 같다.
핸들러는 로그의 출력 방법을 정의한다. 다음은 DEFAULT_LOGGING 설정에 등록된 핸들러이다.
로그를 출력하는 프로그램에서 사용하는 로거(logger)의 이름을 의미한다. DEFAULT_LOGGING 설정에는 다음과 같은 로거들이 등록되어 있다.
참고
https://docs.djangoproject.com/en/5.0/ref/logging/#default-logging-configuration
https://wikidocs.net/77522