자바 예외 처리

smj_716·2025년 2월 5일

Java-study / live-study

목록 보기
9/16

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

🖥️ try, catch, finally

  • try: 예외가 발생할 수 있는 코드 감싸는 블록
  • catch: try 블록에서 예외가 발생했을 때 실행되는 블록
  • finally: 예외 발생 여부와 상관없이 항상 실행되는 블록으로, 주로 자원 해제에 사용
public class ExceptionHandlingExample {
    public static void main(String[] args) {
        try {
            int result = divide(10, 0);
            System.out.println("Result: " + result);
        } catch (ArithmeticException e) {
            System.out.println("예외 발생: " + e.getMessage());
        } finally {
            System.out.println("프로그램 종료");
        }
    }

    public static int divide(int a, int b) throws ArithmeticException {
        if (b == 0) {
            throw new ArithmeticException("0으로 나눌 수 없습니다.");
        }
        return a / b;
    }
}

위 코드에서 divide 메서드는 두 수를 나누는 기능을 한다. 만약 두 번째 인자가 0이라면 ArithmeticException을 발생시키고, 이를 main 메서드에서 try-catch 블록으로 처리한다. finally 블록은 예외 발생 여부와 상관없이 항상 실행되어 "프로그램 종료"를 출력한다.

🖥️ throw
throw: 프로그래머가 의도적으로 예외를 발생시킬 때 사용

public class ThrowExample {
    public static void checkAge(int age) {
        if (age < 18) {
            throw new IllegalArgumentException("나이가 18세 이상이어야 합니다.");
        }
        System.out.println("성인입니다.");
    }

    public static void main(String[] args) {
        checkAge(15); // 예외 발생
    }
}

checkAge(15);를 호출하면 IllegalArgumentException이 발생한다.

🖥️ throws
메서드 선언부에 사용되어 해당 메서드가 특정 예외를 던질 수 있음을 명시

public class ThrowsExample {
    public static void riskyMethod() throws Exception {
        throw new Exception("예외 발생!");
    }

    public static void main(String[] args) {
        try {
            riskyMethod();
        } catch (Exception e) {
            System.out.println("예외 처리: " + e.getMessage());
        }
    }
}

riskyMethodthrows Exception을 선언하여 예외를 호출한 곳에서 처리하도록 한다. main 메서드에서는 try-catch로 예외를 처리한다.

🖥️ try-with-resources
Java 7에서 들어온 기능으로 AutoCloseable 인터페이스를 구현한 클래스에서 자동으로 자원을 해제하도록 도와준다. 대표적으로 BufferedReader, FileReader, InputStream 등이 해당된다.

// Java 7 이후 try-with-resources
static String readFirstLineFromFile(String path) throws IOException {
    try (BufferedReader br =
                   new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
}

// Java 7 이전
static String readFirstLineFromFileWithFinallyBlock(String path)
                                                     throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(path));
    try {
        return br.readLine();
    } finally {
        if (br != null) br.close();
    }
}

try 블록이 종료되면 BufferedReader가 자동으로 닫힌다. 기존의 finally 블록 대신에 resource(java.lang.AutoClosable 이나 java.io.Closable을 구현한 오브젝트)를 자동으로 반환하여close()가 자동으로 호출된다.


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

자바의 예외 계층 구조는 java.lang.Throwable 클래스를 최상위 클래스로 하며, 이는 두 가지 주요 하위 클래스를 가진다 : Exception / Error

Throwable 클래스란?

오류와 예외 모두 자바의 최상위 클래스인 Object를 상속받는다. 그리고 그 사이에는 Throwable 클래스와 상속관계가 있는데, Throwable 클래스의 역할은 오류나 예외에 대한 메시지를 담는 것이다.
대표적으로 getMessage()printStackTrace() 메서드가 바로 이 클래스에 속해 있다. 당연히 Throwable을 상속받은 Error와 Exception 클래스에서도 위 두 메서드를 사용할 수 있게 된다.

위의 예외 클래스 계층 구조를 더 간단히 표현하면 아래와 같다.
자바에서 다루는 모든 예외 오류는 Exception 클래스에서 처리한다. 그리고 아래의 Exception 클래스 트리 구조를 보면 파랑색과 붉은색으로 색깔별로 구분됨을 볼 수 있는데, 이것이 컴파일 에러런타임 에러를 따로 클래스로 구분했기 때문이다.


3. Exception과 Error의 차이

📢 1) Error

시스템 레벨에서 발생하는 심각한 오류로, 주로 JVM의 문제나 하드웨어 한계로 인해 발생한다. 개발자가 이를 처리하여 복구하기 어렵기 때문에 애플리케이션에서 처리하지 않는 것이 일반적이다.
ex) OutOfMemoryError, StackOverflowError

📢 2) Exception

프로그램에서 발생할 수 있는 예외 상황을 나타내며, 개발자가 이를 처리하여 프로그램의 정상적인 흐름을 유지할 수 있다. 아래와 같이 두가지로 나뉜다.

Checked Exception(컴파일 에러)

  • 컴파일 타임에 체크되고 반드시 예외 처리를 해야한다. 만약 예외처리를 하지 않는다면 컴파일 자체가 되지 않는다.
  • 따라서 Checked Exception이 발생할 가능성이 있는 메소드라면 반드시 로직을 try - catch로 감싸거나 throws로 던져서 처리해야 한다. 
  • 주로 외부 자원 접근 시 발생할 수 있는 예외를 처리하는데 사용한다.
  • 파일 입출력, 네트워크 통신 등의 작업에서 발생할 수 있는 예외를 처리한다.
    ex) IOException, SQLException, FileNotFoundException

Unchecked Exception(런타임 에러)

  • 런타임에 발생하고 예외 처리를 강제하지 않는다.
  • 개발자의 충분한 주의로 미리 회피할 수 있는 경우가 대부분이라 상대적으로 미약한 예외로 처리되어, 자바 컴파일러는 별도의 예외 처리를 하지 않도록 설계 되어 있기 때문이다.
  • 주로 프로그래밍 오류로 인해 발생하는 예외를 처리한다.
  • null참조, 배열 인덱스 초과 등의 오류를 처리한다.
    ex) NullPointerException, ArrayIndexOutOfBoundsException, IllegalArgumentException, SystemException

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

위에서 다룬 내용이며, 요약하자면 아래와 같다.

구분RuntimeException (Unchecked Exception)Checked Exception
컴파일 시 검사 여부❌ 컴파일러가 예외 처리를 강제하지 않음✅ 컴파일러가 예외 처리를 강제함
예외 처리 필요 여부예외 처리를 강제하지 않아 try-catch 없이도 컴파일 가능반드시 try-catch 또는 throws를 사용해야 함
발생 시점실행(Runtime) 중에 주로 발생컴파일 타임에 예외 가능성을 체크함
원인주로 프로그래머의 실수로 발생 (예: NullPointerException)외부 환경(파일, 네트워크, DB 등)과 관련된 예외
처리 방식프로그램 실행 중 예외 발생 시 종료될 수도 있음반드시 예외 처리를 통해 정상적인 흐름을 유지해야 함
예제 코드public void divide(int a, int b) { int result = a / b; } (0으로 나누면 ArithmeticException 발생)public void readFile() throws IOException { FileReader file = new FileReader("test.txt"); }
  • RuntimeException (Unchecked Exception) : 프로그래머의 실수로 발생하는 예외로, 컴파일러가 예외 처리 여부를 검사하지 않는다.
  • Checked Exception : 외부 환경에 의해 발생할 수 있는 예외로, 컴파일러가 예외 처리 여부를 검사한다.

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

자바에서는 사용자 정의 예외를 만들어 특정 상황에 대한 예외 처리를 세분화할 수 있다. 이를 위해 Exception 클래스를 상속하여 새로운 예외 클래스를 정의한다.

// 사용자 정의 예외 클래스
public class InvalidAgeException extends Exception {
    public InvalidAgeException(String message) {
        super(message);
    }
}

// 예외를 사용하는 클래스
public class CustomExceptionExample {
    public static void main(String::contentReference[oaicite:0]{index=0}

0개의 댓글