JAVA/JAVA 기초

Java 예외(Exception) 처리

임베디드 친구 2024. 10. 10. 20:22
반응형

자바(Java)는 강력하고 유연한 프로그래밍 언어로, 다양한 애플리케이션과 시스템을 개발하는 데 널리 사용된다. 그러나 프로그래밍에서는 언제든지 예측할 수 없는 상황이 발생할 수 있으며, 이를 효과적으로 처리하지 않으면 프로그램의 안정성과 신뢰성이 저하될 수 있다. 자바에서는 이러한 상황에 대처하기 위해 예외(Exception)를 사용하며, 예외를 처리함으로써 프로그램이 예외적인 상황을 우아하게 관리하고 적절한 조치를 취할 수 있게 된다.

이 글에서는 자바의 예외 처리에 대해 체계적으로 알아보며, 예외의 종류, 처리 방법, 사용자 정의 예외, 그리고 예외 처리의 모범 사례를 다룰 것이다. 이를 통해 예외의 개념을 명확히 이해하고, 예외 상황을 안전하게 처리할 수 있는 방법을 익히게 될 것이다.

1. Exception이란?

예외(Exception)는 프로그램의 정상적인 흐름을 방해하는 예기치 못한 이벤트나 오류를 의미한다. 예외가 발생하면 프로그램의 실행이 중단되며, 적절한 예외 처리 코드가 없다면 프로그램은 비정상적으로 종료될 수 있다.

자바는 이러한 예외를 처리하고 관리하기 위해 Exception 클래스를 제공하며, 예외가 발생할 경우 개발자는 적절한 예외 처리 코드를 작성하여 프로그램이 예외적인 상황에서도 안정적으로 동작할 수 있도록 해야 한다.

예외 처리의 목적은 다음과 같다:

  • 프로그램이 예외적인 상황에서도 정상적으로 종료될 수 있도록 한다.
  • 사용자에게 친숙한 에러 메시지를 제공하여 문제의 원인을 이해하도록 돕는다.
  • 시스템 오류나 데이터 손상 등의 치명적인 문제를 예방한다.
  • 프로그램의 디버깅 및 유지보수를 쉽게 한다.

2. Exception의 종류

자바의 예외는 크게 Checked Exception(검사 예외), Unchecked Exception(비검사 예외), 그리고 Error(에러)로 나눌 수 있다. 이 세 가지는 예외 처리 방법 및 발생 시점에 따라 구분된다.

2.1. Checked Exception(검사 예외)

Checked Exception은 컴파일 시점에서 컴파일러에 의해 체크되는 예외이다. 이러한 예외는 개발자가 반드시 예외 처리 코드를 작성하거나 메서드에 throws 키워드를 사용하여 호출자에게 예외를 알리도록 강제한다. 만약 이러한 예외를 처리하지 않으면, 프로그램은 컴파일되지 않는다.

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class CheckedExceptionExample {
    public static void main(String[] args) {
        try {
            File file = new File("nonexistent_file.txt");
            FileInputStream fileInputStream = new FileInputStream(file);  // FileNotFoundException 발생 가능
        } catch (IOException e) {
            System.out.println("파일을 찾을 수 없습니다: " + e.getMessage());
        }
    }
}

2.2. Unchecked Exception(비검사 예외)

Unchecked Exception은 컴파일러가 체크하지 않는 예외로, 런타임 시 발생한다. 개발자가 예외를 명시적으로 처리하지 않아도 된다. 주로 프로그래머의 실수로 인해 발생하는 예외로, 잘못된 인덱스 접근이나 null 값 참조 시 발생한다.

public class UncheckedExceptionExample {
    public static void main(String[] args) {
        String text = null;
        System.out.println(text.length());  // NullPointerException 발생
    }
}

2.3. Error(에러)

Error는 자바 프로그램 외부 환경에서 발생하는 심각한 문제로, 개발자가 직접 처리하지 않는 것이 일반적이다. 예를 들어, 메모리가 부족할 때 발생하는 OutOfMemoryError는 개발자가 해결할 수 없는 문제이며, 시스템의 문제로 간주된다.

public class ErrorExample {
    public static void recursiveMethod() {
        recursiveMethod();  // 무한 재귀 호출로 StackOverflowError 발생
    }

    public static void main(String[] args) {
        recursiveMethod();
    }
}

3. Exception 처리 방법

자바에서는 try-catch-finally 블록을 사용하여 예외를 처리한다. try 블록 안에 예외가 발생할 수 있는 코드를 배치하고, catch 블록에서 해당 예외를 처리하며, finally 블록은 예외 발생 여부와 관계없이 항상 실행되는 코드를 작성한다.

3.1. try-catch 블록

try-catch 블록은 기본적인 예외 처리 방법으로, 예외가 발생하면 catch 블록이 실행되며, 예외에 따라 다른 대응을 할 수 있다.

try {
    int result = 10 / 0;  // ArithmeticException 발생
} catch (ArithmeticException e) {
    System.out.println("수학적 오류 발생: " + e.getMessage());
}

3.2. try-catch-finally 블록

finally 블록은 예외가 발생하든 그렇지 않든 항상 실행되어야 하는 코드를 작성하는 데 사용된다. 주로 리소스 해제나 정리 작업을 수행할 때 사용된다.

try {
    int[] numbers = {1, 2, 3};
    System.out.println(numbers[10]);  // ArrayIndexOutOfBoundsException 발생
} catch (ArrayIndexOutOfBoundsException e) {
    System.out.println("배열 인덱스 범위를 벗어났습니다.");
} finally {
    System.out.println("예외 발생 여부와 관계없이 실행됩니다.");
}

3.3. throws 키워드

메서드 선언부에 throws 키워드를 사용하여 해당 메서드에서 발생할 수 있는 예외를 호출자에게 전달할 수 있다. 이는 예외 처리를 메서드의 호출자에게 위임하는 것이다.

public void readFile(String fileName) throws FileNotFoundException {
    FileInputStream file = new FileInputStream(fileName);  // FileNotFoundException 발생 가능
}

4. 사용자 정의 Exception

자바에서는 필요에 따라 Exception 클래스를 상속받아 사용자 정의 예외를 만들 수 있다. 사용자 정의 예외는 특정 상황에서 발생할 수 있는 예외를 표현할 때 유용하며, 예외에 대한 추가 정보를 제공할 수 있다.

class CustomException extends Exception {
    public CustomException(String message) {
        super(message);
    }
}

public class CustomExceptionExample {
    public static void main(String[] args) {
        try {
            throw new CustomException("사용자 정의 예외 발생");
        } catch (CustomException e) {
            System.out.println("예외 처리: " + e.getMessage());
        }
    }
}

5. 예외 처리의 모범 사례

자바 예외 처리의 모범 사례를 통해 안정적이고 유지보수하기 쉬운 코드를 작성할 수 있다.

  1. 예외를 무시하지 말고 처리하라: 예외를 catch 블록에서 아무 작업 없이 무시하는 것은 좋은 습관이 아니다. 예외가 발생했을 때 최소한 로그를 남기거나 사용자에게 알림을 제공해야 한다.
try {
    // 예외 발생 가능한 코드
} catch (Exception e) {
    // 나쁜 예시: 예외를 무시함
}
  1. 구체적인 예외를 캐치하라: Exception 클래스는 모든 예외의 상위 클래스이지만, 가능한 한 구체적인 예외를 캐치하여 처리하라.
try {
    int result = 10 / 0;
} catch (ArithmeticException e) {
    System.out.println("수학적 오류 발생: " + e.getMessage());
}
  1. 적절한 예외 메시지를 제공하라: 예외 발생 시 적절한 메시지를 포함하여 문제를 명확하게 전달하라.
throw new IllegalArgumentException("숫자는 0보다 커야 합니다.");
  1. 자원(Resource)을 해제하라: 예외 발생 여부와 관계없이 파일, 네트워크 연결 등의 자원을 해제하기 위해 finally 블록을 사용하거나 try-with-resources를 사용하라.
try (FileInputStream file = new FileInputStream("input.txt")) {
    // 파일 처리
} catch (IOException e) {
    System.out.println("파일 처리 중 오류 발생: " + e.getMessage());
}
  1. 사용자 정의 예외를 사용하라: 특정 비즈니스 로직에 맞는 예외를 정의하여 예외 처리 로직을 명확하게 하라.

6. 결론

자바에서 예외 처리는 프로그램의 안정성과 신뢰성을 높이는 중요한 부분이다. 적절한 예외 처리를 통해 예측할 수 없는 상황에 대비하고, 사용자에게 친숙하고 안전한 애플리케이션을 제공할 수 있다. 예외 처리의 다양한 방법과 모범 사례를 학습하여 예외 상황에서도 프로그램이 안정적으로 동작하도록 만들어야 한다.

반응형