Back-End/Spring

[Spring DB][자바 예외] - 체크, 언체크 예외의 활용 그리고 예외 포함 스택 트레이스

얄루몬 2022. 7. 20. 18:37

 

💻본 포스팅은 '스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 - 김영한'님의 강의를 듣고 작성되었습니다.

https://inf.run/As6W

 

스프링 DB 1편 - 데이터 접근 핵심 원리 - 인프런 | 강의

백엔드 개발에 필요한 DB 데이터 접근 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 DB 접근 기술의 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., - 강의

www.inflearn.com


목차
1. 체크 예외 활용
2. 언체크 예외 활용
3. 예외 포함과 스택 트레이스

1. 체크 예외 활용

  • 현재 실무에서는 체크 예외보단 언체크 예외를 사용하는 것이 일반적이라고 한다.
  • 대부분 다 언체크 예외를 사용하고 예외적으로 비지니스 로직에 문제가 발생해서 이 문제를 의도적으로 체크해야 할 때만 체크 예외를 사용한다 한다.
      • 계좌 이체 실패(매우 심각한 문제)
      • 이 경우엔 예외를 놓치면 안 된다고 생각하기에 체크 예외로 사용한다.
      • 컴파일러를 통해 놓친 예외를 인지한다.
  • 그러나 비지니스 로직에 생긴 예외도 언체크 예외를 사용해서 해결할 때도 있다.(비지니스 로직에서 발생한 예외라고 전부 체크예외 사용 X)

[체크 예외의 문제점]

  • 체크 예외는 예외 누락이 없어서 훨씬 좋아보이지만 사실은 문제점이 많다.

  • 위의 그림처럼 시스템 레벨에서 발생하는 예외는 사실 복구하기 힘들다.
  • 또한 이 부분을 해결하기 위해서 서비스계층으로 체크 예외를 던진다고 해도 서비스 계층에서도 이를 해결하지 못해 결국 컨트롤러로 예외를 던지게 될 것이다.
  • 이때 컨트롤러 역시 따로 예외를 처리하지 않는다면 이 예외는 던져지게 되는데 때 문제가 발생한다.
package hello.jdbc.exception.basic;


import org.junit.jupiter.api.Test;

import java.net.ConnectException;
import java.sql.SQLException;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

public class CheckedAppTest {

    @Test
    void checked(){
        Controller controller = new Controller();
        assertThatThrownBy(()-> controller.request())
                .isInstanceOf(Exception.class);
    }

    static class Controller{
        Service service = new Service();

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

        //해당 예외를 처리하지 않고 controller로 던지는 중중
       public void logic() throws ConnectException, SQLException {
            repository.call();
            networkClient.call();
        }
    }

    static class NetworkClient{
        public void call() throws ConnectException {
            throw new ConnectException("");
        }
    }

    static class Repository{
        public void call() throws SQLException {
            throw new SQLException("ex");
        }
    }



}
  • 해당 코드를 살펴보면 Repository & NetworkClient에서 발생한 체크 예외를 넘길 때 SQLException 즉, JDBC 기술에 의존하여 계속 예외를 처리하고 있는 것이다.
  • 이 문제는 JDBC가 아닌 JPA 등 다른 기술로 대체하게 될 때 해당 JDBC 기술이 쓰인 코드를 모두 변경해주어야 하는 문제가 생긴다. 

다시 말해 체크 예외의 문제점은 두가지로 볼 수 있다.

1. 대부분 예외는 복구 불가능하다.

2. 의존관계에 대한 문제(위의 상황엔 JDBC 기술에 의존한 것이 문제가 된다.)


2. 언체크 예외 활용

  • 체크 예외와 달리 중간에 기술리 변경되어도 해당 시작하는 부분만 바꿔주면 된다.(모든 코드를 손볼 필요가 없다.)

[언체크 예외를 선호하는 이유?]

  • 예외는 대부분 처리할 수 없는 경우가 많기 때문에 언체크 예외를 사용하는 추세로 바뀌었다.
  • 처리해야 할 예외의 양이 증가하기 때문에 언체크 예외를 사용하는 추세로 바뀌었다.
    • 외부 라이브러리 사용 등 많은 부분이 있다..

[런타임 예외는 문서화]

  • 런타임 예외가 있으면 선언하지 않아도 되기 때문에 런타임 예외가 있을 땐 이를 문서화해서 사용하는 것이 좋다.

3. 예외 포함과 스택 트레이스

예외를 전환할 때는 기존 예외를 꼭 포함해서 전환해주어야 한다.

  • 그래야 해당 예외가 어떤 예외로부터 나왔는지를 확인할 수 있다.