Java 프로그램을 실행시킬 때, 프로그램 로직이 잘못 설계되었거나, 외부적인 요인, 혹은 하드웨어 문제에 의해 오류가 발생한 적이 있을 것이다. 자바에서는 이렇게 예상과 다른 결과를 만들어 내거나, 심각하면 프로그램을 종료시키는 오류들을 Error와 Exception으로 구분한다.
Error vs Exception
정확히 말하자면, 자바에서는 오류를 'Checked Exception', 'Unchecked Exception', 'Error' 총 3개로 구분한다. 이러한 오류들은 개발자가 예측할 수 있는지, 핸들러를 통해 처리/복구할 수 있는지, 시스템 레벨과 애플리케이션 레벨중 어디에서 발생하는지, 예외처리가 강요되는지, RuntimeException을 상속하는지 등에 따라 구분된다.
Error vs Exception
- Error
- 시스템 레벨에서 발생하고, 프로그램이 복구하거나 재시도 할 수 없는 심각 수준의 오류이다
- JVM 실행 자체에 문제가 생긴 것이 아니기에 개발자가 미리 예측할 수 없고, 따라서 애플리케이션에서 예외처리 로직을 통해 처리 할 수 없다
- 시스템 환경, 메모리 용량, 하드웨어, 프레임워크나 라이브러리 버전 문제 등의 원인이 존재하고, 전체적인 시스템에 변화를 주어야 해결할 수 있는 경우가 대부분이다
- 컴파일 에러, 런타임 에러, 논리적 에러로 나뉘어진다
- Throwable 클래스를 상속받는다
- ex) OutOfMemoryError(메모리 부족), StackOverflowError(스택 오버플로우) 등
- Exception
- 애플리케이션 레벨에서 발생한다
- 개발자가 구현한 로직에서 문제가 생긴 것이므로, 미리 예측 가능하기 때문에 예외 처리 로직을 통해 처리할 수 있다
- RuntimeException의 상속 여부에 따라서 Checked Exception과 Unchecked Excpetion으로 나뉜다
- Throwable 클래스를 상속받는다
- ex) IOException, NullPointerException, IndexOutOfBoundException 등
Error
에러는 발생 시점에 따라 크게 컴파일 에러, 런타임 에러, 논리적 에러로 구분한다. 각각 에러들에 대해 알아보자
컴파일 에러(Compillation Error)
- 컴파일 단계에서 발생한 에러
- 컴파일이 완료되기 전에 발생한 에러로, 프로그램이 만들어지지 않아 프로그램 실행 자체가 불가능한 상태이다. 따라서 심각한 오류를 발생시키지는 않는다
- 원래는 컴파일러가 소스 코드를 javac.exe로 컴파일 하는 과정에서 전반적인 코드를 체크해서 에러 메세지를 보여주는 형태이지만, IDE에서 일정 주기로 계속 자동으로 컴파일을 해주기 때문에 개발자는 바로 문제를 알 수 있는 것이다
- 컴파일 에러가 일으킨 부분을 개발자가 수정하여 해결할 수 있다
- ex) 대표적으로 맞춤법, 문장부호(;), 선언되지 않은 변수 사용 등에 해당하는 문법 구문 오류(syntax error)가 있다
런타임 에러(Runtime Error)
- 프로그램 실행 중에 발생한 에러
- 프로그램을 계속 실행시킬 수 없는 심각한 오류로, 프로그램이 비정상적으로 종료된다
- 대체로 개발 시 설계 미숙(논리적)으로 발생하는 에러가 대부분이며, 개발자가 에러 메시지를 역추적해서 원인을 확인한 후 수정하여 고칠 수 있다
- ex) OutOfMemoryError, StackOverflowError 등
논리 에러(Logic Error)
- '버그'라고 생각하면 된다
- 위의 두 에러처럼 프로그램 실행 자체에 문제가 생기지는 않지만, 실행 결과가 개발자의 예상과 달라 의도한 작업을 수행하지 못하게 되는 경우를 말한다
- 컴퓨터 입장에서는 프로그램이 정상적으로 돌아가는 것이니 에러 메시지를 띄워주지 않는다. 따라서 개발자가 프로그램의 전반적인 코드 흐름을 따라가며 원인을 찾아야 한다
- ex) 재고가 음수가 되거나, 게임 캐릭터가 피가 0이어도 죽지 않는 경우 등
Exception
Exception은, 코드적 관점에서 '반드시 예외 처리를 해야 하는가?'에 따라 Checked Exception과 Unchecked Exception으로 나뉜다. 이를 구분하는 방법으로는 RuntimeException의 상속 여부를 확인하여 알 수 있다
Checked Exception
- 컴파일 예외 클래스를 가리키는 것으로, Exception을 상속받는 하위 클래스중 RuntimeException을 제외한 모든 예외를 말한다
- 컴파일 단계에서 확인한다
- 반드시 명시적으로 예외 처리를 해야한다. 그렇지 않으면 컴파일 되지 않는다
예외 발생시 트랜잭션을 roll-back 하지 않는다- ex) IOException, FileNotFoundException, SQLException 등, 주로 JVM 외부와의 통신에서 주로 사용된다
Unchecked Exception
- 런타임 예외 클래스를 가리키는 것으로, RuntimeException과 그 하위 예외를 말한다
- 런타임 단계에서 확인한다
- 명시적으로 예외 처리를 해주지 않아도 프로그램 실행이 가능하다
예외 발생시 트랜잭션을 roll-back 처리한다- ex) NullPointerException, illegalArgumentException, IndexOutOfBoundException, SystemException 등
Transaction Roll-back과 Exception
- Java에서 Checked/Unchecked Exception에 따라 Transaction Roll-back 처리를 한다는건 정확하지 않은 정보이다.
정확히 말하면 Java에서 Transaction Roll-back과 Exception은 전혀 상관이 없다 - Transaction의 정의, '데이터베이스의 상태를 변환시키는 하나의 논리적 기능을 수행하기 위한 작업의 단위'에서 생각해본다면 예외처리를 해준 Checked Exception에서는 DB 상태 변화 자체가 일어나지 않아서 Roll-back을 언급할 필요가 없다
- Unchecked Exception은 어떨까?
- Java에서는 Unchecked Exception시에 사용자 정의에 따라서 Roll-back을 할 수도, 안할 수도 있다
- Unchecked Exception에서 Roll-back을 한다는건, Spring Framework에서 기본적으로 트랜잭션을 롤백 시키기 때문에 나온 얘기이다. 따라서 Springr과 Java를 동일시 시키지 않는 이상, Exception과 Transaction Roll-back은 아무런 관계가 없는 것이다
Exception Handling
그렇다면 Checked Exception에서 명시적인 예외 처리는 어떻게 하는것일까?
이는 Checked Exception이 발생할 가능성이 있는 메서드를 try-catch로 감싸거나, throw를 통해 직접 예외를 발생시키거나, throws로 호출한 쪽에서 예외를 처리할 수 있다
Try-Catch
- try 구문에 위험한 로직이 들어가고, catch를 사용하여 예외 발생시 수행할 로직이 들어간다
- catch 구문에서 특정 예외를 정하여, 예외마다 다른 처리를 해줄 수 있다
- catch 구문에서는 throws로 다른 예외를 던져서 예외 전환을 통해 프로그램을 종료 할 수 있다
- 혹은 다른 로직을 수행하여 계속해서 구문을 실행하는 등의 능동적인 처리가 가능하다
Throws
- 메서드 선언시에 throws Exception을 추가하여 사용한다
- 발생한 exception 처리를, 예외가 발생한 메서드를 호출하는 쪽이 책임지도록 하는 방식이다
- 다른 메서드의 일부분으로 동작하는 경우, throws를 추천한다
- 프로그램이 강제로 종료되기 때문에 수동적이다
Throw
- throws와는 다르게, 메서드 내부에서 개발자가 직접 예외를 발생시키고 싶을 때 사용한다
- 'throw new Excpetion'처럼, checked/unchecked에 상관 없이 모두 사용할 수 있다
- Exception을 커스텀하여 사용하거나 비즈니스 로직 안에서 예외를 던져줄 때, Spring 프레임 워크에서 ExceptionHandler를 사용할 때 주로 사용된다
Reference
- What Is an Excpetion?: https://dev.java/learn/exceptions/what-is-an-exception/
- Error & Exception: https://gyoogle.dev/blog/computer-language/Java/Error%20&%20Exception.html
- 예외 처리에 대한 작은 생각: https://www.nextree.co.kr/p3239/
- 자바 예외처리의 차이: https://pulpul8282.tistory.com/115