Java 예외 처리: 계층 구조, 분류 및 사용자 정의 예외

프로그램 실행 중 정상적인 흐름을 방해하는 비정상적인 상황을 예외(Exception)라고 합니다. 예외 처리는 견고한 Java 애플리케이션을 개발하는 데 필수적인 요소입니다.

Java 예외 클래스 구조

Java의 예외 계층 구조는 최상위 클래스인 Throwable을 기반으로 하며, 두 가지 주요 하위 클래스로 나뉩니다:

  • Error: OutOfMemoryError와 같이 컴파일 타임 및 시스템 오류를 나타내며, 일반적으로 복구가 불가능합니다.
  • Exception: 프로그램 실행 중에 포착 및 처리할 수 있는 예외를 나타냅니다.

Error와 Exception의 차이

  • Error: StackOverflowError처럼 JVM이 처리할 수 없는 심각한 문제를 나타냅니다. 개발자가 직접 처리할 수 없습니다.
  • Exception: 프로그램 자체에서 처리 가능한 예외 상황으로, try-catch 문을 사용하여 포착하고 처리해야 합니다.

Exception 분류

Exception은 다시 두 가지 유형으로 구분됩니다:

  • RuntimeException (런타임 예외): NullPointerException, IndexOutOfBoundsException 등이 여기에 속하며, 명시적으로 포착하거나 선언할 필요가 없습니다.
  • Checked Exception (확인된 예외): IOException, SQLException 등이 있으며, 반드시 포착하거나 메서드 시그니처에 throws 키워드로 선언해야 합니다.

예외 처리 메커니즘

예외 발생시키기

throw 키워드를 사용하여 코드 내에서 직접 예외를 발생시킵니다.

throw new IllegalArgumentException("잘못된 인수입니다.");

throw와 throws의 사용법

  • throw: 메서드 내에서 예외 객체를 직접 던질 때 사용합니다.
  • throws: 메서드 시그니처에서 해당 메서드가 발생시킬 수 있는 예외 유형을 선언할 때 사용합니다.
public void loadFile() throws IOException {
    // IOException을 발생시킬 수 있는 코드
}

예외 포착하기

try-catch 블록을 사용하여 예외를 포착하고 처리합니다.

try {
    // 예외가 발생할 수 있는 코드
} catch (FileNotFoundException e) {
    // 예외 처리 로직
    System.err.println("파일을 찾을 수 없습니다: " + e.getMessage());
}

여러 예외 처리 순서

다중 catch 블록을 사용할 경우, JVM은 선언된 순서대로 예외 타입을 검사하여 일치하는 첫 번째 블록을 실행합니다. 따라서 구체적인 예외부터 먼저 처리해야 합니다.

예외 전파 (Exception Propagation)

예외가 메서드 내에서 처리되지 않으면 호출 스택을 따라 상위 메서드로 전파됩니다. 적절히 처리되지 않으면 최종적으로 JVM까지 도달하여 프로그램이 종료됩니다.

사용자 정의 예외 (Custom Exception)

애플리케이션 특화 예외를 만들려면 다음 두 가지 방법을 사용합니다:

  1. Exception 클래스를 상속받아 Checked Exception 생성
  2. RuntimeException 클래스를 상속받아 Unchecked Exception 생성
// Checked Exception
public class InvalidUserInputException extends Exception {
    public InvalidUserInputException(String message) {
        super(message);
    }
}

// Unchecked Exception
public class ProcessingFailureException extends RuntimeException {
    public ProcessingFailureException(String message) {
        super(message);
    }
}

사용자 정의 예외를 활용하면 코드 가독성이 향상되고, 호출자가 특정 오류 상황에 맞춰 정확한 처리를 할 수 있습니다.

실습 예제

public class CustomExceptionExample {
    public static void main(String[] args) {
        try {
            validateAge(-5);
        } catch (InvalidUserInputException e) {
            System.out.println("사용자 입력 오류 발생: " + e.getMessage());
        }
    }

    public static void validateAge(int age) throws InvalidUserInputException {
        if (age < 0) {
            throw new InvalidUserInputException("나이는 음수일 수 없습니다. 입력값: " + age);
        }
        System.out.println("유효한 나이: " + age);
    }
}

태그: Java 예외 처리 Throwable Exception Error RuntimeException

7월 23일 10:46에 게시됨