[TIL] 파이썬 예외 처리 깊게 파기: raise, except, 그리고 from
Forest 프로젝트를 기획하고 고도화하면서, 예기치 못한 에러에 우아하게 대처하는 ‘견고한 시스템’의 중요성을 체감하게 된다. 프론트엔드는 물론이고 스크립트나 서버 측 로직에서도 예외 처리는 서비스의 안정성과 직결된다. 오늘은 파이썬의 핵심 예외 처리 문법인 raise, except, 그리고 에러의 인과관계를 명확히 해주는 from에 대해 정리해 보았다.
1. raise: 능동적으로 에러 깃발 들기
단순히 시스템이 터지는 것을 기다리는 게 아니라, “현재 상황은 비정상이다”라고 명확히 선언하고 상위 로직에 처리를 위임하는 역할이다.
- 기본 발생: 특정 조건에서 고의로 에러를 발생시킬 때 사용. (
raise ValueError("잘못된 값입니다.")) - 다시 던지기(Re-raising):
except로 잡은 에러를 중간에서 로깅 등만 처리한 뒤, 다시 상위로 넘길 때 인자 없이raise만 단독으로 사용. - 사용자 정의 예외 (Custom Exception): 파이썬 내장 에러 외에, 도메인에 맞는 명확한 에러 클래스를 직접 만들어 사용하면 디버깅이 훨씬 수월해진다.
class InsufficientFundsError(Exception):
pass
def withdraw(balance, amount):
if amount > balance:
raise InsufficientFundsError(f"잔액 부족 (현재: {balance})")
return balance - amount
2. except: 에러를 안전하게 받아내는 포수
발생한 에러로 인해 프로그램이 강제 종료되지 않도록 방어하고, 상황에 맞게 복구하거나 안내하는 구문이다.
- 특정 에러 처리 및 상세 확인:
except ValueError as e:형태로 발생한 에러 객체를 받아 상세 내용을 로깅할 수 있다. - 다중 에러 처리: 하나의
try블록에서 발생하는 여러 종류의 에러를 각각 다른except블록으로 나누어 디테일하게 대처할 수 있다. - 주의점:
except Exception:으로 모든 에러를 뭉뚱그려 잡는 것은 개발자가 꼭 알아야 할 치명적인 버그까지 숨길 수 있으므로 가급적 지양하고, 가장 마지막 방어선으로만 사용해야 한다.
3. from: 에러의 뿌리 추적하기 (Exception Chaining)
어떤 에러를 다른 에러로 감싸서 던질 때, 원본 에러의 추적 기록(Traceback)을 잃지 않고 유지하기 위해 사용하는 문법이다. 특히 복잡한 로직을 혼자 디버깅할 때 진짜 원인을 빠르게 파악하는 데 필수적이다.
- 원인 명시 (
from e): 내부 시스템 에러(예: DB 연결 실패)를 사용자 친화적인 에러(예: 서비스 장애)로 변환하면서도, 에러 로그에는 “이 에러는 저 에러 때문에 발생했다”는 인과관계를 남긴다. - 꼬리 자르기 (
from None): 보안상 내부 구조 노출을 막거나 로그를 깔끔하게 유지하고 싶을 때, 원본 에러의 흔적을 아예 지워버린다.
class ServiceUnavailableError(Exception):
pass
try:
raise ConnectionError("DB 응답 시간 초과")
except ConnectionError as e:
# 사용자에게는 친절한 에러를 던지지만, 시스템 로그에는 DB 에러 기록이 보존됨
raise ServiceUnavailableError("일시적인 서비스 장애입니다.") from e