알겠습니다. 파이썬의 표준 import logging 라이브러리의 핵심 구조와 동작 원리를 개발자의 관점에서 설명해 드리겠습니다.
logging 라이브러리는 “무엇을(What), 어디에(Where), 어떻게(How), 언제(When) 기록할 것인가”를 제어할 수 있도록 모듈화된 강력한 시스템입니다. 이 시스템은 크게 4가지 주요 컴포넌트로 구성됩니다.
logging 라이브러리의 4대 핵심 컴포넌트

(이미지 출처: 파이썬 공식 문서)
1. 로거 (Loggers)
- 역할: 애플리케이션 코드에서 로그 메시지를 생성하는 진입점입니다. 개발자가 직접 상호작용하는 주체입니다.
- 생성:
log = logging.getLogger(__name__) - 기능:
- 메소드 제공:
log.debug(),log.info(),log.warning(),log.error(),log.critical()과 같은 메소드를 제공하여 개발자가 메시지를 기록할 수 있게 합니다. - 심각도(Level) 기반 필터링: 각 로거는 자신만의 레벨(예:
log.setLevel(logging.DEBUG))을 가질 수 있습니다. 생성된 메시지의 레벨이 로거의 레벨보다 낮으면, 메시지는 다음 단계(핸들러)로 전달되지 않고 즉시 무시됩니다. - 메시지 전파: 로거는 계층 구조를 가집니다.
getLogger('app.ui')는getLogger('app')의 자식입니다. 메시지는 자신의 핸들러에서 처리된 후, 부모 로거의 핸들러로 전파(propagate)될 수 있습니다. (기본값:True)
- 메소드 제공:
2. 핸들러 (Handlers)
- 역할: 로거로부터 전달받은 로그 메시지(정확히는
LogRecord객체)를 실제 목적지로 보내는(dispatch) 역할을 합니다. “어디에(Where)” 기록할지를 결정합니다. - 종류:
StreamHandler: 콘솔(터미널)과 같은 스트림(sys.stdout,sys.stderr)으로 출력합니다. SF Downloader에서 사용하는 핵심 핸들러입니다. (정확히는 이것을 대체하는ForwardingHandler를 사용)FileHandler: 파일에 로그를 기록합니다.RotatingFileHandler: 파일 크기가 일정 이상 커지면 새 파일에 로깅을 시작합니다. (예:app.log,app.log.1,app.log.2)TimedRotatingFileHandler: 특정 시간 간격(매일, 매시간 등)으로 로그 파일을 교체합니다.SMTPHandler: 이메일로 로그를 보냅니다. (주로 심각한 오류 발생 시)- … 등 다양한 종류가 있습니다.
- 연결:
logger.addHandler(my_handler)코드를 통해 하나의 로거에 여러 개의 핸들러를 붙일 수 있습니다. 예를 들어, 하나의 로그를 콘솔과 파일 양쪽에 동시에 기록할 수 있습니다.
3. 포매터 (Formatters)
- 역할: 로그 메시지의 **최종 출력 형식(레이아웃)**을 결정합니다. “어떻게(How)” 기록할지를 담당합니다.
- 생성:
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') - 기능:
LogRecord객체에 담긴 다양한 정보(시간, 로거 이름, 레벨, 메시지 등)를 지정된 형식의 문자열로 변환합니다.%(asctime)s,%(levelname)s등 다양한 속성을 조합하여 원하는 로그 포맷을 만들 수 있습니다.
- 연결:
handler.setFormatter(formatter)코드를 통해 각 핸들러에 포매터를 설정합니다.
4. 필터 (Filters)
- 역할: 로거의 레벨 필터링보다 더 세밀한 조건으로 로그를 전달할지 여부를 결정합니다. “언제(When)” 또는 “어떤 조건에서” 기록할지를 제어합니다.
- 기능:
filter(record)메소드를 구현한 객체입니다. 이 메소드가True를 반환하면 로그가 처리되고,False를 반환하면 무시됩니다.LogRecord객체의 모든 속성(로거 이름, 레벨, 메시지 내용 등)을 검사하여 복잡한 필터링 규칙을 만들 수 있습니다.
- 연결:
logger.addFilter(my_filter)또는handler.addFilter(my_filter)코드를 통해 로거나 핸들러에 필터를 추가할 수 있습니다.- SF Downloader에서는
LevelFilter라는 커스텀 필터를 만들어,config.ini에서 지정한 레벨의 로그만 통과시키도록 핸들러에 연결했습니다.
- SF Downloader에서는
SF Downloader에서의 동작 흐름
log = get_logger(__name__)(로거): 개발자는 코드에서log.info("메시지", context="main")을 호출합니다.logging시스템은 이 정보로LogRecord객체를 생성합니다.LevelFilter(필터):SF_Downloader로거에 연결된ForwardingHandler는 먼저LevelFilter에게LogRecord를 검사받습니다.config.ini에INFO가 활성화되어 있으면 필터를 통과합니다.ForwardingHandler(핸들러): 필터를 통과한LogRecord객체를 받아서, 포매팅 없이 그대로 자신의stream(sys.stdout, 즉Stream객체)으로 전달합니다.Stream.write(record):Stream객체는LogRecord를 받습니다.ContextFormatter(포매터):Stream객체 내부의format()메소드가ContextFormatter를 사용하여LogRecord를 최종 출력 문자열로 변환합니다. (예: “2023… – INFO – … – [main] 메시지”)- 최종 출력: 변환된 문자열은
original_stream(터미널)으로,LogRecord의 정보는 딕셔너리로 변환되어 시그널을 통해 GUI로 전송됩니다.
이처럼 logging 라이브러리는 각 컴포넌트의 역할을 명확히 분리하고, 이들을 조합하여 매우 유연하고 강력한 로깅 시스템을 구축할 수 있도록 설계되어 있습니다.