[Java] 예외 처리 개념 및 구현

Hood·2025년 10월 16일

Java

목록 보기
3/5
post-thumbnail

들어가기 전

프로그래밍을 하다보면 수많은 에러와 예외를 맞이하게 됩니다.
개발자는 이를 방지하기 위해 예외처리 코드를 작성합니다.
매번 작성되는 예외처리 코드를 제대로 알지 못하고 작성하는 것 같아
이번 포스트는 Java의 예외 클래스의 상속 계층도를 파보려고 합니다.


에러와 예외의 차이

자바의 예외 클래스 상속 계층도를 보면 엄연하게 Error와 Exception을 다르게 봅니다.
그럼 Error(에러)Exception(예외) 의 차이를 먼저 알아봅시다.

Error(에러)?

에러의 사전적 의미는 오류이며
그 말은 부정확하거나 잘못된 동작을 뜻하며
프로그래밍 관점에서는 단순히 잘못된 결과가 아닌 시스템의
안정성과 신뢰성을 좌우하는 중요한 요소입니다.

세 가지 종류로 구분하며
1. 컴파일 오류 : 프로그래밍 언어의 문법 규칙 등을 위반하여 컴파일 시 발생하는 오류
2. 논리 오류 : 문법적으로는 올바르지만 프로그래머의 의도와 다르게 동작하는 오류
3. 런타임 오류 : 프로그래밍 실행 중에 발생하는 오류

메모리 부족(OutOfMemory), 스택오버플로우(StackOverflowError)와 같이
일단 발생하면 복구할 수 없는 심각한 오류이고 예측이 불가능합니다.
즉, 에러는 JVM 실행에 문제가 생긴 것이므로 개발자가 대처할 방법이 없습니다.

Exception(예외)?

Exception는 사전적 의미는 예외이며
오류는 시스템이 종료되어야 할 수준에 수습할 수 없는 심각한 문제이지만
예외는 개발자가 구현한 로직에서 발생한 실수나 사용자의 영향에 의해 발생합니다.
이는 개발자가 미리 예측하여 방지할 수 있기 때문에 상황에 맞는 예외 처리
(Exception Handling)를 해야합니다.

예외 클래스의 상속 계층도

자바에서는 예외가 발생하면 예외 클래스부터 객체를 생성하며
해당 인스턴스를 통해 예외처리를 합니다.
자바의 모든 에러와 예외 클래스는 Throwable 클래스로부터 확장되며
모든 예외의 상위 클래스는 Exception 클래스 입니다.
그리고 Exception 클래스 안에는 Runtime(실행 예외), Other(일반 예외)로 나뉩니다.

그림을 좀 더 확장해보면
OtherException 클래스는 컴파일 에러 시 다루는 하위 클래스로
사용자의 실수와 같은 외적인 요인에 의해 발생하는 컴피일 시 발생하는 예외입니다.
ex. 존재하지 않는 파일의 이름 입력 (FileNotFoundException),
실수로 클래스의 이름을 잘못 기재(ClassNotFoundException),
입력한 데이터 형식이 잘못된 경우 (DataFormatException)

RuntimeException는 프로그래머의 실수로 발생하는 예외가 담긴 클래스로
ex. 배열의 범위를 벗어남 (IndexOutOfBoundsException)
값이 null인 참조 변수의 멤버를 호출 (NullPointerException)
클래스 간의 형 변환을 잘못함 (ClassCastException)
정수를 0으로 나누는 산술 오류 (ArithmeticException)


Checked Exception / Unchecked Exception

자바의 예외는 컴파일, 런타임으로 구분된다는 것은 위를 보면 알 수 있습니다.
그런데 또 다른 Checked, Unchecked의 코드적 관점에서 구분할 수 있는데
가장 핵심적인 차이는 반드시 예외 처리를 해야 하는가? 에 있습니다.
쉽게 이해하면 Checked는 컴파일 예외 클래스로
Unchecked는 런타임 예외 클래스가 되고
이유는 Checked 예외를 체크하는 시점이 컴파일 단계이고
해결하지 않으면 프로그램이 실행되지 않기 때문입니다.

따라서 Checked Exception 이 발생할 가능성이 있는 메소드라면
try ~ catch로 감싸거나 throws를 던져서 처리해야 합니다.


예외 처리 (Exception Handling)

예외는 개발자가 구현한 로직에서 발생한 실수나 사용자의 영향에 의해 발생합니다.
이는 개발자가 미리 예측하여 방지할 수 있다고 했습니다.
그래서 예외 처리는 프로그램 실행 시 발생할 수 있는 예기치 못한 예외 발생을 대비하기 위한 코드를 작성하는 것이 됩니다.

목적에는 비정상적인 동작이나 에러를 잡아 복구를 시도하거나 회피하는 식의 처리를 통해 프로그래밍이 정상적인 유지를 할 수 있도록 하는 것에 있습니다.

Java의 예외 처리문

Java의 예외처리 문은 대표적으로 try~catch 문, try~catch~finally 문 등이 있으며
예외 발생 시 적절한 조치를 하도록 돕습니다.

try~catch 문

자바의 가장 기본적인 예외 처리 구문이며
try 안에는 예외가 발생할 가능성이 있는 코드를 이 블록 안에 작성하며
catch 안에는 try 블록에서 특정 예외가 발생했을 때 실행할 코드를 작성합니다.
그리고 인자에 어떤 종류의 예외를 처리할지 명시할 수 있습니다.

public static void main(String[] args){
    try {
        // ArithmeticException 발생지점
        int result = 10 / 0;
    } catch(ArithmeticException e) {
        // ArithmeticException 이 발생했을 때 실행될 코드
        System.out.println("ArithmeticException 예외가 발생했습니다.");
    }
}

try~catch~finally 문

try~catch 구문에 finally 블록이 추가된 형태이며
finallytry 블록의 예외 발생 여부와 상관없이 항상 실행되는 코드 블록입니다.
주로 자원 해제(파일 닫기, 네트워크 연결 종료)와 같이 반드시 실행되어야 하는
코드를 작성할 때 사용합니다.

public static void main(String[] args){
    try {
        System.out.println("자원을 엽니다.");
    } catch(Exception e) {
        System.out.println("예외가 발생했습니다.");
    } finally {
        System.out.println("자원을 닫습니다.");
    }
}

try~with~resources 문 (Java 7 이상)

AutoCloseable 인터페이스를 구현한 자원 (InputStream, Connection)을 사용할 때
finally 블록에서 close() 메서드를 직접 호출하지 않아도 try 블록이 끝나면
자동으로 해제해주는 편리한 구문입니다.

사용 시 코드가 더 간결해지고 자원 누수를 방지하기 좋습니다.

public static void main(String[] args){
    try (Scanner scanner = new Scanner(System.in)) {
        String input = scanner.nextLine();
        System.out.println(input);
    } catch (Exception e) {
        System.out.println("예외 처리" + e.getMessage());
    }
}

개발자가 직접 예외를 발생시키는 방법

위에 구문들은 모두 자바 언어의 컴파일 단계에서 오류가 생길 때 던지는
Exception의 예제였습니다.
예를 들어 사용자의 나이가 19살 이하였을 때 예외를 발생하는 코드는 어떻게 작성할까요?
이때는 개발자가 직접 예외를 발생시켜야 합니다.

public void checkAge(int age) {
    if (age < 19) {
        throw new IllegalArgumentException("미성년자는 접근할 수 없습니다.");
    }
}

마무리하며

예외 처리는 또 다른 형태의 코드 설계입니다.
버그를 수정하는 행위를 넘어 시스템의 안정성과 신뢰성을 높이는 중요한 설계 과정입니다.
잘 고려된 예외 처리 전략은 예측 불가능한 오류로부터 프로그램을 사전에 보호하니
이를 잘 고려해서 프로그램을 설계해야 합니다.

profile
달을 향해 쏴라, 빗나가도 별이 될 테니 👊

0개의 댓글