스프링/5. 스프링 DB-1

35. 언체크 예외 활용.

sdafdq 2023. 10. 4. 00:47

이제 언체크 예외를 쓸 것이다.

 

언체크 예외를 쓰면 이제 명시적으로 예외를 던져 줄 필요가 없다.

 

그럼 이제 코드도 깔끔해지고 더 이상 SQLException 같은 특정기술의 예외에 의존을 하지 않아도 된다.

 

 

 

public class UnCheckedAppTest {
    @Test
    public void unChecked(){
        Controller controller = new Controller();
        assertThatThrownBy(()-> controller.request())
                .isInstanceOf(Exception.class);
    }
    
    static class Controller{
        Service service = new Service();

        public void request(){
            service.logic();
        }
    }
    
    static class Service{
        Repository repository = new Repository();
        NetworkClient networkClient = new NetworkClient();

        public void logic(){
            repository.call();
            networkClient.call();
        }
    }
    
    static class NetworkClient{
        public void call() throws RuntimeConnectException {
            throw new RuntimeConnectException("연결 실패");
        }
    }
    
    static class Repository{
        public void call() throws RuntimeSQLException {
            try {
                runSQL();
            }catch (SQLException e){
                throw new RuntimeSQLException(e);
            }
        }

        public void runSQL () throws SQLException{
            throw new SQLException("ex");
        }
    }

    static class RuntimeConnectException extends RuntimeException {
        public RuntimeConnectException(String cause) {
            super(cause);
        }
    }

    static class RuntimeSQLException extends RuntimeException {
        public RuntimeSQLException(Throwable cause) {
            super(cause);
        }
    }
}

테스트 코드. 이제 런타임에러를 던지게 끔 해봤다.

아래서 부터 읽자면,

RuntimeException을 상속받아 런타임오류를 정의하고,

생성자 중 Throwable cause를 택했다.

cause는 말 그대로 이유인데, 그러니까.. 다음 에러에 같이 담을 수 있는?

Repository 보면 try catch로 잡는데, 전에 왔던 에러를 catch(e)로 담아서 받는다.

근데 이 때, 새로운 에러를 던지면서 Throwable인 에러를 던지면, 저 RuntimeSQLException에 같이 담긴다.

그러니까, 스택 트레이스에 cause도 나오고, RuntimeSQLException() 까지의 에러 정보도 같이 나온다.

 

보면 Service도 컨트롤러도 더 이상 에러를 던지지 않고, 또 그에 따라 의존성도 사라졌다.

그래서 중간에 기술을 바꾸고, 구현체를 갈아 끼워도 문제 없다.

 

 

대부분 복구 불가능 한 예외기 때문에, 이제 공통으로 처리하면 된다.

물론, 공통으로 처리하는 부분에서는 받는 예외를 바꿔야 한다.

 

 

 

이렇게 언체크 예외가 좋은데, 많은 기술들의 예외가 체크예외인 이유는..

옛날에는 아무래도 이걸 배우기 전의 생각처럼 체크예외가 좋다고 생각했다.

그래서 자바가 기본으로 제공하는 옛날에 만든 기능들에는 체크예외가 많다.

 

근데, 시간이 흐르며 복구할 수 없는 예외들이 너무 많아졌다.

그러다 그냥 throws Exception도 써보고 했는데, 저 방법은 잡은 예외가 어떤 예외인지 알 수 없기 때문에 안 좋다.

 

 

그러다 보니, 이제 대부분 최근 라이브러리 들은 런타임 예외를 기본으로 한다.

그리고, 체크 언체크는 말 그대로 컴파일러가 체크하냐 안 체크하냐의 차이라, 런타임 예외도 굳이 필요하면 잡아서 처리할 수 있다.

 

근데 아무래도, 런타임 예외는 명시를 안해도 되는 특성 때문에 놓칠 수 있기에,

문서화를 잘 해놓는 것이 중요하다.

 

예를 들어

이런 식으로.. 실제 JPAEntityManager이다.

 

 

또, 정말 중요한 예외면 아예 명시해 버리기도 한다.

 

 

'스프링 > 5. 스프링 DB-1' 카테고리의 다른 글

38. 런타임 예외로 문제 해결  (0) 2023.10.04
37. 스프링으로 예외처리, 반복 해결 체크예외  (0) 2023.10.04
34. 체크예외 활용  (0) 2023.10.03
33. 언체크 예외  (0) 2023.10.03
32. 예외 테스트  (0) 2023.10.02