Java

[Effective Java] 아이템 71 : 필요 없는 검사 예외 사용은 피하라

jwKim96 2023. 3. 26. 15:01

0. 들어가며

저를 포함한 많은 자바 개발자들은 Checked Exception이 try-catch 구문이나 throw 를 강제하기 때문에 좋아하지 않는데요.

그래서 요즘은 거의 Checked Exception은 사용하지 않고, 불가피하게 사용하게 되는경우는 RuntimeException으로 변환해서 다루는 경우도 많은 것 같습니다.

게다가 Checked Exception을 던지는 메서드는 Stream에서 직접 사용할 수 없어서 더욱 기피하게되는데요.

하지만 이런 Checked Exception도 제대로 활용한다면 API와 프로그램의 질을 올릴 수 있다고 합니다.

1. 제대로 활용할 수 있는 경우

Checked Exception을 제대로 활용할 수 있는 경우는 다음과 같습니다.

  • 외부에서 API를 정상적으로 호출해도 발생할 수 있는 경우
    • 제어할 수 없는 상황에서 오류가 발생할 수 있는 경우
  • 개발자가 의미있는 조치를 취할 수 있는 경우
public void printFile(String filePath) {
    File file = new File(filePath);

    try (FileReader fr = new FileReader(file))
    {
        int content;
        while ((content = fr.read()) != -1) {
            System.out.print((char) content);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

printFile("Effective-java.txt");

위 예시는 텍스트를 읽어와 출력하는 메서드인데요.

프로그램 로직상으로는 아무런 문제가 없지만, 제어할 수 없는 상황(파일시스템)에 의해 예외가 발생합니다.

이런 경우에는 Checked Exception이 유용하게 사용될 수 있습니다.

그리고 예외가 발생한 경우 개발자가 의미있게 조치를 취할수도 있는데요.

public void printFile(String filePath) throw IOException {
    File file = new File(filePath);
    FileReader fr = new FileReader(file);
    int content;
    while ((content = fr.read()) != -1) {
        System.out.print((char) content);
    } 
}

try
{
    printFile("Effective-java.txt");
} catch (IOException e) {
    System.out.print("해당 파일을 찾을 수 없습니다");
}

위와 같은 경우 예외가 발생하면, 다른 흐름으로 유도하도록 Checked Exception을 활용할 수 있습니다.

2. 사용을 피해야 하는 경우

위에서 설명한 상황이 아니라면 왠만하면 피하는게 좋습니다.

무언가 반환해야하는 상황이라면 Optional을 이용하는것이 좋습니다.

public Result getSomething() throw IOException {
    // select query
    if (result == null) {
        return Optional.empty();
    }

    return Optional.of(result);
}

Result result = getSomething().orElseThrow(() -> new RuntimeException());

위 처럼 예외가 호출하는쪽에 충분한 정보를 제공할 수 있다면, Optional을 사용하는게 좋습니다.

왜냐하면 1번에서 잠시 본 것 처럼, Checked Exception을 사용하면 호출하는쪽에서 처리하는것이 번거로울 수 있기 때문입니다.

그런데 만약 정상적인 흐름으로 갈 수 없고, 여기서 중단되어야 한다면 다음과 같이 Unchecked Exception을 던지는 것을 고려하는게 더 좋습니다.

public void printFile(String filePath) {
    File file = new File(filePath);

    try (FileReader fr = new FileReader(file)) {
        int content;
        while ((content = fr.read()) != -1) {
            System.out.print((char) content);
        }
    } catch (IOException e) {
        throw new RuntimeException(e)
    }
}

printFile("Effective-java.txt");