[초급] 당신의 자동화가 새벽 3시에 멈추는 진짜 이유 (feat. 에러코드)

[초급] 당신의 자동화가 새벽 3시에 멈추는 진짜 이유 (feat. 에러코드)

결론부터 말하자면, 당신의 자동화 스크립트는 100% 터진다.

새벽 3시, 세상 모르고 자고 있는데 구글 시트에 데이터가 안 쌓이고 있다. 아침에 출근해서 확인하니 스크립트는 뻗어있고, 원인은 불명. 상상만 해도 끔찍하다. 이걸 겪어봐야 정신 차린다. 아마추어와 프로의 차이는 ‘실패하지 않는 시스템’을 만드는 게 아니다. 그런 건 세상에 없다. ‘실패를 어떻게 다루는가’에서 갈린다.

코드가 중간에 멈추는 상황, 이걸 ‘예외(Exception)’라고 부른다. 이걸 처리하는 게 ‘예외 처리’다. 그냥 보험 들어놓는 것과 같다. 사고는 나게 되어있다. 보험 없이 도로에 나가면 그게 제정신인가. 코드도 마찬가지다.

대부분의 초심자들이 자동화 파이프라인을 구축할 때 저지르는 치명적인 실수 3가지를 짚어주겠다. 이것만 피해도 당신의 시스템 수명은 10배 길어진다.


실수 1: 오직 성공만 가정하는 순진한 코딩 😥

API 요청을 보냈을 때, 당연히 성공적인 응답(HTTP 200)만 올 거라고 가정한다. 딱 ‘해피 패스(Happy Path)’만 생각하는 거다. 하지만 네트워크는 변덕스럽고, 상대 서버는 언제든 아플 수 있다.

🚨 문제 상황: API 서버가 점검 중이거나, 일시적인 오류로 500 에러를 뱉었다. 당신의 코드는 이 상황을 전혀 예상하지 못했기에, 그 자리에서 즉시 실행을 멈춘다. 그 뒤에 이어져야 할 중요한 작업들은 전부 무시된다.

해결책: try-except 구문으로 코드를 감싸야 한다. 일단 가장 기본적인 방어막이다. ‘try’ 블록 안의 코드를 실행하다가 뭔가 잘못되면, 프로그램이 죽는 대신 ‘except’ 블록으로 제어권이 넘어간다.

이렇게 바꿔라:


import requests

try:
    response = requests.get('https://api.example.com/data')
    print(response.json())
except Exception as e:
    print(f"💥 예외 발생: {e}")
    # 여기서 최소한 에러가 났다는 사실이라도 알 수 있다.

이것만으로도 최소한 스크립트가 허무하게 멈추는 건 막는다.

실수 2: 에러 뭉뚱그리기 뭉텅이 처리 🤷‍♂️

첫 번째 실수를 겨우 면하고 try-except를 썼다. 그런데 모든 에러를 ‘Exception’ 하나로 퉁쳐서 처리한다. 이건 그냥 ‘아프다’는 사실만 알 뿐, 배가 아픈 건지 머리가 아픈 건지 모르는 것과 같다. 원인을 모르면 해결도 못 한다.

🚨 문제 상황: API 키가 만료되어 ‘401 Unauthorized’ 에러가 떴다. 그런데 당신의 코드는 그냥 ‘예외 발생’이라고만 알려준다. 당신은 서버 문제인 줄 알고 한참을 헤맨다. 사실은 그냥 API 키만 갱신하면 1분 만에 끝날 일이었다.

해결책: 에러 코드별로 다른 대응 전략을 짜야 한다. 마치 군대의 지휘관처럼, 적의 종류에 따라 다른 부대를 보내야 한다. requests 라이브러리를 쓴다면, 상태 코드(Status Code)를 확인하는 로직을 추가해야 한다.

이렇게 구체화해라:


import requests
from requests.exceptions import HTTPError

url = 'https://api.example.com/data'

try:
    response = requests.get(url)
    response.raise_for_status()  # 200번대가 아니면 HTTPError 발생
    data = response.json()
    print("데이터 수신 성공!")

except HTTPError as http_err:
    if http_err.response.status_code == 401:
        print("🔑 API 인증 실패. 키가 만료되었거나 잘못되었습니다.")
    elif http_err.response.status_code == 404:
        print(f"🔍 리소스를 찾을 수 없음: {url}")
    elif http_err.response.status_code >= 500:
        print("🔧 서버 내부 오류 발생. 잠시 후 다시 시도하세요.")
    else:
        print(f"기타 HTTP 오류: {http_err}")
except Exception as e:
    print(f"💥 알 수 없는 예외 발생: {e}")

이제 에러 메시지만 봐도 원인이 뭔지, 뭘 해야 할지 바로 감이 온다.

실수 3: 흔적도 없이 사라지는 에러 👻

에러를 잡아서 처리까지 했다. 그런데 그 사실을 어디에도 기록하지 않는다. 그냥 print()로 콘솔에 찍고 끝낸다. 스케줄러로 새벽에 혼자 돌아가는 스크립트라면, 그 print 메시지는 누가 보나? 허공에 사라질 뿐이다.

🚨 문제 상황: 지난밤, 스크립트가 10번 실행되는 동안 3번의 네트워크 오류가 발생했다가 저절로 복구됐다. 당신은 아무런 로그를 남기지 않았기에, 시스템이 불안정하다는 사실 자체를 인지하지 못한다. 그러다 결국 대형 장애로 이어진다.

해결책: 모든 실행과 에러를 파일로 기록(Logging)해야 한다. 비행기의 블랙박스와 같다. 추락한 뒤에 원인을 분석하려면 기록이 있어야 한다. 파이썬의 기본 `logging` 모듈만 써도 충분하다.

최소한 이 코드를 추가해라:


import logging

# 로그 기본 설정: 'automation.log' 파일에 기록, 시간과 로그 레벨, 메시지 포함
logging.basicConfig(filename='automation.log', level=logging.INFO, 
                    format='%(asctime)s - %(levelname)s - %(message)s')

# ... (이전 코드와 결합) ...

except HTTPError as http_err:
    # ... (이전 에러 처리) ...
    logging.error(f"HTTP 에러 발생: {http_err.response.status_code} - {url}") # print 대신 logging

except Exception as e:
    logging.critical(f"치명적 예외 발생: {e}") # 아주 심각한 에러는 critical로

finally:
    logging.info("스크립트 실행 완료.") # 성공이든 실패든 무조건 실행

이제 `automation.log` 파일만 열어보면 밤새 무슨 일이 있었는지 타임라인이 그려진다. 시스템은 원래 깨진다. 중요한 건 깨졌을 때 알려주고, 스스로 복구하거나, 최소한 원인이라도 남기게 만드는 설계다. 이게 자동화 시스템의 핵심이다.


PipeMaster-Lab 운영정책 및 제보 안내

① 공개된 모든 기록은 특정 기업이나 개인의 청탁 또는 금전적 지원 없이, 시스템 아키텍트의 독립적인 연구 및 실험 결과를 바탕으로 작성됩니다.
② 인용된 외부 콘텐츠 해석에 이의가 있는 경우,
연구실 직통 메일 pipemaster.lab@gmail.com
으로 연락 주시면 24시간 내 회신 및 즉각 조치합니다.
③ 게시된 내용 중 버전 변경으로 인한 정보 불일치나 치명적인 로직 오류를 제보해 주시는 분께는 내부 검토 후 소정의 기프티콘 등 바운티를 지급합니다.
④ 기업 단위의 시스템 아키텍처 컨설팅, 비즈니스 제휴 및 고도화 제안 역시 해당 공식 메일로만 수신 및 회신합니다.
verified

PIPEMASTER RESEARCH LAB

20년 IT 내공과 AI가 결합된 실전 무인 수익 자동화 시스템 연구소
본 콘텐츠는 PipeMaster-Lab 내부 Certified 규격을 엄격히 통과하였음을 증명합니다.

댓글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다