Python 로그가 보이지 않을 때 원인은 생각보다 단순한 경우가 많습니다. 대부분은 effective level이 예상보다 높거나, handler가 없거나, logging 설정이 너무 늦게 실행되거나, propagation이 팀이 생각한 방식과 다르게 동작하는 문제입니다.
짧게 말하면, config를 계속 바꾸기 전에 먼저 effective logger level, attached handler, 실제 startup 경로에서 logging 설정이 언제 적용되는지를 확인하는 것이 가장 빠릅니다.
먼저 “로그를 아예 안 찍는가”와 “로그가 다른 곳으로 가는가”를 구분하세요
이 둘은 다른 문제입니다.
어떤 경우는 코드가 실제로 로그 레코드를 만들지 못합니다. level 필터가 막고 있기 때문입니다. 반대로 로그는 만들어졌지만 file, process manager, worker stream, platform sink 같은 다른 경로로 흘러가서 팀이 보고 있는 곳에만 안 보이는 경우도 많습니다.
이 구분이 중요한 이유는, 전자는 logger 설정 문제이고 후자는 출력 경로 문제이기 때문입니다.
Python 로그가 사라지는 흔한 이유
1. effective level이 너무 높음
가장 흔한 케이스입니다. logger.info()나 logger.debug()는 호출되지만, logger 또는 handler 중 하나가 WARNING 이상만 통과시키고 있을 수 있습니다.
2. 보이는 handler가 없음
logger는 존재하지만 stdout, stderr, file, 혹은 플랫폼이 기대하는 출력 경로로 보내는 handler가 없는 상태입니다.
3. logging 설정이 너무 늦게 실행됨
basicConfig()나 custom logging setup이 framework, worker bootstrap, import된 module의 초기화 이후에 실행되면, 이미 형성된 handler chain을 기대한 대로 바꾸지 못할 수 있습니다.
4. 다른 framework나 runtime이 설정을 덮어씀
Gunicorn, Celery, uvicorn, Django, Flask extension, platform entrypoint는 자체 logging 동작을 갖는 경우가 많습니다. 로컬 스크립트에서는 되는데 운영에서만 안 보이는 이유가 여기에 있습니다.
5. propagation을 잘못 이해하고 있음
child logger가 자체 handler에서 멈추거나, 반대로 root logger까지 올라가서 예상과 다른 결과를 만들 수 있습니다.
실전 점검 순서
1. effective level과 handler를 먼저 보세요
config를 고치기 전에 현재 live 상태를 봐야 합니다.
- logger effective level
- root logger level
- attached handler
- handler level
이 정보만으로도 로그가 막힌 건지, 다른 곳으로 가는 건지 빠르게 구분할 수 있습니다.
2. 설정이 startup 경로에서 언제 실행되는지 확인하세요
logging setup이 아래 중 언제 일어나는지 봐야 합니다.
- application code import 전
- framework나 worker boot 전
- 항상 도달하는 code path 안
설정 코드가 맞아도 실행 시점이 늦으면 운영에서는 실패합니다.
3. runtime이 handler chain을 바꿨는지 확인하세요
로컬 스크립트에서는 보이는데 실제 서비스에서는 안 보인다면, runtime 차이를 비교해야 합니다.
- 로컬 shell
- test runner
- Gunicorn이나 Celery worker
- container entrypoint
- platform-managed environment
이 단계에서 “로컬에선 되는데 운영에선 안 됨” 문제가 많이 풀립니다.
4. propagation과 root logger 동작을 확인하세요
child logger 설정은 맞는데 root logger나 parent chain이 최종 결과를 바꾸는 경우가 많습니다. 모듈이 많은 앱일수록 더 흔합니다.
5. 실제 runtime 경로에서 최소 로그를 찍어보세요
REPL이나 간단한 script만 보지 말고, 문제가 나는 실제 process path 안에서 간단한 로그를 하나 찍어봐야 합니다.
그래야 설정 문제인지, runtime wiring 문제인지, 단지 다른 출력 경로를 보고 있었던 건지 구분됩니다.
문제를 감 잡기 위한 짧은 예시
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
logger.info("hello")
이 단순한 코드도 이미 다른 곳에서 logging이 설정됐거나, handler가 교체됐거나, 플랫폼이 로그를 다른 곳으로 수집하면 “아무 일도 안 일어나는 것처럼” 보일 수 있습니다.
패턴을 찾은 뒤 어떻게 바꿀지
level filtering이 문제인 경우
필요한 logger나 handler level만 낮추고, 전체를 과하게 noisy 하게 만들지 않는 편이 좋습니다.
보이는 handler가 없는 경우
운영 환경이 기대하는 stdout, stderr, file, 혹은 플랫폼 stream에 맞는 handler를 붙여야 합니다.
설정이 너무 늦게 실행되는 경우
import된 모듈과 worker process가 기대한 설정을 물려받도록 startup 더 앞단으로 옮겨야 합니다.
runtime이 설정을 덮는 경우
ad hoc config를 덧대기보다, framework나 worker의 logging model에 맞춰 설정하는 편이 안정적입니다.
빠른 체크리스트
Python 로그가 안 보일 때는 아래 순서가 가장 좋습니다.
- effective level을 본다
- attached handler와 handler level을 본다
- logging config가 startup 중 언제 실행되는지 확인한다
- 로컬 경로와 실제 runtime 경로를 비교한다
- propagation과 root logger 동작을 확인한다
FAQ
Q. 왜 basicConfig()가 아무 일도 안 하는 것처럼 보이나요?
이미 더 앞단에서 logging이 설정됐기 때문일 수 있습니다.
Q. 로컬에서는 보이는데 운영에서는 왜 안 보이나요?
runtime, worker model, platform handler chain이 다르기 때문인 경우가 많습니다.
Q. 가장 빠른 첫 단계는 무엇인가요?
config를 바꾸기 전에 effective level과 current handler를 출력해 보는 것입니다.
Q. 테스트에서 logger가 동작하면 운영도 맞는 건가요?
아닙니다. test runner와 production worker는 다른 logging 동작을 설치할 수 있습니다.
Read Next
- 로그 부족 때문에 메모리 조사도 막히고 있다면 Python 메모리 사용량이 높을 때를 보세요.
- 더 넓은 흐름은 Python troubleshooting guide에서 볼 수 있습니다.
- queue pressure가 더 큰 문제라면 Python ThreadPoolExecutor queue가 계속 쌓일 때를 확인하세요.
Related Posts
- Python 메모리 사용량이 높을 때
- Python troubleshooting guide
- Python ThreadPoolExecutor queue가 계속 쌓일 때
- Python Celery worker concurrency가 낮아 보일 때
Sources:
심사 대기 중에는 광고 대신 관련 가이드를 먼저 보여줍니다.
먼저 읽어볼 가이드
검색 유입이 많은 핵심 글부터 이어서 보세요.
- 미들웨어 트러블슈팅 가이드: Redis vs RabbitMQ vs Kafka 개발자를 위한 미들웨어 트러블슈팅 허브 글입니다. Redis, RabbitMQ, Kafka 중 어떤 증상부터 먼저 봐야 하는지와 어떤 문제 패턴이 각 시스템에 가까운지 정리합니다.
- Kubernetes CrashLoopBackOff: 먼저 볼 것들 startup failure, probe, config, resource limit 관점에서 CrashLoopBackOff를 어떻게 나눠서 봐야 하는지 정리한 가이드입니다.
- Kafka consumer lag가 계속 늘 때: 트러블슈팅 가이드 Kafka consumer lag가 계속 늘어날 때 무엇부터 봐야 하는지 정리합니다. poll 주기, 처리 속도, rebalance, consumer 설정까지 실전 기준으로 다룹니다.
- Kafka Rebalancing Too Often 가이드 Kafka consumer group에서 rebalance가 너무 자주 일어날 때 membership flapping, poll timing, protocol, assignment churn을 어떤 순서로 봐야 하는지 설명하는 실전 가이드입니다.
- Docker container가 계속 재시작될 때: 먼저 확인할 것들 exit code, command failure, environment mistake, health check 관점에서 Docker restart loop를 푸는 실전 가이드입니다.
심사 대기 중에는 광고 대신 관련 가이드를 먼저 보여줍니다.