Backend/Java

[Effective Java : Item 77] 예외를 무시하지 말라

김세진 2024. 4. 1. 14:12
반응형

 

 

 

 

개요

 

검사 예외 및 비검사 예외에 동일하게 적용되는 원칙이다. 아주 자명한 사실이지만, 사람들이 자주 어기고 있는 원칙 중 하나라고 한다. API 설계자가 메서드 선언에 예외를 명시하는 이유는, 그 메서드를 사용할 때 발생할 수 있는 문제에 대해 적절한 조치를 취해달라고 말하는 것이다. 다음의 코드와 같이 예외를 무시하는 방법은 아주 간단하다. try-catch 문으로 코드를 묶고, catch에 아무런 조치를 하지 않으면 된다.

 

try {
    ...
} catch (SomeException e) {
}

 

문제 상황에 잘 대처하기 위해 예외가 존재하는데, 위처럼 catch 블록을 비워두면 예외가 존재할 이유가 없어진다. 

 

 

예외를 무시해도 되는 경우

 

예외를 무시해도 괜찮을 경우도 있다. 예를 들어, FileInputStream을 사용한 후, close() 메서드를 호출하여 스트림을 닫을 때 발생할 수 있는 예외가 그렇다. 그 이유는 다음과 같다.

 

1. 입력 전용 스트림이므로 파일의 상태를 변경하지 않는다.

2. 파일의 상태를 변경하지 않았으므로 복구할 것이 없다.

3. close()를 시도했다는 것은 필요한 정보를 이미 다 읽었다는 뜻이므로 남은 작업을 중단할 이유도 없다.

 

혹여나 동일한 예외가 자주 발생한다면 로그로 남기는 것도 좋다.

 

위와 같이 마땅한 이유로 다음 코드와 같이 예외를 무시하기로 했다면 catch 블록 안에 그렇게 결정한 이유를 주석으로 남기고, 예외 변수명을 ignored로 명명하자.

 

FileInputStream fis = null;
try {
    fis = new FileInputStream("example.txt");
} catch (FileNotFoundException e) {
    // ... 처리 로직
} finally {
    if (fis != null) {
        try {
            fis.close();
        } catch (IOException ignored) {
            // 입력 전용 스트림이기 때문에 close 예외 무시
        }
    }
}

 

입출력 관련하여 더 적절한 예로 자바 7부터 도입된 try-with-resources 절을 사용한다면 위처럼 close를 직접 하지 않아도 try 절이 끝날 경우 자동으로 close된다. close시 발생하는 예외는 버려지지 않고 '숨겨졌다(suppressed)' 는 꼬리표를 달고 스택 추적 내역에 출력된다.

 

try (FileInputStream fis = new FileInputStream("example.txt")) {
} catch (IOException e) {
    // ... 처리 로직
}

 

 

정리

 

1. 예외를 무시할 경우 그 프로그램은 오류를 내재한 채 동작하게 된다. 그러다 오류와 아무 상관없는 곳에서 동작을 멈출 수 있게 된다.

2. 예외는 항상 적절히 처리하도록 하되, 무시해도 될 이유가 명확하다면 처리 후 주석을 달도록 하자.

3. 무시하지 않고 바깥으로 전파되게만 놔둬도 최소한 디버깅 정보를 남길 수 있다.

 

 

 

반응형