📚 학습 기록/Java 기초 & 중급

[25.02.25][Java] 예외 처리 (Exception Handling) - 예외 계층, 체크 예외 vs 언체크 예외

zenjoydev 2025. 2. 25. 18:07

💡 오늘은 예외 처리에 대해 정리해보겠습니다.
자바에서 예외 처리는 안정적인 프로그램 실행을 위해 필수적인 개념입니다.
특히, 체크 예외 vs 언체크 예외, throw와 throws의 차이, 그리고 try-catch-finally를 어떻게 활용하는지에 대해 집중적으로 다룹니다.


📌 예외(Exception)란?

프로그래밍에서 예외란 실행 중 발생하는 예상치 못한 오류를 의미합니다.
예를 들어, 0으로 나누는 경우(ArithmeticException), null 값을 참조하는 경우(NullPointerException) 등이 있습니다.

자바의 예외 계층 구조는 다음과 같이 구성됩니다.

Object  
 └── Throwable  
      ├── Exception  
      │    ├── IOException  
      │    ├── SQLException  
      │    └── RuntimeException  
      │         ├── NullPointerException  
      │         ├── IllegalArgumentException  
      │         └── ArithmeticException  
      └── Error  
           ├── OutOfMemoryError  
           └── StackOverflowError

📌 예외 처리의 필요성

예외 처리는 단순한 에러 방지가 아니라 안정적인 프로그램 운영을 위한 필수 요소입니다.

1️⃣ 서버와의 연결, 데이터 전송, 자원 해제

  • 예외 발생 시 반드시 자원을 해제해야 합니다.
  • 그렇지 않으면 **메모리 누수(memory leak)**가 발생하고, 결국 서버가 멈추는 심각한 상황이 올 수 있습니다.

2️⃣ 예외 처리가 더 복잡한 이유

  • 정상 흐름보다 예외 흐름이 훨씬 더 복잡합니다.
  • 예외가 발생한 경우 이후 코드 실행을 중단할지, 특정 작업을 수행할지 결정해야 합니다.

3️⃣ 정상 코드 흐름과 예외 흐름 분리

  • try-catch 블록을 활용하여 정상 코드와 예외 처리 코드를 분리하면 가독성이 높아집니다.

📌 체크 예외(Checked Exception) vs 언체크 예외(Unchecked Exception)

구분체크 예외(Checked Exception)언체크 예외(Unchecked Exception)

예외 종류 Exception (RuntimeException 제외) RuntimeException 및 그 하위 클래스
컴파일 시점 체크 여부 O (컴파일러가 확인) X (컴파일러가 확인하지 않음)
throws 필수 여부 필수 (throws 없으면 컴파일 오류 발생) 선택 (생략 가능)
예시 IOException, SQLException NullPointerException, ArithmeticException
주요 사용처 파일, DB, 네트워크 연결 등 외부 자원 사용 프로그래밍 오류 (로직 실수 등)

✅ 체크 예외(Checked Exception)

  • 반드시 예외 처리를 해야 합니다.
  • 파일 입출력, 네트워크, 데이터베이스 연결과 같은 외부 리소스 사용 시 주로 발생합니다.
  • try-catch 또는 throws로 예외 처리를 선언해야 합니다.
  • 예제 코드
public void readFile(String filePath) throws IOException {
    FileReader file = new FileReader(filePath);
    BufferedReader reader = new BufferedReader(file);
    System.out.println(reader.readLine());
    reader.close();
}

→ IOException은 체크 예외이므로 반드시 throws를 선언해야 합니다.


✅ 언체크 예외(Unchecked Exception)

  • 예외 처리를 강제하지 않으며, 발생하면 자동으로 throw됩니다.
  • 주로 프로그래밍 오류(로직 실수)로 인해 발생하는 경우가 많습니다.
  • 대표적인 예: NullPointerException, IndexOutOfBoundsException
  • 예제 코드
     
public void divide(int a, int b) {
    int result = a / b;  // b가 0이면 ArithmeticException 발생
    System.out.println(result);
}

→ ArithmeticException은 RuntimeException의 하위 클래스이므로, throws 선언 없이 자동으로 예외가 발생합니다.


📌 throw vs throws 차이점

구분throwthrows

기능 예외 발생 예외 선언
위치 메서드 내부 메서드 시그니처
예시 throw new Exception(); void method() throws Exception
주요 사용처 특정 조건에서 예외 강제 발생 예외를 호출한 곳에서 처리하도록 위임

예제 코드

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

→ throw는 특정 조건에서 예외를 발생시키는 데 사용됩니다.

 

📌 try-catch-finally 예외 처리 방법

예외 처리를 위해 try, catch, finally 블록을 사용할 수 있습니다.

java
복사편집
try { // 예외 발생 가능 코드 } catch (ExceptionType e) { // 예외 처리 코드 } finally { // 항상 실행되는 코드 (자원 해제 등) }

✅ finally의 역할

  • 예외 발생 여부와 관계없이 항상 실행됩니다.
  • 주로 파일, 네트워크, 데이터베이스 연결을 해제할 때 사용됩니다.
  • 예제 코드
     
try {
    // 예외 발생 가능 코드
} catch (ExceptionType e) {
    // 예외 처리 코드
} finally {
    // 항상 실행되는 코드 (자원 해제 등)
}

✅ finally의 역할

  • 예외 발생 여부와 관계없이 항상 실행됩니다.
  • 주로 파일, 네트워크, 데이터베이스 연결을 해제할 때 사용됩니다.
public void readFile(String filePath) {
    FileReader file = null;
    try {
        file = new FileReader(filePath);
        System.out.println("파일을 읽습니다.");
    } catch (IOException e) {
        System.out.println("파일을 읽는 중 오류 발생: " + e.getMessage());
    } finally {
        if (file != null) {
            try {
                file.close();
            } catch (IOException e) {
                System.out.println("파일 닫기 오류 발생");
            }
        }
    }
}

📌 결론

1️⃣ 체크 예외는 반드시 예외 처리를 해야 하며, 언체크 예외는 선택 가능하다.
2️⃣ 예외 처리를 하지 않으면, 예외가 발생한 시점에서 프로그램이 종료될 수 있다.
3️⃣ throw는 예외를 발생시키는 것이고, throws는 예외를 호출한 곳으로 넘기는 것이다.
4️⃣ 예외 발생 여부와 관계없이 finally 블록은 항상 실행된다.


이제 예외 처리를 이해하고 실무에서 적용할 수 있도록 연습해보세요! 💪
더 궁금한 점이 있다면 댓글 남겨주세요. 😃