본문 바로가기
  • 실행력이 모든걸 결정한다
Spring Series/Spring Framework

[Spring] 예외처리 전략

by 김코더 김주역 2022. 3. 20.
반응형

1. 일반적인 예외 처리 방법

1) 예외 복구

- 예외 상황에 대한 문제를 해결해서 정상적인 작업 흐름으로 돌아오게 하는 방법이다.

- 사용자에게 다른 접근 방법을 안내하거나, 정해진 횟수만큼 작업을 재시도하도록 처리하는 경우가 대표적인 사례다.

 

 

2) 예외 회피

- 예외처리를 자신이 담당하지 않고 throws 또는 throw문을 통해 자신을 호출한 쪽으로 던져버리는 방법이다.

- 예외 회피를 너무 남발하면 예외의 위치와 종류를 찾기 힘들어질 수 있다.

- 예외 회피를 사용할 때는 자신을 호출한 쪽에서 예외를 다루는 것이 최선의 방법이라는 확신이 있어야 한다.

public void task() throws SQLException {
    try {
        ...
    }
    catch(SQLException e) {
        // 로그 출력 등의 작업
        throw e;
    }
}

 

 

3) 예외 전환

예외 전환은 크게 2가지 목적으로 사용된다.

(1) 의미를 분명하게 해줄 수 있는 예외로 바꿔서 외부로 던지려는 목적

예시 SQLException -> DuplicateUserIdException

public void add(User user) throws DuplicateUserIdException {
    try {
        ...
    }
    catch (SQLException e) {
        if(e.getErrorCode() == MysqlErrorNumbers.ER_DUP_ENTRY) // 중복된 ID
            throw new DuplicateUserIdException(e); // SQLException -> DuplicateUserIdException
        else
            throw e;
    }
}

※ 전환하는 예외에 원래 발생하는 예외를 담은 것을 중첩 예외라고 하는데, 중첩 예외는 getCause() 메소드를 통해서 처음 발생한 예외를 확인할 수 있다.

 

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

 

(2) 체크 예외를 언체크 예외(런타임 예외)로 바꾸려는 목적

- 체크 예외는 예외처리를 강제하는 예외고, 언체크 예외는 예외처리를 강제하지 않는 예외다.

- 예외를 잡아도 복구할 방법이 없거나 외부에서 굳이 예외를 처리하지 않아도 되는 경우에 사용하는 방법이다. 이로써 외부에서 다시 예외를 잡거나 던지는 수고를 덜게 된다.

예시 SQLException -> EJBException

try {
    ...
} catch (SQLException se) { // 체크예외
    throw new EJBException(se); // 언체크예외
}

 

 

 

2. JdbcTemplate의 예외처리

- JdbcTemplate 템플릿과 콜백 안에서 발생하는 모든 SQLException을 런타임 예외인 DataAccessException 계층구조의 클래스들 중 하나에 담아서 던져준다. DataAccessException은 의미가 같은 예외라면 데이터 액세스 기술의 종류와 상관없이 일관된 예외가 발생하도록 되어있다.

- SQLException의 getErrorCode()가 반환하는 에러 코드는 DB의 종류마다 다르고, getSQLState()가 반환하는 상태 정보는 DB별로 달라지는 에러 코드를 대신할 수 있지만 정확성이 떨어진다. 즉, SQLException을 사용하여 DB 종류와 상관없는 예외 처리 코드를 구현하는 것보단 DataAccessException을 사용하는 것이 편리하다.

 

 

 

3. 예외 전환 API

- 예외 전환 API를 사용해서 SQLException을 DataAccessException으로 전환할 수도 있다. SQLExceptionTranslator 인터페이스를 구현한 클래스들 중 하나인 SQLErrorCodeExceptionTranslator를 사용하면 DB 에러 코드를 참조하는 예외 전환을 수행할 수 있다.

예시

try {
    ...
} catch(DuplicateKeyException ex) {
    SQLException se = (SQLException)ex.getRootCause(); // 루트 예외를 추출
    SQLExceptionTranslator set = new SQLErrorCodeSQLExceptionTranslator(this.dataSource);
    assertThat(set.translate(null, null, se), is(DuplicateKeyException.class)); // null 부분은 에러 메시지를 만들지 않겠다는 것이다.
}

 

 

 

 

 

 

● 참고 자료 : 토비의 스프링 3.1

반응형

댓글