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
'Spring Series > Spring Framework' 카테고리의 다른 글
[Spring] 여러 AOP 및 트랜잭션 기법들 (0) | 2022.04.01 |
---|---|
[Spring] 트랜잭션 추상화 (0) | 2022.03.27 |
[Spring] Template/Callback 패턴 (0) | 2022.03.19 |
[Spring] 테스트 코드의 작성 (0) | 2022.03.10 |
[Spring] @Value가 null을 가져오는 문제 (0) | 2022.03.06 |
댓글