C 언어 디버깅과 파이썬 로깅은 “오류(버그)를 찾아내고 상태를 추적”한다는 점에서 유사하지만, 사용 방식·환경·철학이 많이 다릅니다. 주요 차이를 정리해 보겠습니다.
| 구분 | C 디버깅 | Python 로깅 |
|---|---|---|
| 주된 목적 | • 런타임 오류(크래시), 메모리 문제, 논리 오류 조사 • 코드 흐름·변수 상태를 정밀 조사 | • 애플리케이션 동작 상태 기록 • 배포 환경에서도 정보·경고·오류 메시지 지속 수집 |
| 접근 방식 | • 주로 인터랙티브 디버거(gdb, lldb) 사용 • printf 찍어 보기• 메모리 검사 도구(valgrind) 활용 | • 파이썬 logging 모듈로 로그 메시지 남김• 로그 레벨(DEBUG, INFO, WARNING, ERROR, CRITICAL) 사용 • 파일·콘솔·원격 수집 시스템으로 핸들러 분기 |
인터랙티브 디버거
-g 옵션으로 디버깅 심볼 포함gdb ./app → 브레이크포인트 설정, 변수·메모리 덤프, 스택 트레이스 확인printf 출력
printf("foo = %d\n", foo); 삽입메모리·쓰레드 검사 도구
코드 인스펙션
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("프로그램 시작")
구조화된 로깅
LoggerAdapter, extra 인자)실시간 로깅 레벨 변경
추가 도구 연계
| 항목 | C 디버깅 | Python 로깅 |
|---|---|---|
| 초기 구축 비용 | • 소스에 -g 플래그, 디버거 설치• 도구(Valgrind) 학습 필요 | • import logging 한 줄• 기본 설정만으로 즉시 사용 가능 |
| 런타임 오버헤드 | • 디버거 연결 시 실행 느려짐 • printf 잔재 제거 번거로움 | • 로그 레벨·핸들러로 제어 • DEBUG 레벨도 운영서 꺼둘 수 있음 |
| 메모리 검사 | Valgrind 등으로 메모리·스레드 문제 전문 분석 | 간단 로깅만으로는 메모리 누수 탐지 불가 (별도 프로파일러 필요) |
| 배포 후 문제 진단 | • 심볼 없으면 스택 트레이스 한계 • 디버거로 바로 연결 어려움 | • 로그 파일에 오류·상태 지속 기록 → 사후 분석 용이 |
| 복잡도 | 주로 로컬 개발 환경에서 세밀하게 조사 | 개발→테스트→운영 전 단계에 일관되게 사용 가능 |
C 코드 개발·운영
printf+ValgrindPython 애플리케이션
logging 으로 중요 이벤트·오류 남기기파이썬 logging 모듈에서 기본 제공되는 레벨(DEBUG=10, INFO=20, WARNING=30, ERROR=40, CRITICAL=50) 외에 임의의 숫자 값을 쓰는 이유와 대표적인 사례를 정리해 보겠습니다.
더 세분화된 출력 제어
DEBUG보다는 더 자세한(더 낮은) 로그가 필요할 때 → 예: TRACE=5INFO와 WARNING 사이의 중요한 이벤트 구분 → 예: NOTICE=25도메인 특화 의미 부여
AUDIT=35METRIC=15운영·분석 파이프라인에서 구분 편의
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(숫자, ...) 를 써도 되지만, 메소드가 있으면 더 직관적이죠.| 커스텀 레벨 | 숫자 | 용도 예시 |
|---|---|---|
NOTSET | 0 | 상위 로거로 이벤트 위임(별도 메시지를 남기진 않음) |
TRACE | 5 | DEBUG보다 더 세부적인 함수 진입·상태 추적 |
METRIC | 15 | 성능·통계 정보 기록 (응답 시간, 처리량 등) |
NOTICE | 25 | 정상 동작 중 주의할 만한 이벤트 (설정 변경, 자동 복구 등) |
AUDIT | 35 | 보안 감사(audit trail) 로그 (사용자 권한 변경 등) |
라이브러리 예:
TRACE 레벨로 요청·응답 헤더를 남깁니다.METRIC 레벨로 로깅해 성능 모니터링용으로 사용하기도 합니다.logging.addLevelName()으로 새 레벨을 정의하고logger.log(숫자, ...) 혹은 커스텀 메소드를 통해 구체적인 도메인 로그를 남길 수 있습니다.