Java 는 에러를 자바 프로그램 입장에서의 에러 발생 근원(Source)에 따라 2가지로 구분
자바 프로그램 “외부”에서 발생하는것 : (Need to be) Checked Exception
자바 프로그램 “내부 로직”에서 발생하는것 : Unchecked Exception
- (블랙박스) 어떤 상황에서 발생되는지 예측할 수 없어, 어떻게 복구해야할지 전혀 알 수 없다. + 그 때마다
- 그래서 로그를 잘 남겨야한다. 그게 Unchecked Exception 처리의 근본이자 원칙
- 대다수가 (Unchecked) Exception 처리를 했다하면 로그도 안남기고 심지어는 먹어버리는 실수
“인생으로 치면 어떤 상황이 발생할지 모르기에, 인생 중 모든 경우의 수를 대처할 수 없다.”
충분히 예상가능한 에러이기에, 콕 집어 복구가 꼭 필요한 예외
”파일을 읽을 때, 파일이 존재하지 않을 때에 대한 대비가 필요합니다.
제발 처리하시고 컴파일하세요.”
private static void checkedExceptionWithTryCatch() {
File file = new File("not_existing_file.txt");
try {
FileInputStream stream = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}private static void checkedExceptionWithThrows() {
File file = new File("not_existing_file.txt");
FileInputStream stream = new FileInputStream(file);
}[많이 쓰이는 Checked Exception]
- IOException : 이용자는 충분히 이상한 걸 입력할 수 있다.
- SQLException : 데이터베이스 접속은 충분히 갑자기 끊길 수 있다.
- ParseException : 파싱하려는 값이 충분히 의도와 다른 값(NULL 등)이 들어있을 수 있다.
에러가 어떤 상황에서 발생될지 예측할 수 없기에, 어떻게 복구해야할지 전혀 알 수 없다.
“RuntimeException 발생 시 원인이 너무 다양하기에 로그와 Stacktrace 를 남겨 셜록 홈즈를 부릅시다.”
private static void uncheckedExceptionWithTryCatch(String str) {
try {
str = str.toUpperCase(); // str 로 건네받은 파라미터가 null 일 수 있다.
System.out.println(str);
} catch (NullPointerException e) {
e.printStackTrace();
}
}“Java 를 잘하는 개발자는 (Runtime)Exception 처리를 잘하는 개발자이다.“
- Exception 처리를 잘한다는 건 매 로직에서 발생할만한 에러, 상황들을 예지할 수 있단 뜻
- Exception 처리를 잘하는 개발자란?
- 상황 “범주”에 맞춰 Custom Exception 정의
- 적합한 곳에서, 어떤 조건에 적합한 Custom Exception 발행(Throw 최초 발행)
- 중간 어딘가에서 적합한 처리 2가지 : Throws vs Try-Catch
try {
// ...
} catch (IllegalArgumentException | IndexOutOfBoundsException error) {
} catch (FileNotFoundException e) {
} catch (IOException e) {
} catch (Exception e) {
}
try {
// ...
} catch (error) {
if (error instanceof TypeError) {
} else if (error instanceof ReferenceError) {
} else if (error instanceof SyntaxError) {
} else if (error instanceof RangeError) {
} else {
}
}
Custom Exception Class 를 만들어놓았다면, instanceof 를 통해 클래스 타입 분류
try {
// ...
} catch (error) {
if (error.name === "TypeError") {
} else if (error.name === "ReferenceError") {
} else if (error.name === "SyntaxError") {
} else if (error.name === "RangeError") {
} else {
}
}
Custom Exception 을 프로퍼티로 분류하도록 했다면, 프로퍼티를 통해 타입 분류
class CustomException extends RuntimeException {
private String type;
private String code;
public CustomException(String type, String code, String message) {
super(message);
this.type = type;
this.code = code;
}
}
추가로 Java 의 Exception 에는 어떤 값들이 들어있을까?
try {
// ...
} catch(RuntimeException e) {
System.out.println(e.getCause());
System.out.println(e.getMessage());
System.out.println(e.getStackTrace());
e.printStackTrace();
}
class CustomError extends Error {
// type;
// code;
constructor(type, code. message) {
super(message);
this.type = type;
this.code = code;
}
}
추가로 Javascript 의 Error 에는 어떤 값들이 들어있을까?
try {
testfunction() // 존재하지 않는 함수를 호출하였을때
} catch(err) {
alert(err.name); // ReferenceError
alert(err.message); // testfunction is not defined
alert(err.stack); // ReferenceError: testfunction is not defined at ... (호출 스택)
}
[여러 계층에서 Exception 발생 시 처리 방법]
1. 한곳에서 다 처리하기
2. 중간에 받아서 다시 넘기기 (Exception 타입 변경)
3. 중간에서 받아서 처리하기 (의도적 먹어버림)
하지만 라이브러리에서 사용을 강제하는게 아닌 이상에야 일반적으로 Checked Exception 은 사용하지 않는다.
얼마나 예외처리 Exception 을 잘 다루는지가 능력있는 개발자인지 여부를 가른다.