CodeGym /행동 /JAVA 25 SELF /복잡한 예외 처리와 모범 사례

복잡한 예외 처리와 모범 사례

JAVA 25 SELF
레벨 24 , 레슨 3
사용 가능

1. 다중 catch: 서로 다른 예외 처리

실제 프로그램에서는 동일한 코드 블록이 여러 타입의 예외를 던질 수 있습니다. 예를 들어, 파일을 읽을 때는 FileNotFoundException이나 IOException이 발생할 수 있고, 데이터 파싱 시에는 NumberFormatException까지 발생할 수 있습니다. 각 상황을 올바르게 처리하려면 Java에서는 여러 개의 catch 블록을 연달아 사용할 수 있습니다.

문법

try {
    // 위험한 작업
} catch (FileNotFoundException e) {
    System.out.println("파일을 찾을 수 없음: " + e.getMessage());
} catch (IOException e) {
    System.out.println("입출력 오류: " + e.getMessage());
} catch (NumberFormatException e) {
    System.out.println("잘못된 숫자 형식: " + e.getMessage());
}

중요 포인트:
catch 블록은 더 구체적인 것에서 더 일반적인 것으로 배치해야 합니다! 처음에 catch (Exception e)를 작성하면 나머지 블록은 도달 불가능해지고 컴파일 오류가 발생합니다.

왜 중요할까요?

  • 구체적인 처리: 오류에 따라 다르게 반응할 수 있습니다(예: 다른 파일을 선택하도록 안내하거나 입력을 다시 받기).
  • 가독성: 어떤 오류를 예상하고 어떻게 처리하는지 한눈에 보입니다.

2. 여러 타입을 한 번에 잡는 catch (multi-catch)

때로는 서로 다른 예외에 대해 동일한 처리가 필요합니다. 예를 들어, 파일 읽기 오류든 숫자 변환 오류든 상관없이 오류 메시지를 출력하거나 로깅만 하고 싶을 수 있습니다.

Java 7부터 multi-catch 문법이 도입되어 하나의 블록에서 여러 예외 타입을 합쳐 처리할 수 있습니다:

try {
    // 위험한 작업
} catch (IOException | NumberFormatException e) {
    System.out.println("파일 또는 숫자 처리 중 오류: " + e.getMessage());
}

작동 방식:

  • 세로 막대(|)로 예외 타입을 나열합니다.
  • 변수 e의 정적 타입은 가장 공통된 상위 클래스(보통 Exception)입니다.
  • 블록 안에서 변수 e에 새 값을 할당할 수 없습니다 — 암묵적으로 final로 간주됩니다.

예시:

try {
    BufferedReader reader = new BufferedReader(new FileReader("numbers.txt"));
    String line = reader.readLine();
    int number = Integer.parseInt(line);
    System.out.println("숫자: " + number);
    reader.close();
} catch (IOException | NumberFormatException e) {
    System.out.println("오류: " + e.getMessage());
}

3. 예외 처리 모범 사례

예외를 억누르지 마세요

나쁨:

try {
    // 위험한 작업
} catch (Exception e) {
    // 아무 것도 하지 않음!
}

왜 나쁠까요?
비어 있는 catch 블록은 오류를 “묵살”하여 장애의 원인 정보를 잃게 만들고, 프로그램을 디버깅하기 어렵게 합니다.

더 나은 방법: 최소한 메시지를 출력하거나 오류를 로깅하세요.

catch (Exception e) {
    e.printStackTrace();
}

예외를 처리할 수 없다면 — 상위로 전파하세요:

catch (IOException e) {
    throw e; // 또는 throw new RuntimeException(e);
}

가장 구체적인 예외를 던지세요

직접 메서드나 API를 작성할 때는 Exception이나 RuntimeException처럼 포괄적인 타입보다 최대한 구체적인 예외를 던지세요. 그러면 코드와 인터페이스가 다른 개발자에게 더 명확해집니다.

예시:

public void withdraw(double amount) throws InsufficientFundsException {
    if (amount > balance) {
        throw new InsufficientFundsException("잔액이 부족합니다");
    }
    // ...
}

프로그램 흐름 제어에 예외를 사용하지 마세요

예외는 예외적인 상황—즉, 정상적인 실행 경로에서 발생하지 않아야 하는 오류—을 처리하기 위한 것입니다. 예외를 일반적인 로직(예: 루프 탈출이나 조건 검사)에 사용하지 마세요.

나쁨:

try {
    while (true) {
        String line = reader.readLine();
        if (line == null) break;
        // 한 줄 처리
    }
} catch (Exception e) {
    // 예외를 루프 종료 용도로 사용 — 나쁨!
}

좋음:

String line;
while ((line = reader.readLine()) != null) {
    // 한 줄 처리
}

4. 실전 예제

예: 서로 다른 오류를 다르게 처리하기

try {
    BufferedReader reader = new BufferedReader(new FileReader("data.txt"));
    String line = reader.readLine();
    int number = Integer.parseInt(line);
    System.out.println("숫자: " + number);
    reader.close();
} catch (FileNotFoundException e) {
    System.out.println("파일을 찾을 수 없습니다!");
} catch (IOException e) {
    System.out.println("파일 읽기 오류!");
} catch (NumberFormatException e) {
    System.out.println("파일 내용이 숫자가 아닙니다!");
}

예: 동일한 처리를 위한 multi-catch

try {
    // 위험한 작업
} catch (IOException | NumberFormatException e) {
    System.out.println("오류: " + e.getMessage());
}

5. 중요한 포인트와 흔한 실수

오류 №1: catch 블록의 순서가 잘못됨. 먼저 더 구체적인 예외, 다음으로 일반적인 예외가 와야 합니다. 그렇지 않으면 넓은 블록까지 실행 흐름이 결코 도달하지 않습니다.

오류 №2: 상하위(관련) 타입을 multi-catch에 함께 사용. 예를 들어, catch (IOException | Exception e)는 컴파일되지 않습니다. IOExceptionException의 하위 클래스이기 때문입니다.

오류 №3: multi-catch에서 변수 e를 변경하려고 함. 이 경우 efinal로 간주되므로 새 값을 할당할 수 없습니다.

오류 №4: 비어 있는 catch 블록. 오류를 무시하면 “조용한” 버그로 이어집니다. 최소한 메시지를 출력하거나 예외를 로깅하세요.

오류 №5: 모든 Exception을 한꺼번에 잡기. catch (Exception e) 사용은 실제 문제를 가려 디버깅을 어렵게 만듭니다. 예상되는 예외만 잡는 것이 좋습니다.

1
과제
JAVA 25 SELF, 레벨 24, 레슨 3
잠금
재무 보고서: 데이터 문제의 정확한 진단
재무 보고서: 데이터 문제의 정확한 진단
1
과제
JAVA 25 SELF, 레벨 24, 레슨 3
잠금
게임 설정: 로드 실패에 대한 일관된 처리
게임 설정: 로드 실패에 대한 일관된 처리
1
과제
JAVA 25 SELF, 레벨 24, 레슨 3
잠금
비밀 아카이브: 기밀 문서 접근 우선순위
비밀 아카이브: 기밀 문서 접근 우선순위
1
과제
JAVA 25 SELF, 레벨 24, 레슨 3
잠금
로깅 서비스: 어떤 오류도 놓쳐서는 안 됩니다!
로깅 서비스: 어떤 오류도 놓쳐서는 안 됩니다!
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION