예외 계층의 구조와 체크 예외, 언체크 예외의 차이와 활용에 대해서 알아보려고 합니다.
- Object: 예외도 객체이고, 모든 객체의 최상위 부모는 Object이므로, 예외의 최상의 부모 또한 Object 입니다.
- Throwable: 최상위 예외로서, Exception과 Error로 나눌 수 있습니다.
- Error: 메모리 부족, 시스템 오류와 같이 애플리케이션에 복구 불가능한 시스템 예외입니다. 이 예외를 잡아서는 안 됩니다.
- 상위 예외를 catch로 잡아버리면 하위 예외까지 같이 잡아버리는데, Throwable 예외를 잡게 되면, Error 예외도 함께 잡는 불상사가 일어날 수 있기 때문에 잡아서는 안됩니다.
- Error는 언체크 예외입니다.
- Exception: 체크 예외
- 애플리케이션 로직에서 사용할 수 있는 실질적인 최상위 예외
- 컴파일러가 체크할 수 있는 예외(RuntimeException 제외)
- RuntimeException: 언체크 예외, 런타임 예외
- 컴파일러가 체크하지 않는 언체크 예외
- NullpointException, IIIegalArgumentException, IIlegalStateException도 언체크 예외에 해당합니다.
예외 기본 규칙
- 예외를 잡아서 처리하거나 던져야 합니다.
- 예외를 잡거나 던질 때 지정한 예외에 더해서 자식 예외도 함께 처리됩니다. (catch로 잡거나, throws로 던져도 하위 예외들이 모두 처리)
만약, 예외를 처리하지 못하고 계속 던지면 main() thread에서 예외 로그를 출력하면서 시스템이 종료됩니다.
웹 애플리케이션의 경우 수많은 사용자들의 요청을 처리하기 때문에, 하나의 예외로 시스템이 종료되면 안됩니다. 스프링 서버가 해당 예외를 받아서 처리하는데, 주로 사용자에게 개발자가 지정한 오류 페이지를 보여주게 됩니다. 이제 체크 예외와 언체크 예외의 장단점과 차이점을 천천히 설명드리겠습니다.
1. Check Exception
- Exception을 상속받으면 체크 예외가 됩니다.
- 생성자를 통해 오류 메세지를 보관하는 기능을 제공합니다. (Uncheck Exception도 동일하게 예외 보관 기능 제공)
Check Exception의 장단점
- 장점
- 개발자가 실수로 예외를 누락하지 않도록 컴파일러를 통해 문제를 잡아줍니다.
- 단점
- 예외를 잡아서 처리할 수 없는 경우, throws 예외를 필수로 선언해야 합니다.
- Controller나 Service가 처리할 수 없어도 throws를 통해 던지는 예외를 작성해줘야 합니다.(의존관계 문제)
- 대부분의 예외는 복구가 불가능(시스템 관련 예외)하여 서블릿 필터, 스프링 인터셉터, 스프링의 RestControllerAdvice로 처리해야 합니다.
2. Unchecked Exception
- RuntimeException을 상속받습니다.
- 컴파일러가 예외를 체크하지 않습니다.
Unchecked Exception의 장단점
- 장점
- 예외를 잡아서 처리할 수 없는 경우, throws 예외를 생략할 수 있습니다. 의존관계를 참조하지 않아도 됩니다.
- 단점
- 개발자가 예외를 누락할 수 있습니다.
일반적으로 체크 예외와 언체크 예외의 큰 차이는 예외를 처리할 수 없는 경우, throws 예외를 밖으로 던지냐 안던지냐의 차이입니다.
이제 둘 중 어떤 것을 사용하면 더 효율적인 예외처리를 할 수 있는지 설명드리겠습니다.
일반적으로 언체크(런타임) 예외를 사용하고, 체크 예외는 비즈니스 로직상 의도적으로 던지는 예외에만 사용해야 합니다. (반드시 예외를 잡아서 처리해줘야 하는 로직)
왜냐하면 모든 메서드에 method() throws 예외를 선언해줘야 하기에 매우 번거롭습니다. 예시를 들어서 설명드리겠습니다.
Checked Exception를 지양해야 하는 이유
NetworkClient, Repository에서 각각 ConnectionException 체크 예외, SQLException 체크 예외를 던진 상황입니다. Service에서는 DB관련 로직, 클라이언트 연결 오류를 처리할 방법을 모르기에 Controller에게 예외를 던져주고, Controller도 같은 상황이기에 예외를 밖으로 던져줍니다.
이러한 문제들은 개발자는 어디에서 문제가 발생했는지 알 수 있어도, 클라이언트 관점에서는 어디에서 문제가 발생했는지 알 수 없습니다. 또한 보안상 문제가 발생할 수도 있게 됩니다. 불필요한 영역에서 의존관계 문제가 발생하고, Jdbc에서 Jpa와 같은 기술로 변경해도 throws 예외 부분을 모두 변경해줘야 하기에 OCP, DI 원칙에도 위배됩니다. 이러한 이유 때문에 Checked Excepion을 지양해야 합니다.
<참고 자료>
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-db-1/dashboard
'Java' 카테고리의 다른 글
[Java] Garbage Collection (1) | 2024.12.05 |
---|---|
[Java] ClassNotFoundException VS NoClassDefFoundError (1) | 2024.02.06 |