자바 & 스프링 예외 처리

HUSII·2023년 5월 10일
0

스프링 DB

목록 보기
3/4

예외 기본 규칙
예외는 폭탄 돌리기와 같다. 잡아서 처리하거나, 처리할 수 없으면 밖으로 던져야한다.
-> 해당 메서드를 콜했던 메서드로 예외가 던져짐
-> 예외를 받은 메서드가 예외처리를 한다면 끝이고, 처리하지 않으면 다시 메서드 밖으로 던진다

예외를 던지는 것과 잡는 것
메서드 밖으로 예외를 던지는 것은 throws를 사용한다.

public void method1() throws Exception{ ... }
// 예외 발생하면
// Exception 예외 및 하위 자식 클래스 밖으로 던짐

잡는 것은 catch를 사용한다.

public void method2() {
	try{ ... } // 해당 코드에서 예외 발생하면
    catch(Exception e){ ... }
    // 여기서 잡음(Exception 또는 하위 자식 클래스만)
}

자바의 예외는 체크예외와 언체크 예외가 있다

체크 예외

대표적으로 Exception 클래스
체크 예외의 특징은
1. 해당 예외를 잡아서 처리하거나, 또는 밖으로 던지도록 선언해야한다.

  • 그렇지 않으면 컴파일 오류가 발생한다.
  1. 밖으로 던질때는 method() throws 예외를 필수로 사용해야 한다.

언체크 예외

대표적으로 RuntimeException 클래스(Exception 클래스를 상속받음)
언체크 예외의 특징은
1. 컴파일러가 예외를 체크하지 않는다
2. throws를 선언하지 않고 생략할 수 있다. 이 경우 자동으로 예외를 던진다.


체크 예외의 문제점

  1. 복구 불가능한 예외가 많다
  2. 예외를 밖으로 던져야 할때마다 throws 예외를 사용하면서 의존 관계에 대한 문제가 생긴다(각종 예외를 의존하게 된다)

    JDBC는 SQLException을 사용하는데 이를 JPA로 바꾸게 되면 JPAException로 바꾸면서 객체 지향적으로 코드를 설계하지 못하게 된다

처음 자바를 설계할 당시에는 체크 예외가 더 나은 선택이라 생각했다고 한다.
그런데 시간이 흐르면서 복구 할 수 없는 예외가 너무 많아졌다.
특히 라이브러리를 점점 더 많이 사용하면서 처리해야 하는 예외도 더 늘어났다.
체크 예외는 해당 라이브러리들이 제공하는 모든 예외를 처리할 수 없을 때마다 throws에 예외를 덕지덕지 붙어야 했다.

체크 예외의 이런 문제점 때문에 최근 라이브러리들은 대부분 런타임 예외를 기본으로 제공한다.
대신 언체크 예외를 사용하면, 이에 대한 예외처리를 해줘야한다.
@ControllerAdvice, @ExceptionHandler사용


또한 체크 예외가 발생했을때, 이를 언체크 예외로 변환하여 던질 수 있다.

static class Repository {
  public void call() {
    try {
    	runSQL();
    } catch (SQLException e) {
    	throw new RuntimeSQLException(e);
    }
  }
  private void runSQL() throws SQLException {
    throw new SQLException("ex");
  }
}
static class RuntimeConnectException extends RuntimeException {
  public RuntimeConnectException(String message) {
  	super(message);
  }
}

RuntimeException을 상속받으면 언체크 예외가 되고
Exception을 상속받으면 체크 예외가 된다.

만들어놓은 예외로 전환할때 꼭 기존 예외를 포함하자
왜 예외가 발생했는 알 수 있다


많은 예외가 던져질때, 특정한 예외만 복구를 시도할 수도 있다

이때 각 예외마다 가지고 있는 구별된 예외코드가 있기 때문에
이를 이용해서 처리하면 된다.

} catch (SQLException e) {
	//h2 db
	if (e.getErrorCode() == 23505) { // 키 중복 오류
		throw new MyDuplicateKeyException(e);
	}
	throw new MyDbException(e);
}

이때 에러코드는 각가의 데이터베이스마다 다르다.
데이터베이스가 전달하는 오류는 수백가지의 오류 코드가 있다.

스프링은 예외 변환기를 통해서 SQLExceptionErrorcode에 맞는 적절한 스프링 데이터 접근 예외로 변환해준다.
만약 예외 처리가 필요하면 특정 기술에 종속적인 SQLException같은 예외를 직접 사용하는 것이 아니라, 스프링이 제공하는 데이터 접근 예외를 사용하면 된다.
스프링은 예외 추상화를 통해 특정 기술에 종속적이지 않다.

SQLExceptionTranslator exTranslator = new
SQLErrorCodeSQLExceptionTranslator(dataSource);
DataAccessException resultEx = exTranslator.translate("select", sql, e);

translate()메서드의 파라미터
1. 읽을 수 있는 설명
2. 실행한 sql
3. 발생된 SQLException
이렇게 하면 스프링 데이터 접근 계층의 예외로 변환해서 반환해준다

} catch (SQLException e) {
	throw exTranslator.translate("save", sql, e);
}
profile
공부하다가 생긴 궁금한 것들을 정리하는 공간

0개의 댓글