Computer >> 컴퓨터 >  >> 프로그래밍 >> Ruby

Ruby 예외 계층 구조 완벽 이해하기

```html

Ruby에서 예외(Exception)는 특별한 개념이 아니라 그저 하나의 클래스입니다. 즉, 예외 계층 구조란 Exception 클래스를 상속하는 모든 클래스들의 집합이라고 할 수 있습니다.

다음은 Ruby 2.1 표준 라이브러리의 예외 계층 구조 전체 모습입니다.

Exception
  NoMemoryError
  ScriptError
    LoadError
    NotImplementedError
    SyntaxError
  SecurityError
  SignalException
    Interrupt
  StandardError -- rescue의 기본값
    ArgumentError
      UncaughtThrowError
    EncodingError
    FiberError
    IOError
      EOFError
    IndexError
      KeyError
      StopIteration
    LocalJumpError
    NameError
      NoMethodError
    RangeError
      FloatDomainError
    RegexpError
    RuntimeError -- raise의 기본값
    SystemCallError
      Errno::*
    ThreadError
    TypeError
    ZeroDivisionError
  SystemExit
  SystemStackError

실전에서의 활용

예외를 이렇게 클래스 트리 형태로 구성해 둔 이유는, 유사한 성격의 예외들을 한 번에 손쉽게 처리(rescue)할 수 있도록 하기 위함입니다.

예를 들어 다음 코드를 살펴보겠습니다.

begin
  do_something
rescue StandardError => e
end

이 코드는 StandardError 자체뿐만 아니라, 그로부터 상속된 모든 예외를 함께 처리합니다. 실제로 우리가 일상적인 코드에서 관심을 가지게 되는 예외 대부분이 바로 이 StandardError 계열에 속합니다.

커스텀 예외 설계하기

직접 라이브러리나 애플리케이션을 작성할 때는, 자신만의 커스텀 예외들을 하나의 기본 클래스 아래에 두는 것이 좋은 설계 습관입니다.

module MyLib

  class Error < StandardError
  end

  class TimeoutError < Error
  end

  class ConnectionError < Error
  end

end

...

begin
  do_something
rescue MyLib::Error => e
  # 위에서 정의한 모든 예외를 한 번에 처리합니다
end

이렇게 하면 MyLib::TimeoutError, MyLib::ConnectionError 등 세부 예외를 각각 따로 처리할 수도 있고, 필요하다면 rescue MyLib::Error 한 줄로 라이브러리가 발생시키는 모든 예외를 일괄 처리할 수도 있습니다.

기억해 둘 핵심 포인트

  • rescue 절에 예외 클래스를 명시하지 않으면 기본적으로 StandardError가 적용됩니다.
  • 반대로 raise에 예외 클래스를 지정하지 않으면 기본값으로 RuntimeError가 발생합니다.
  • ScriptError(문법 오류, 로드 실패 등)나 SystemExit 같은 예외는 StandardError를 상속하지 않으므로, 일반적인 rescue로는 잡히지 않습니다. 이는 프로그램의 비정상 종료나 문법 오류를 무분별하게 삼키지 않도록 하기 위한 의도된 설계입니다.

예외 계층 구조를 제대로 이해하고 있으면, 불필요하게 넓은 범위의 예외를 잡는 실수를 피하고 더 안전하고 예측 가능한 코드를 작성할 수 있습니다.