본문 바로가기
Artificial Intelligence/60. Python

[PYTHON] 예외 처리의 함정: except Exception을 지양해야 하는 3가지 이유와 올바른 해결 방법

by Papa Martino V 2026. 3. 8.
728x90

except Exception
except Exception

 

파이썬(Python) 개발 중 발생하는 예기치 못한 에러는 프로그램의 안정성을 위협하는 가장 큰 요소입니다. 많은 초보 개발자들이 모든 에러를 한 번에 잡아내기 위해 except Exception:이라는 포괄적인 구문을 사용하곤 합니다. 하지만 시니어 개발자의 관점에서 이러한 '묻지마 예외 처리'는 버그를 숨기고 유지보수를 불가능하게 만드는 위험한 습관입니다. 본 글에서는 왜 포괄적 예외 처리가 위험한지 분석하고, 견고한 소프트웨어를 위한 계층적 예외 처리 해결 방법을 제시합니다.


1. except Exception: 구문이 위험한 결정적 이유

파이썬의 예외 객체는 상속 구조로 이루어져 있습니다. Exception은 거의 모든 상용 에러의 부모 클래스이기 때문에 이를 사용하는 것은 다음과 같은 심각한 부작용을 낳습니다.

  • 디버깅의 난해함: 어떤 종류의 에러가 발생했는지 로그에 남기지 않으면, 실제 버그의 원인을 파악하는 데 수 배의 시간이 소요됩니다.
  • 시스템 신호 차단: 사용자가 프로그램을 종료하기 위해 누르는 Ctrl+C(KeyboardInterrupt)나 시스템 종료 신호까지 의도치 않게 잡아버려 프로그램이 제어 불능 상태가 될 수 있습니다.
  • 논리적 오류 은폐: 오타로 인한 NameError나 타입 불일치인 TypeError 같은 명백한 코딩 실수까지 에러 없이 넘어가게 되어 잠재적 시한폭탄을 만들게 됩니다.

2. 예외 처리 전략에 따른 안정성 및 가독성 차이 비교

포괄적 예외 처리와 명시적 예외 처리의 차이를 명확히 이해하면 더 나은 아키텍처를 설계할 수 있습니다.

비교 항목 except Exception: (비권장) Specific Exception (권장)
에러 식별력 매우 낮음 (모든 에러를 동일 취급) 매우 높음 (에러별 대응 가능)
코드 안정성 낮음 (예상치 못한 버그 발생 가능) 높음 (의도한 예외만 제어)
유지보수 비용 상승 (원인 파악에 시간 소요) 절감 (즉각적인 에러 트래킹)
실행 흐름 제어 모든 에러에서 멈춤/진행 에러 성격에 따른 정교한 제어
권장 상황 최상위 로깅/최후의 방어선 일반적인 모든 비즈니스 로직

3. [Sample Example] 단계별 예외 처리 해결 가이드

파일을 읽고 데이터를 처리하는 과정에서 발생할 수 있는 여러 에러를 명시적으로 해결하는 실전 코드입니다.

안 좋은 예시: 모든 에러를 하나로 뭉뚱그림

try:
    with open("data.txt", "r") as f:
        content = f.read()
        result = int(content)
except Exception as e:
    # 파일이 없는지, 숫자가 아닌지, 권한이 없는지 알 수 없음
    print("에러가 발생했습니다.") 
    

좋은 예시: 발생하는 에러별로 최적의 해결책 제공

try:
    with open("data.txt", "r") as f:
        content = f.read()
        result = int(content)
except FileNotFoundError:
    print("해결 방법: 파일 경로를 확인하거나 기본 파일을 생성하세요.")
except ValueError:
    print("해결 방법: 파일 내용이 올바른 숫자 형식인지 확인하세요.")
except PermissionError:
    print("해결 방법: 읽기 권한을 확인하세요.")
except Exception as e:
    # 예상치 못한 에러에 대한 최소한의 로깅 (마지막 보루)
    print(f"미처 예상치 못한 에러 발생: {e}")
    

4. 고품질 예외 처리를 위한 3가지 골든 룰

  1. 구체적인 예외를 먼저 작성: 상속 구조상 하위 클래스(구체적인 에러)를 먼저 나열하고, 부모 클래스(범용적인 에러)를 나중에 배치해야 합니다.
  2. LBYL vs EAFP: 파이썬은 "허락을 구하기보다 용서를 구하는 것이 쉽다(EAFP)"는 철학을 선호합니다. 즉, if문으로 일일이 체크하기보다 try-except를 적절히 사용하는 것이 더 파이썬답습니다.
  3. 최소 범위의 try 블록: 예외가 발생할 가능성이 있는 코드만 try 블록에 넣으세요. 블록이 너무 길면 어느 줄에서 에러가 났는지 찾기 힘들어집니다.

5. 결론: 견고한 코드는 예외를 대하는 태도에서 결정됩니다

except Exception: 구문은 양날의 검입니다. 프로그램이 멈추지 않게 하는 임시방편은 될 수 있지만, 시스템의 건강 상태를 가리는 가림막이 되기도 합니다. 에러를 두려워하여 숨기기보다는 명시적으로 드러내고 각 상황에 맞는 해결 방법을 제시하는 코드가 진정으로 가치 있는 소프트웨어입니다. 오늘 작성하시는 코드에서는 한 단계 더 깊이 들어가, 구체적인 예외 이름을 적어보는 습관을 가져보시길 권장합니다.


[내용 출처 및 참고 문헌]

  • Python Software Foundation. "Built-in Exceptions - Class hierarchy."
  • Effective Python: 90 Specific Ways to Write Better Python by Brett Slatkin.
  • Clean Code in Python by Mariano Anaya.
728x90