[JAVA] 예외

이재훈·2023년 8월 13일
0

JAVA8

목록 보기
20/22

자바의 정석 책을 읽었고 그 안에 예외에 대한 설명이 있었지만 그렇게 주의깊게 읽고 학습하지 않았습니다. 이번에는 예외에 대해 학습해보도록 하겠습니다.

자바와 객체지향

checked Exception vs Uncheked Exception

이것에 대해 자주 이야기하는 오답은 아래와 같습니다.

Checked Exception은 컴파일 할 때 발생하고, Unchecked Exception은 런타입에 발생하는 예외로 알고 있습니다.

하지만 이것은 옳은 대답이 아닙니다. 컴파일 시점에는 예외가 발생하지 않습니다. 컴파일 시점에 발생하는 문법적 오류에 대한 "에러"입니다.

다음과 같이 답변하는 것이 옳은 대답입니다.

Checked Exception은 컴파일 할 때 예외에 대한 처리를 강제하고 
Unchecked Exception은 예외에 대한 처리를 강제하지 않습니다.

예외 처리를 강제한다는 것은 무엇일까요? try-catch 문법 또는 throws 문법을 강제합니다.

두 종류의 예외의 차이

public class CheckedException extends Exception{}

CheckedException class는 Exception class를 상속 받습니다.

public class Client {
    public void throwsCheckedExceptionMethod() throws CheckedException {
        throw new CheckedException();
    }

    public void tryCatchCheckedExceptionMethod() {
        try {
            throw new CheckedException();
        } catch (CheckedException e) {
            // 예외대 대한 적절한 처리
            e.printStackTrace();
        }
    }
}

위의 코드에서 throws, try-catch를 지운다면 컴파일 에러가 나타나게 됩니다. 이것으로 CheckedException은 예외 처리를 강제한다는 것을 알 수 있습니다.

public class UncheckedException extends RuntimeException{ }

UncheckedException은 RuntimeException을 상속 받습니다.

public class Client {
    public void throwsUncheckedExceptionMethod() {
        throw new UncheckedException();
    }

    public void tryCatchUncheckedExceptionMethod() {
        throw new UncheckedException();
    }
}

Client에서는 예외를 강제하지 않아도 실행이 됩니다. Exception이 발생하는 것은 당연하지만 컴파일 시점에서 예외처리를 강제하지 않아도 컴파일 에러는 발생하지 않습니다.

예외 관련 클래스 상속도

Exceptoin 클래스를 상속 받으면 CheckedException이 되고 RuntimeExceptoin 클래스를 상속 받으면 UnCheckedException이 됩니다.
Exceptoin을 상속 받은 RuntimeException은 UnChekedException 입니다. 이것은 이해하는 것이 아닌 암기가 필요한 내용입니다.

어떤 예외를 사용하는게 권장되는가?

그렇다면 Checked Exception과 Unchecked Exception 중 어떤 예외를 사용해야 할까요? 컴파일 시점에서 에러처리를 강제하는 Checked Exception을 사용하는 것이 옳다고 생각할 수 있습니다.

앞으로 예외를 정의할 때는 Checked Exception이 아닌 Unchecked Exception을 사용해야 합니다.

왜?

그 이유는 대부분의 예외는 로직에서 해결할 수 없기 때문입니다. 예시를 하나 들어보도록 하겠습니다.


사용자가 서버에 파일을 요청하고 서버는 파일을 찾아 사용자에게 전달하는 서비스입니다.

사용자가 파일 이름을 잘못 입력할 경우 서버에서 할 수 있는 일은 사용자에게 제대로 된 파일 이름을 입력해 달라고 다시 요청하는 방법입니다.

이 때는 FileNotFoundException을 사용합니다.

public class FileNotFoundException extends IOException {
 // ... 생략
}

public class IOException extends Exception {
// ... 생략
}

FileNotFoundException는 IOException을 상속 받고 있고 IOException은 Checked Exception입니다. 컴파일 시점에 에러처리를 강제하는 것입니다.

public void readFile(String fileName) throws FileNotFoundException{
    FileReader fileReader = new FileReader(fileName);
}

public void readFile(String fileName) {
    try {
        FileReader fileReader = new FileReader(fileName);
    } catch (FileNotFoundException e) {
        throw new RuntimeException(e);
    }
}

그렇다면 에러에 대한 처리는 이렇게 될 것입니다. throws로 에러를 던진다던가 try-catch에 RumetimeException을 발생시킨다던가 할 것입니다.


결국 무의미한 throws가 반복되게 됩니다. 그리고 이것은 객체지향적으로도 문제가 있습니다.

readFile이 FileNotFoundException을 던지는 예외라는 것이 외부에 알려지는 것은 
캡슐화가 깨진 것입니다.

내부에서 FileNotFoundException을 발생시킬만한 코드가 있다는 것이 던져지는 예외를 통해 외부에 알려지게 됩니다.

그러므로 Unchecked Exception을 사용하여 예외를 도중에 처리하고 싶다면 try-catch를 사용하면 됩니다.

결론

Unchecked Exception을 사용하는 것이 객체지향적으로 옳다!!


해당 게시글은 프로그래머스 스쿨 강의
"실무 자바 개발을 위한 OOP와 핵심 디자인 패턴(푸)"
를 정리한 내용입니다. 쉽게 잘 설명해주시니 여러분도 강의를 듣는 것을 추천드립니다.

profile
부족함을 인정하고 노력하자

0개의 댓글