1. 자바 예외 클래스 계층 구조.

2. 사용자 정의 예외가 필요한 이유.
- Java는 프로그래밍 중 발생할 수 있는 일반적인 예외들을 대부분 제공하고 있음.
- 하지만 실제 개발에서는 기본적으로 제공되는 일반적인 예외들만으로는 아쉬운 점과 불편한 점이 있어서
사용자 정의 예외를 추가해야 할 필요가 있음.
- 비즈니스 로직 예외.
- 특정 업무 규칙이나 프로세스에 맞는 예외를 정의해놓으면 문제의 상황을 더 명확히 이해할 수 있음.
- 기존 예외의 세분화.
- 기존에 있는 예외 중 일부 상황만 뽑아내서 별도로 처리할 때 유용함.
2-1. Checked vs Unchecked
- Java의 Exception은 크게
체크 예외(Checked Exception)와 언체크 예외(Unchecked Exception)으로 나눔.
- 체크 예외(Checked Exception)
- Exception 클래스와 그 자손들.
- 예외처리 안 하면 컴파일이 안됨.
- 사용자의 실수처럼 외적인 요인에 의해 발생하는 예외.
- 언체크 예외(Unchecked Exception)
- RuntimeException 클래스와 그 자손들.
- 예외처리가 선택임.
- 프로그래머의 실수로 인해 발생하는 예외.
2-1-1. (Checked) Ex.
체크(Checked) 예외는 반드시 예외처리를 해야됨.
try (Scanner file = new Scanner(new File(fileName))) {
if (file.hasNextLine()) return file.nextLine();
} catch(FileNotFoundException e) {
}
- 위처럼 특정 파일의 첫 번째 줄을 읽는 코드가 있을 경우.
- 해당 코드는
FileNotFoundException을 처리하긴 하지만
좀 더 세부적으로 "파일이 아예 없는 것인지?" or "파일명이 잘못된 것인지?" 알 수 없음.
- 따라서 파일 이름이 잘못된 경우를 구분하기 위해 새로운 사용자 정의 예외를 만듦.
public class IncorrectFileNameException extends Exception {
public IncorrectFileNameException(String errorMessage) {
super(errorMessage);
}
}
↑ 위 코드를 ↓아래와 같이 활용할 수 있음.
try (Scanner file = new Scanner(new File(fileName))) {
if (file.hasNextLine())
return file.nextLine();
} catch (FileNotFoundException e) {
if (!isCorrectFileName(fileName)) {
throw new IncorrectFileNameException("잘못된 파일명: " + fileName );
}
}
- 근데 이렇게 작성할 경우 기존의 예외 원인(
FileNotFoundException )이 사라져버림.
- 따라서 이를 보완하려면 생성자에
Throwable을 추가해서 원인 예외를 함께 전달해야됨.
public class IncorrectFileNameException extends Exception {
public IncorrectFileNameException(String errorMessage, Throwable err) {
super(errorMessage, err);
}
}
- 그러면
↓아래와 같이 원인 예외와 함께 던질 수 있음.
catch (FileNotFoundException err) {
if (!isCorrectFileName(fileName)) {
throw new IncorrectFileNameException("잘못된 파일명: " + fileName, err);
}
}
2-2-2. (Unchecked) Ex.
- 이번에는 파일 이름에 확장자가 아예 없는 경우.
- 이 문제는 컴파일 시점이 아니라 RuntimeException, 즉 실행중에만 발생하므로
Unchecked 예외가 적절함.
- 이를 위해
RuntimeException을 상속받아 사용자 정의 예외를 만듦.
public class IncorrectFileExtensionException extends RuntimeException {
public IncorrectFileExtensionException(String errorMessage, Throwable err) {
super(errorMessage, err);
}
}
try (Scanner file = new Scanner(new File(fileName))) {
if (file.hasNextLine()) {
return file.nextLine();
} else {
throw new IllegalArgumentException("읽을 수 없는 파일");
}
} catch (FileNotFoundException err) {
if (!isCorrectFileName(fileName)) {
throw new IncorrectFileNameException("잘못된 파일명: " + fileName, err);
}
} catch (IllegalArgumentException err) {
if (!containsExtension(fileName)) {
throw new IncorrectFileExtensionException("확장자가 없는 파일명: " + fileName, err);
}
}
3. 결론.
- 따라서 사용자 정의 예외는 비즈니스 로직과 밀접한 문제 상황을 명확하게 드러낼 때 매우 유용함.
- 적절하게 사용한다면 예외 처리와 로깅을 매우 효율적으로 할 수 있음.
4. 참고.