Python (5/19) - 1

김소은·2025년 5월 22일

📚 C debugging VS Python logging

C 언어 디버깅과 파이썬 로깅은 “오류(버그)를 찾아내고 상태를 추적”한다는 점에서 유사하지만, 사용 방식·환경·철학이 많이 다릅니다. 주요 차이를 정리해 보겠습니다.


1. 목적과 접근 방식

구분C 디버깅Python 로깅
주된 목적• 런타임 오류(크래시), 메모리 문제, 논리 오류 조사
• 코드 흐름·변수 상태를 정밀 조사
• 애플리케이션 동작 상태 기록
• 배포 환경에서도 정보·경고·오류 메시지 지속 수집
접근 방식• 주로 인터랙티브 디버거(gdb, lldb) 사용
printf 찍어 보기
• 메모리 검사 도구(valgrind) 활용
• 파이썬 logging 모듈로 로그 메시지 남김
• 로그 레벨(DEBUG, INFO, WARNING, ERROR, CRITICAL) 사용
• 파일·콘솔·원격 수집 시스템으로 핸들러 분기

2. C 디버깅 주요 기법

  1. 인터랙티브 디버거

    • 컴파일 시 -g 옵션으로 디버깅 심볼 포함
    • gdb ./app → 브레이크포인트 설정, 변수·메모리 덤프, 스택 트레이스 확인
    • 단계별 실행(step in/out), 조건부 브레이크포인트
  2. printf 출력

    • 코드를 수정해 임의 위치에 printf("foo = %d\n", foo); 삽입
    • 런타임 시 직관적으로 값 관찰
    • 간단하지만, 반복 빌드·실행이 필요
  3. 메모리·쓰레드 검사 도구

    • Valgrind: 메모리 누수·뭉침, 잘못된 접근 탐지
    • Helgrind (Valgrind 도구군): 쓰레드 경합(race condition) 검출
  4. 코드 인스펙션

    • 정적 분석(Static Analysis, e.g. clang-tidy, cppcheck)
    • 코드 리뷰를 통한 로직 검증

3. Python 로깅 주요 기법

  1. logging 모듈

    import logging
    logging.basicConfig(
        level=logging.DEBUG,
        format='%(asctime)s %(levelname)s [%(name)s] %(message)s',
        handlers=[logging.FileHandler('app.log'), logging.StreamHandler()]
    )
    logger = logging.getLogger(__name__)
    logger.info("프로그램 시작")
    • 레벨별 출력 제어: DEBUG→INFO→WARNING→ERROR→CRITICAL
      * 예) level=logging.WARNING : WARNING, ERROR, CRITICAL 레벨이 출력됨
    • 포맷, 핸들러(file, console, SMTP, HTTP 등) 유연하게 구성
  2. 구조화된 로깅

    • JSON, key–value 형태로 기록 → 중앙집중식 수집(elastic stack, Splunk 등)
    • 컨텍스트 정보 추가 (LoggerAdapter, extra 인자)
  3. 실시간 로깅 레벨 변경

    • 운영 중에도 로그 레벨을 동적으로 올렸다 내렸다 하여 조사 가능
    • Config 파일(.ini, YAML) 재로딩
  4. 추가 도구 연계

    • Sentry, Bugsnag 같은 에러 추적 서비스와 연동
    • APM(Application Performance Monitoring) 툴로 로그 기반 트레이스

4. C 디버깅 vs Python 로깅 비교

항목C 디버깅Python 로깅
초기 구축 비용• 소스에 -g 플래그, 디버거 설치
• 도구(Valgrind) 학습 필요
import logging 한 줄
• 기본 설정만으로 즉시 사용 가능
런타임 오버헤드• 디버거 연결 시 실행 느려짐
printf 잔재 제거 번거로움
• 로그 레벨·핸들러로 제어
• DEBUG 레벨도 운영서 꺼둘 수 있음
메모리 검사Valgrind 등으로 메모리·스레드 문제 전문 분석간단 로깅만으로는 메모리 누수 탐지 불가 (별도 프로파일러 필요)
배포 후 문제 진단• 심볼 없으면 스택 트레이스 한계
• 디버거로 바로 연결 어려움
• 로그 파일에 오류·상태 지속 기록 → 사후 분석 용이
복잡도주로 로컬 개발 환경에서 세밀하게 조사개발→테스트→운영 전 단계에 일관되게 사용 가능

5. 언제, 어떻게 선택할까?

  • C 코드 개발·운영

    • 로컬 개발 중 치명적 버그: gdb+printf+Valgrind
    • 제품 릴리스 후: 심볼 없는 바이너리라면 로그(자체 로깅 시스템)나 모니터링 에이전트 활용
  • Python 애플리케이션

    • 코드 작성 초기부터: logging 으로 중요 이벤트·오류 남기기
    • 운영 환경: 로깅 레벨 조정, 중앙 수집 시스템과 통합

요약

  1. C 디버깅은 “직접 코드 흐름과 메모리 상태를 인터랙티브로 살펴보는” 방식
  2. Python 로깅은 “애플리케이션 전 단계에 걸쳐 작동 상태를 기록·수집하는” 방식
  3. 각 언어의 생태계와 목적에 맞춰 적절히 도구를 활용하세요.

파이썬 logging 모듈에서 기본 제공되는 레벨(DEBUG=10, INFO=20, WARNING=30, ERROR=40, CRITICAL=50) 외에 임의의 숫자 값을 쓰는 이유와 대표적인 사례를 정리해 보겠습니다.


📚 logging with custom level

1. 왜 커스텀 레벨을 쓰나?

  1. 더 세분화된 출력 제어

    • DEBUG보다는 더 자세한(더 낮은) 로그가 필요할 때 → 예: TRACE=5
    • INFOWARNING 사이의 중요한 이벤트 구분 → 예: NOTICE=25
  2. 도메인 특화 의미 부여

    • 보안 감사 로그 → AUDIT=35
    • 성능 메트릭 로그 → METRIC=15
  3. 운영·분석 파이프라인에서 구분 편의

    • 중앙화 로깅 시스템에선 레벨별로 색인·알람을 다르게 걸 수 있음

2. 커스텀 레벨 정의 예제

import logging

# 1) 레벨 이름과 숫자 추가
TRACE_LEVEL = 5
NOTICE_LEVEL = 25

logging.addLevelName(TRACE_LEVEL, "TRACE")
logging.addLevelName(NOTICE_LEVEL, "NOTICE")

# 2) Logger 클래스에 메소드 연결
def trace(self, msg, *args, **kwargs):
    if self.isEnabledFor(TRACE_LEVEL):
        self._log(TRACE_LEVEL, msg, args, **kwargs)
def notice(self, msg, *args, **kwargs):
    if self.isEnabledFor(NOTICE_LEVEL):
        self._log(NOTICE_LEVEL, msg, args, **kwargs)

logging.Logger.trace  = trace
logging.Logger.notice = notice

# 3) 사용
logging.basicConfig(level=TRACE_LEVEL)
logger = logging.getLogger(__name__)

logger.trace("TRACE 레벨 로그 (매우 상세)")
logger.debug("DEBUG 레벨 로그")
logger.info("INFO 레벨 로그")
logger.notice("NOTICE 레벨 로그 (INFO<NOTICE<WARNING)")
logger.warning("WARNING 레벨 로그")
  • 위처럼 .addLevelName().Logger 확장으로 완전히 새로운 레벨을 만들 수 있습니다.
  • logger.log(숫자, ...) 를 써도 되지만, 메소드가 있으면 더 직관적이죠.

3. 실제 쓰이는 대표적 사례

커스텀 레벨숫자용도 예시
NOTSET0상위 로거로 이벤트 위임(별도 메시지를 남기진 않음)
TRACE5DEBUG보다 더 세부적인 함수 진입·상태 추적
METRIC15성능·통계 정보 기록 (응답 시간, 처리량 등)
NOTICE25정상 동작 중 주의할 만한 이벤트 (설정 변경, 자동 복구 등)
AUDIT35보안 감사(audit trail) 로그 (사용자 권한 변경 등)
  • 라이브러리 예:

    • 일부 HTTP 클라이언트는 TRACE 레벨로 요청·응답 헤더를 남깁니다.
    • DB 드라이버나 ORM이 쿼리 실행을 METRIC 레벨로 로깅해 성능 모니터링용으로 사용하기도 합니다.

요약

  • 표준 다섯 단계 외에도, 필요에 따라 logging.addLevelName()으로 새 레벨을 정의하고
  • logger.log(숫자, ...) 혹은 커스텀 메소드를 통해 구체적인 도메인 로그를 남길 수 있습니다.
  • 이렇게 하면 “어느 로그가 무슨 의미인지”와 “어떤 상황에 켜고/끄고”를 훨씬 더 유연하게 관리할 수 있습니다.
profile
개발자

0개의 댓글