토비의 스프링을 보고 개인적으로 요약한 자료이다. 이번 포스팅에서는 예외에 관해서 적고자 한다.
문제가 있을 시, lshn1007@hanyang.ac.kr 로 메일주시면 삭제하겠습니다.
1. 예외를 잡고는 아무것도 하지 않을 때
* 예외 발생을 무시하고 다음 라인으로 넘어가겠다는 의도가 있는 것이 아니라면 절대 하면 안됨
* 예외 발생을 무시하고 넘어가면 특정 기능이 비정상 동작하거나, 메모리 또는 리소스가 낭비될 수 있음
* 디버그 하기 힘들어 질 수 있음
2. 예외를 잡고는 콘솔에 출력만 하는 행위
* 로그를 모니터링하지 않는 이상 무시될 수 있으므로 catch 블록을 이용해서 출력만 한것은 제대로 된 예외 처리를 한 것이 아님
3. 예외 처리의 책임을 전가만 하는 행위
* 사용하려는 메소드에서 어떤 문제가 발생할 수 있는 지 의미 있는 정보를 얻을 수 없음
public void method1() throws Exception {
method2();
}
public void method2() throws Exception {
method3();
}
public void method3() throws Exception {
...
}
굉장히 부끄러운 챕터임... 실제로 2번과 같은 행위를 프로젝트에서 진행한 경험이 있음
자바에서 throw를 통해 발생시킬 수 있는 예외는 총 3가지가 존재한다.
1. Error
2. Checked Exception
IOException
, SQLException
이 대표적인 예시임3. UnChecked Exception
NullPointerException
, IllegalArgumentException
등이 대표적인 예시임1. 예외 복구
/**
* 예시 : 네트워크가 불안정한 상태에서 원격 DB에 접속하던 중 예외가 발생한 경우에는 정해진 횟수만큼 재시도하여 복구
*/
int maxRetry = MAX_RETRY;
while (maxRetry-- > 0) {
try {
... // 예외가 발생할 가능성이 있는 시도
return; // 작업 성공
} catch (SomeException e) {
// 로그 출력. 정해진 시간만큼 대기
} finally {
// 리소스 반납. 정리 작업
}
}
throw new RetryFailedException(); // 최대 재시도 횟수를 넘기면 직접 예외 발생(복구가 불가능하므로 더 시도하지 않고 예외 복구 포기)
2. 예외 처리 회피
// 예외 처리 회피 1 - throws
public void add() throws SQLException {
// JDBC API
}
// 예외 처리 회피 2 - rethrow
public void add() throws SQLException {
try {
// JDBC API
} catch (SQLException e) {
// 로그 출력
throw e;
}
}
3. 예외 전환
예외 처리와 마찬가지로 예외 처리의 책임을 호출한 쪽으로 전달하지만, 발생한 예외를 그대로 넘기지 않고 적절한 예외로 전환해서 전달하는 방법을 말함
예외 전환은 두 가지 목적으로 사용된다.
(1) 발생한 예외를 그대로 던질 때 해당 예외 상황에 대한 적절한 의미를 부여하지 못하는 경우 의미를 분명히 하기 위해 사용
(2) 예외를 처리하기 쉽고 단순하게 만들기 위해 사용(ex. 체크 예외를 언체크 예외로 포장해 전달한다.) -> CheckedException 을 UnCheckedException으로 변경하는 로직
발생한 예외의 의미를 분명히 하는 예제
public void getAll(User user) throws QuerySyntaxException, SQLException {
try {
...
} catch (SQLException e) {
// 에러 코드가 ER_PARSE_ERROR 면 예외 전환
if (e.getErrorCode() == MysqlErrorNumbers.ER_PARSE_ERROR) {
throw new QuerySyntaxException();
} else {
throw e;
}
}
}
1. 런타임 예외를 통한 예외 처리 전략
2. 애플리케이션 예외를 통한 예외 처리 전략
애플리케이션 예외
라고 한다.try {
BigDecimal balance = account.withdraw(amount);
...
} catch (InsufficientBalanceException e) { // 체크 예외
// 예외에 담긴 인출 가능한 잔고 금액 정보를 가져옴
BigDecimal availFunds = e.getAvailFunds();
...
}