본문 바로가기
java-liveStudy

9주차 과제. 예외

by 에드박 2021. 1. 16.

목표

자바의 예외 처리에 대해 학습하세요.

학습할 것 (필수)

  • 자바에서 예외 처리 방법 (try, catch, throw, throws, finally)
  • 자바가 제공하는 예외 계층 구조
  • Exception과 Error의 차이는?
  • RuntimeException과 RE가 아닌 것의 차이는?
  • 커스텀한 예외 만드는 방법

 


1. Exception VS Error

자바에서 Runtime 에 발생할 수 있는 프로그램 오류는 두가지가 있습니다.

  • Error(에러)
  • Exception(예외)

 Error(에러) 

  • 시스템에 비정상적인 상황이 생겼을 때 발생
  • 시스템 레벨에서 발생하기 때문에 일단 발생하면 수습될 수 없는 심각한 오류
  • 개발자가 미리 예측하여 처리하는게 불가능
  • 애플리케이션에서 Error 처리를 따로 신경쓰지 않아도 됨
  • 예시) 메모리 부족(OutOfMemoryError), 스택오버플로우(StackOverflowError)

 

 Exception(예외) 

  • 개발자가 구현한 로직에서 발생
  • 프로그램 코드에 의해서 수습될 수 있는 다소 미약한 오류
  • 발생할 상황을 미리 예측하여 처리할 수 있음
  • 예외는 개발자가 처리할 수 있기 때문에 예외를 구분하고 그에 따른 처리 방법을 명확히 알고 적용하는것이 중요
  • 예시) IndexOutBoundException, ArithmeticException, ClassCastException, NullPointException...

2. 자바에서 예외 처리 방법

  • UncaughtExceptionHandler
  • try-catch-finally
  • throw
  • throws

 예외 처리의 정의와 목적 

  • 정의 : 프로그램 실행 시 발생할 수 있는 예외에 대비한 코드를 작성하는 것
  • 목적 : 프로그램의 비정상 종료를 막고, 정상적인 실행상태를 유지하는 것
발생한 예외를 처리하지 못하면, 프로그램은 비정상적으로 종료되며, 처리되지 못한 예외(uncaught exception)는 JVM의 '예외처리기(UncaughtExceptionHandler)'가 받아서 예외의 원인을 화면에 출력합니다.

 

 2-1. UncaughtExceptionHandler 

(참고 : semtax.tistory.com/81)

  • 발생한 예외를 처리하지 못하면, 프로그램은 비정상적으로 종료되며, 처리되지 못한 예외(uncaught exception)는 JVM의 '예외처리기(UncaughtExceptionHandler)'가 받아서 예외의 원인을 화면에 출력합니다.

자바를 사용하다 보면 사용자가 어떠한 예외도 처리하지 않는 경우에도 에러메시지가 출력되면서 프로그램이 종료 되는것을 볼 수 있습니다.

 

아래 코드는 배열의 인덱스가 9까지인 int 배열 변수 arr에서 12의 인덱스에 접근하는 코드입니다.

 

예외를 따로 처리하지 않은 코드
ArrayIndexOutOfBoundsException이 발생하고 에러 메시지를 출력해줍니다.

 

위 에러메시지는 자바의 Thread 클래스에 있는 UncaughtExceptionHandler 에 의해 기본적으로 등록된 핸들러에서 처리해준 메시지 입니다.

 

UncaughtExceptionHandler를 따로 설정하지 않는다면

Java 에서 기본적으로 정의된 UncaughtExceptionHandler가 실행이 됩니다.

 

Thread 클래스의 UncaughtExceptionHandler 인터페이스

 

위의 UncaughtExceptionHandler 를 직접 구현해서 사용할 수도 있습니다.

 

아래는 UncaughtExceptionHandler 를 구현한 DefaultExceptionHandler 입니다.

 

UncaughtExceptionHandler 를 구현한 DefaultExceptionHandler 클래스

 

직접 구현한 DefaultExceptionHandler 클래스를 적용하는 방법은 간단합니다.

Thread 클래스의 setDefaultUncaughtExceptionHandler() 메소드를 사용하면 됩니다.

 

직접 구현한 UncaughtExceptionHandler 를 등록하는 방법

 

위의 코드를 실행해보면 달라진 에러 메시지가 출력되는걸 확인할 수 있습니다.

 

 

 

 2-2. try-catch 문 (예외 복구) 

  • 다른 작업 흐름으로 유도

위의 코드는 재시도를 통하여 예외를 극복하는 코드입니다.

네트워크 환경이 좋지않아서  서버에 접속이 안되는 상황에서 적용하면 좋은 코드입니다.

 

예외 복구의 핵심은 예외가 발생하여도 애플리케이션은 정상적인 흐름으로 진행된다는것입니다.
재시도를 통해 정상적인 작동을 하게 한다거나, 예외가 발생하면 이를 미리 예측하여
다른 흐름으로 유도시키도록 구현하면 비록 예외가 발생하였어도 정상적으로 작업을 종료할 수 있습니다.

 

예외가 발생할 때마다 애플리케이션이 종료되버린다면 매우 곤란할것입니다. 따라서 해당 예외를 try-catch 문으로 처리하여 예외가 발생하더라도 복구하고 계속해서 실행을 유지할 수 있습니다.

 

finally블록

  • 예외의 발생 여부에 관계없이 항상 수행됩니다.
  • finally블럭은 try-catch 문의 맨 마지막에 위치합니다.

 

 2-3. throws (예외처리 회피, 예외 되던지기) 

  • throws 키워드를 사용해서 메소드에서 발생할 수 있는 예외처리를 메소드를 호출하는 쪽으로 넘기는 것입니다. 
  • 메소드의 선언부에 선언함으로써 이 메소드를 사용하려는 사람이 어떠한 예외들이 처리되어져야 하는지 쉽게 알 수 있습니다.
  • 메소드를 사용하는 쪽에서 이에 대한 처리를 하도록 강요하기 때문에 보다 견고한 프로그램 코드를 작성할 수 있습니다.
  • 예외를 처리하는 코드를 자유롭게 작성할 수 있습니다.
  • 하지만 무책임하게 던지는것은 위험합니다. 해당 메소드에서 이 예외를 던지는 것이 최선의 방법이라도 생각될 때만 사용해야 합니다.
  • 여러개를 사용하는경우 쉼표(,) 로 구분하여 정의할 수 있습니다.

 2-4. throw (예외 전환, 예외 던지기) 

 

  • throw 키워드를 사용해서 예외를 고의로 발생시킵니다.
  • 예외 상황을 직접 처리하기 위해 사용하거나 중첩 예외를 발생시킬 때 사용할 수 있습니다.
  • 호출한 쪽에서 예외를 받아서 처리할 때 좀 더 명확하게 인지할 수 있도록 돕기 위한 방법입니다.

 

 

호출한 쪽에서 예외를 받아서 처리할 때 좀 더 명확하게 인지할 수 있도록 돕기 위한 방법입니다.
어떤 예외인지 분명해야 처리가 수월해지기 때문입니다. 예를들어 Checked Exception 중 복구가 불가능한 예외가 잡혔다면 이를 Unchecked Exception으로 전환하여서 다른 계층에서 일일이 예외를 선언할 필요가 없도록 할 수도 있습니다.

 

 

예외가 복구 로직을 만들 수 있는 경우라면 (네트워크 지연 시 재시도를 해볼 수 있다거나, 다른 곳에서 받아올 수 있다거나, 기본값을 사용할 수 있을 때) try-catch 문으로 복구 로직을 사용해야합니다.
이 때 던지는 예외로는 UncheckedException이 아닌 CheckedException을 던집니다.
UncheckedException을 사용할 수 없는것은 아니지만
CheckedException을 던지면 예외처리를 강제할 수 있기 때문에 더욱 안전한 코드를 만들 수 있습니다.

3. 자바가 제공하는 예외 계층 구조

  • 자바에서는 실행 시 발생할 수 있는 오류(Exception과 Error)를 클래스로 정의하였습니다.
  • Error와 Exception 클래스역시 Object 클래스의 자손입니다.
  • 자바에서는 클래스들을 두 그룹으로 나눌 수 있습니다.
  • 1. Exception클래스와 그 자손들 (RuntimeException 과 그 자손들 제외)
  • 2. RuntimeException 클래스와 그 자손들 

 

 

예외 클래스의 계층도

 

Exception 클래스들은 CheckedException
RuntimeException 클래스들은 UncheckedException 이라고 부릅니다.

4. RuntimeException 과 RE가 아닌 것의 차이는?

RuntimeException 클래스는 주로 프로그래머의 실수에 의해서 발생될 수 있는 예외들로 자바의 프로그래밍 요소들과 관계가 싶습니다. 예를 들면, 배열의 범위를 벗어난다던가(IndexOutBoundException) 값이 null인 참조변수의 멤버를 호출하려 했다던가 (NullPointerException) 하는 경우에 발생합니다.

 

Exception 클래스(RuntimeException 클래스와 그 서브 클래스 제외)는 주로 외부의 영향으로 발생할 수 있는 것들로서, 프로그램 사용자들의 동작에 의해서 발생하는 경우가 많습니다. 예를 들면, 존재하지 않는 파일의 이름을 입력했다던가(FileNotFoundException), 실수로 클래스의 이름을 잘못 적었다던가(ClassNotFoundException), 또는 입력한 데이터 형식이 잘못된(DataFormatException) 경우에 발생합니다.

 

  • Exception 클래스들 : 사용자의 실수와 같은 외적인 요인에 의해 발생하는 예외. 반드시 예외를 처리해야함
    (CheckedException)
  • RuntimeException클래스들 : 프로그래머의 실수로 발생하는 예외. 명시적인 처리를 강제하지 않음
    (UncheckedException)

 

RuntimeException 과 Exception의 차이

여기서부터는 Exception 클래스들을 CheckedException
RuntimeException 클래스들을 UncheckedException 이라고 부르겠습니다.

 

둘의 명확한 차이는 '꼭 처리를 해야 하느냐'

  • CheckedException이 발생할 가능성이 있는 메소드라면 반드시 로직을 try-catch 문으로 감싸거나 throws 로 예외를 던져줘야 합니다. CheckedException은 개발자가 어쩔 수 없는 상황에 의해 발생하는 예외사항 이므로 
  • UncheckedException은 명시적인 처리를 하지 않아도 됩니다. 이 예외는 피할 수 있지만 개발자의 부주의로 발생하는 경우가 대부분입니다. 예측하지 못한 상황에서 발생하는 예외가 아니기 때문에 굳이 로직으로 처리할 필요가 없도록 만들어졌습니다.

예외를 확인하는 시점

  • CheckedException : 컴파일 단계에서 체크가 가능합니다.
  • UncheckedException : 컴파일 단계에서 체크할 수 없는 예외입니다. 실행 과정중 어떤 특정한 논리에 의해 발견되는 예외를 말합니다. 실행 과정중 발생한다 하여 RuntimeException 이라고 합니다.

5. 커스텀한 예외를 만드는 방법

커스텀한 예외를 만드는 방법은 간단합니다.

 

  • CheckedException을 만든다면 Exception을 상속받습니다.(Exception을 확장)
  • UncheckedException을 만든다면 RuntimeException을 상속받습니다.(RuntimeException을 확장)

 


 

 

참고 문헌

- www.nextree.co.kr/p3239/

- semtax.tistory.com/81

- woowabros.github.io/experience/2019/01/29/exception-in-transaction.html

- reference-m1.tistory.com/246

 

'java-liveStudy' 카테고리의 다른 글

11주차. Enum  (0) 2021.01.24
10주차 과제. 멀티쓰레드 프로그래밍  (0) 2021.01.17
8주차. 인터페이스  (0) 2021.01.09
7주차. 패키지  (0) 2021.01.01
6주차 과제. 상속  (0) 2020.12.25

댓글