아무리 생각해도.. 티스토리의 마크다운은 좀 많이 불편하다.. 그렇다고 다시 github.io로 돌아갈 수도, velog로 돌아갈 수도 없는 노릇이지만.... 이럴 때 어떻게 해야하나요,, 추천 부탁드립니다 :(
오늘은 제이슨의 세번째 자바 기초 강의였던 Java Exception에 대해 듣고, 정리한 내용이다.
우선 Exception의 상속 구조는 다음과 같다. 이미지는 우아한테크코스 수업 자료에서 가져왔는데, 문제가 된다면 얼른! 지우겠습니다
Throwable을 상속하고, Error, Exception이 존재한다.
에러의 경우는 개발자가 에러라는 것을 직접 사용하는 것은 드물다. 여기서 에러를 직접 사용하는 것은 무엇을 의미할까? 우리가 프로그램을 짤 때, 어떤 부분에서 문제가 발생될 것으로 예상될 때, 에러가 발생할 것으로 예상한다. 예를 들어, 나이를 입력하라고 했는데, 문자를 입력하는 경우 프로그램 상에서 적절한 포맷이 아니라는 에러가 발생할 수 있기 때문에, 미리 try-catch 구문을 통해 막거나, 아니면 그냥 적절한 에러 메시지를 통해 에러를 터뜨리곤 한다. (클라이언트의 잘못으로 넘기는 것?)
즉, 개발자는 에러를 직접 사용한다기 보다는 에러를 handle한다는 표현이 더 어울릴 것 같다. (반박 환영, 댓글 부탁드립니다 🙂)
아무튼, 그래서 이러한 에러는 자바의 런타임 시점에서 발생하는 런타임 에러, 컴파일 시점에서부터 발생하는 컴파일 에러가 있다. 컴파일 에러는 요즘 우리보다 더 똑똑한 IDE들이 잘 잡아준다. 런타임 에러가 문제!
아무튼 쓸데없는 말은 이제 그만하고, 본론이 checked Exception과 unchecked Exception에 대해서 알아보자.
Checked Exception
Checked Exception이란 CompileTime Exception이라고도 하며 확인을 해야되는 예외라고 볼 수 있다. 컴파일 시점에 Exception을 catch하는지 확인한다. 컴파일 시점에 Exception에 대한 처리(try/catch)를 하지 않을 경우 컴파일 에러가 발생한다. Exception이 발생하는 메소드에서 throws 예약어를 활용해 Exception을 호출 메소드에 전달해야 한다.
이 시점에 이걸 사용하는 코드들은 이 예외에 대해 확인을 해야하고 처리를 할 지, 혹은 나를 호출하는 다른 것에 그 처리를 위임할 지 결정을 해야한다. 요약하자면 무시할 수 없고 내가 다룰지, 혹은 던져줄 지 결정해야한다.
Unchecked Exception
런타임시점에서 발생하는 예외이다.(Runtime Exception을 상속한다.) 컴파일 시점에 Exception을 핸들링하지 않아도 된다. Exception이 발생하는 메소드에서 throws 예약어를 활용해 Exception을 처리할 필요가 없다. 하지만 처리해도 무방하다.
What is better between Checked Exception and Unchecked Exception?
항상 듣는 이야기는, 무엇이 더 낫다는 것은 없다. (정답은 없다.) 하지만 상황에 따라 적절한 타입의 에러를 이용할 수 있다.
- 호출하는 메서드가 Exception을 활용해 무엇인가 의미있는 작업을 할 수 있다면 Checked Exception을 사용해라.
- 만약 호출하는 메서드가 Exception을 catch해 예외 상황을 해결하거나 문제를 해결할 수 없다면 Unchecked Exception을 사용해라.
- 명확하지 않다면 Unchecked Exception을 사용해라.
여기서,, 위 내용들이 애매하다! 싶을 때 도움이 되는 우테코 크루들의 한 줄 요약
- Checked Exception --> 집을 수리하는 데 내 손에 망치가 있다. 다칠 걸 알고 있기 때문에 미리 구급차를 대기시키는 것과 같다.
- Checked Exception --> 가스가 누출될 수 있으니 잘 막아주세요. // Unchecked Exception --> 가스가 누출되면 잘 막아주세요.
여기에 더불어, 강의 중간중간 나왔던 내용들을 덧붙여 보자면,
try {
System.out.println("try");
throw new CustomFirstException();
} catch (CustomFirstException e) {
System.out.println("1-catch");
throw new CustomSecondException();
} catch (CustomSecondException e) {
System.out.println("2-catch");
}
위와 같은 코드에서 "2-catch"는 과연 실행될까?
정답은, 실행되지 않는다. try 구문 내에서 던진 에러만 catch 문에서 잡는다!
프로그래밍을 할 때, Custom Exception을 사용하는 것이 좋을까?
정답은, 또 없다. ㅋㅋㅋ 정답이라고 하기 보다는 상황에 따라 알맞은 것을 이용하면 된다. 에러 핸들링을 하는 과정에서 코드를 읽을 때 가독성을 위해 커스텀을 사용하는 것이 좋다는 의견도 있고, 메시지 전달이 주이니 기존의 익셉션에 적절한 메시지를 보내면 된다는 의견도 있었다. 내 생각에는 크리티컬하게 다루어야하는 에러라면 커스텀 에러를 통해 로그에서 구분될 수 있도록 해주는 것이 좋을 것 같고, 그가 아니라면 그냥 기존에 존재하는 예외를 사용해도 좋을 것 같다. 🧐