Exception Handling
이번 포스트는 Exception Handling에 대해 다룬다. 이 포스트를 마지막으로 소프트웨어 공학 태그에 대한 포스트는 마무리 될 예정이다.
Exception Handling
Exception
- Exception(예외) : 프로그램의 실행 중에 발생하여 정상적인 명령 흐름을 방해하는 사건
Exception Object
- Exception이 발생했을 때 Exception Object가 만들어진다.
- 이 객체는 에러의 타입과 에러 발생 당시에 프로그램의 상태 정보를 포함한다.
Exception Object를 생성하여 Runtime System에 넘기는 행위
=> Throwing an exception
Exception Handling의 장점
1. Separting Error-Handling Code from “Regular” Code
정상적인 코드 흐름과 오류 처리 코드를 분리할 수 있다.
- 코드 가독성이 높아지고, 유지 보수하기에도 좋다.
- 예전에는 예상 가능한 오류 상황들(파일이 열리지 않으면.? 파일 길이를 모르면? 메모리 할당이 안되면? 등)에 대한 모든 예외 케이스를 if 문 등으로 직접 처리하였기에 코드가 복잡했다.
- 이는 정상적인 논리가 if 문 중첩으로 묻히게 된다. (구별하기가 어려워진다.)
“try - catch”문 사용
- 정상 흐름인 코드 (try 블록)와 오류 처리 코드(catch 블록)가 명확히 분리된다.
- 코드 가독성이 높아지고, 유지보수하기에도 유리하다.
- 각 오류별 처리 코드도 독립적이고 명확하게 작성이 가능하다.
2. Propagating Errors Up the Call Stack
Exception은 호출 스택(Call Stack)을 따라서 전파가 가능하다.
현재 함수에서 처리하지 않으면 상위 호출 함수로 자동 전달된다.
- 특정 함수에서 오류 처리 책임을 가지지 않아도 된다.
- 상위의 호출자가 처리가 가능하다.
3. Grouping and Differentiating Error Types
Exception은 계층적 구조 (Class Hierarchy)로 설계가 가능하다.
- 다양한 에러 타입이 구분이 가능하다.
- 유사한 오류는 그룹으로 묶어서 처리가 가능하다.
- 특수한 오류는 별도로 구분하여 처리가 가능하다.
- Catch 구문에서 상위 타입과 하위 타입을 구분하여 처리가 가능하다.
Exception Etiquette
“Don’t catch an exception unless you know what to do with it!”
- 예외는 그저 잡기만 하고 아무 의미 있는 처리를 하지 않는 다는 것은 좋지 않다는 뜻
- 오류 발생 시 조용히 해결되면 오류의 존재조차 알 수 없다.
- 프로그램 상태가 잘못된 상태로 계속 진행될 수 있다.
“자신이 처리할 책임이 없다면 Throw로 상위에 전파하는 것이 좋다.”
Exception-Handling Fundamentals
- Java의 exception handling : try, catch, throw, throws, finally
- C# : try, catch, throw, finally
Finally 문은 try문을 나가기 전에 관계없이 항상 수행한다.
- Throwable Inheritance Hierarchy

Exception Types
Throwable
- Java에서 모든 오류 / 예외 처리를 위한 최상위 클래스
- 즉, catch 할 수 있는 건 전부 Throwable을 상속받은 클래스
- Error, Exception 이라는 2개의 subclass를 가지고 있다.
1. Error
- JVM이 발생시키는 시스템 레벨 오류
- 보통 회복하기에 불가능하고, catch에서 처리하는 것이 바람직하지 않다.
- 예시 ) 메모리 부족, 재귀 호출 폭주로 스택 초과, JVM 내부 오류
2. Exception
- 애플리케이션 수준에서 발생하는 예외
- 정상적인 코드 흐름에서 예외 상황이 발생할 수 있다. -> catch가 가능하다.
Exception 종류
1. Checked Exception
- Well-written application이라면 예상하고 회복할 수 있어야 하는 예외
- 이 상황은 올 수 있고, 그에 대한 처리를 해야 한다. => 강제로 처리해야한다.
- 컴파일 시점에 Catch or Specify Requirement가 적용된다.
- 반드시 try-catch문으로 처리하거나
- throws로 상위로 명시적으로 전달해야 한다.
- 정리
- 의도 : 프로그램에서 처리 가능해야 하는 예외
- 처리 강제 여부 : O (컴파일 시점에서는 반드시 처리해야 한다.)
- 주 용도 : 외부 환경 요인
2. Error
- 애플리케이션 외부 요인으로 발생한다.
- 일반적으로 애플리케이션이 회복 불가능하다. => try-catch를 하지 않는다.
3. Runtime Exception (Unchecked Exception)
- 애플리케이션의 내부 논리 오류로 발생한다.
- 보통 프로그래밍 버그 (논리 오류 / 잘못된 API 사용) 등이 원인이다.
- 주로 코드 자체 수정이 우선이다. => Catch보다는 버그 수정이 필요하다.
- 따로 잡아야 한다기보다는 애초에 발생하지 않도록 설계하는 것이 중요하다.
- 정리
- 의도 : 프로그래밍 오류 -> 내부 논리 오류 발생 시
- 처리 강제 여부 : X
- 주 용도 : 버그 -> 프로그램 코드에서 수정 필요
Multiple catch Clauses
- 하나의 try 블록 내에서 여러 가지 서로 다른 Exception이 발생이 가능하다.
- 이를 각기 다른 catch 블록에서 처리가 가능하다.
하나의 try문에서 생길 수 있는 다양한 Exception에 대해서 catch 블록을 여러 개 나열하여 각각에 대해 다르게 처리
‘throw’ keyword
- throw는 exception Object를 생성해서 강제로 발생시키는 키워드
- try-catch문 없이 프로그래머가 의도적으로 특정 Exception을 발생시킬 때 사용된다.
처리 흐름 (throw 실행)
- 현재 실행중이던 메서드 중단
- Exception Object가 생성되어 호출 스택 상위로 전파
- 적절한 try-catch 블록에서 처리될 때까지 계속 전파
- 만약 어디서도 처리하지 않으면 JVM 까지 전파되어 프로그램의 비정상 종료
‘throws’ keyword
- throws는 메서드 선언부에서 사용된다.
- 해당 메서드가 어떤 Exception을 발생시킬 수 있는지를 명시한다.
처리 흐름(throws 실행)
- 메서드에서 Checked Exception 발생 가능
- 메서드 호출자는 try-catch로 처리하거나, 호출자도 다시 throws로 선언해서 상위로 넘긴다.
- 최종적으로 JVM까지 Exception 전파 시 처리되지 않으면 프로그램의 비정상 종료
‘finally’ keyword
- finally는 try-catch-finally 구조에서 사용된다.
- 목적 : 예외 발생 여부와 관계없이 항상 실행되는 블록을 의미한다.
- 예외 발생 흐름과 무관하여 실행이 보장된다.