[JAVA] 에러와 예외

용용학생·2024년 4월 9일

자바

목록 보기
9/32
post-thumbnail

오류의 종류

프로그래밍을 하다보면 예기치 않은 오류를 만나기도 하고 심각하면 프로그램이 강제로 종료되기도 한다.

프로그램 오류의 원인으로는 크게 3가지로 나눌 수 있다.

  1. 논리 에러 : 실행은 되지만 의도와는 다르게 작동하는 것
  2. 컴파일 에러 : 컴파일 시에 발생하는 에러
  3. 런타임 에러 : 프로그램 실행 중에 발생하는 에러

논리 에러

논리 에러는 프로그램이 실행되는 데에는 전혀 문제가 없지만, 결과가 예상과 달라 사용자가 의도된대로 작업을 수행하지 못하는 문제이다.

예를 들어, 전진 키를 눌렀는데 우회전을 한다거나 피가 0이 되어도 죽지 않는다거나 하는 경우를 들 수 있다.

논리 에러는 컴퓨터 입장에서는 문제가 없기 때문에 에러 메시지를 알려주지 않는다.
논리 에러의 해결 방법은 프로그램의 코드와 알고리즘을 확인해보아야 한다.

컴파일 에러

컴파일 에러는 컴파일 단계에서 오류를 발견하여 에러 메시지를 출력하는 것을 말한다.

컴파일 에러의 대표적인 원인은 문법 오류(Syntax Error)이다.
예로, 문장의 끝에 세미콜론;을 생략했다거나 문자형으로 반환해야하는데 정수형으로 반환했을 경우이다.

컴파일 에러는 실행되기 전 컴파일 단계에서부터 걸러지기 때문에 심각한 문제는 아니고 오히려 미리 발견할 수 있기 때문에 다행인 오류이다.

런타임 에러

런타임 에러는 프로그램이 실행되는 중에 발생하는 오류이다.

런타임 에러를 잘 다루어야 프로그램이 실행 중에 비정상적으로 종료되는 일을 막을 수 있다.

자바의 예외


자바에서의 예외 상속 계층은 그림처럼 이루어져 있다.

Throwable

Throwable 클래스는 모든 에러와 예외 클래스의 슈퍼 클래스이다.

이 클래스를 상속받은 객체들만 throw되어질 수 있기 때문에 모든 예외는 이 클래스를 상속받고 있다.

이 클래스에 정의된 두 메서드를 이용하면 예외 처리에 도움이 된다.

  • getMessage() : 던져진 예외의 세부 메시지 문자열을 반환
  • printStackTrace() : 예외가 발생한 시점의 발생 메서드, 해당 메서드를 호출한 메서드, 그 상위 메서드들이 순차적으로 표시됨

Error

  • 시스템 레벨에서 발생하는 심각한 문제를 나타냄
  • 개발자가 대처할 방법이 없다
  • 프로그램이 비정상적으로 종료되되록 유도한다
  • 메모리 부족(OutOfMemoryError)나 스택오버플로우(StackOverflowError) 같은 문제가 발생할 때 던져진다

Exception

  • 프로그램 코드에 의해 발생하는 문제
  • Error 에 비해 상대적으로 미약한 문제
  • 미리 예측하여 대응 코드를 작성해놓을 수 있기에 적절한 예외 처리가 중요함

Exception 클래스는 그림에서 알 수 있듯이 RuntimeException(과 그 하위 클래스들)과 그 외의 클래스들로 나누어진다.

이 구분은 Checked ExceptionUnchecked Exception으로 볼 수 있다.

Checked Exception

Checked Exception은 RuntimeException 클래스를 상속 받지 않은 Exception 클래스의 모든 하위 클래스를 말한다.

이름처럼 Checked Exception에 해당하는 클래스들은 무조건 예외에 대한 처리가 되어야 한다. 그렇지 않으면 컴파일 에러가 발생한다.

Unchecked Exception

Unchecked Exception은 RuntimeException과 그 하위 클래스들을 말한다.

Checked와 Unchecked Exception의 중요한 차이가 있다.

  • 컴파일러의 도움을 받을 수 있나
  • 시점의 차이 (컴파일과 런타임)
  • RuntimeException 을 상속받는가

Checked Exception 과는 반대로 예외에 대한 처리를 명시해줄 필요가 없다.

그렇다면 왜 Unchecked Exception은 예외 처리를 할 필요가 없을까?

public void main(String[] args) { 
    try {
        int[] list = {1, 2, 3, 4, 5};
        System.out.println(list[0]);
    } catch (ArrayIndexOutOfBoundsException e) {
        e.printStackTrace();
    }
}

이런 간단한 예시에서도 "배열의 범위를 넘어선 인덱스에 접근할 가능" 때문에 예외처리를 해야 한다면 불필요하게 복잡한 코드가 만들어질 것이다.

공식 문서에서도 이러한 이유가 나타나 있다.
1. Error 클래스는 기본적으로 핸들링이 불가능하기 때문에 처리를 명시할 필요가 없다.
2. RuntimeException 클래스가 발생시킬 수 있는 예외는 컴파일러가 모두 분석하기엔 불가능하고 그렇다고 모든 부분을 다 명시적으로 처리하기에는 코드가 깨끗하지 못하기 때문이다.

profile
자바 스프링 공부하는 정리 블로그!

0개의 댓글