본문 바로가기
spring/토비의 스프링

토비의 스프링 Vol. 1 정리 - 4장 예외 - 2 예외처리 방법

by Empering 2020. 5. 6.
반응형

토비의 스프링 Vol. 1 정리 - 4 - 1 예외처리 방법

4장 예외


예외처리 방법

> 예외 복구

예외상황을 파악하고 문제를 해결해서 정상 상태로 돌려놓는 것이다.

예외처리 코드를 강제하는 체크 예외들은 이렇게 예외를 어떤 식으로든 복구할 가능성이 있는 경우에 사용한다. API를 사용하는 개발자로 하여금 예외상황이 발생할 수 있음을 인식하도록 도와주고 이에 대한 적절한 처리를 시도해보도록 요구하는 것이다.

 

> 예외처리 회피

예외처리를 자신이 담당하지 않고 자신을 호출한 쪽으로 던져버리는 것이다.

throws 문으로 선언해서 예외가 발생하면 알아서 던져지게 하거나 catch 문으로 예외를 잡은 후 다시 예외를 던지는 것이다.

        try {
            // ...
        } catch (SQLException e) {
            // 로그출력
            throw e;
        }

> 예외 전환

예외 회피와 비슷하게 예외를 복구해서 정상적인 상태로는 만들 수 없기 때문에 예외를 메소드 밖으로 던지는 것이다. 하지만 예외 회피와 달리, 발생한 예외를 그대로 넘기는 게 아니라 적절한 예외로 전환해서 던진다는 특징이 있다. 예외 전환은 보통 두 가지 목적으로 사용된다.

첫 번째, 내부에서 발생한 예외를 그대로 던지는 것이 그 예외상황에 대한 적절한 의미를 부여해주지 못하는 경우에 의미를 분명하게 해줄 수 있는 예외로 바꿔주기 위해서이다.

		// ....
		} catch (SQLException e) {
			throw DuplicateUserIdException(e);
		}

두 번째, 예외를 처리하기 쉽고 단순하게 만들기 위해 포장하는 것이다. 주로 예외처리를 강제하는 체크 예외를 언체크 예외인 런타임 예외로 바꾸는 경우이다.

 

예외처리 전략

> 런타임 예외의 보편화

자바 엔터프라이즈 서버환경에서는 수많은 사용자가 동시에 요청을 보내고 각 요청이 독립적인 작업으로 취급된다. 독립형 애플리케이션과 달리 서버의 특정 계층에서 예외가 발생했을 때 작업을 일시 중단하고 사용자와 바로 커뮤니케이션하면서 예외상황을 복구할 수 있는 방법이 없다.

대응이 불가능한 체크 예외라면 빨리 런타임 예외로 전환해서 던지는 게 낫다.

    public class DuplicateUserException extends RuntimeException {
        public DuplicateUserException(Throwable cause) {
            super(cause);
        }
    }
    
    public void add() throws DuplicateUserException {
        try {
            // JDBC를 통한 USER INSERT 코드
        } catch (SQLException e) {
            if (e.getErrorCode() == ERR_DUP_ENTRY) {
                // 예외 전환
                throw new DuplicateUserException(e);
            } else {
                // 예외 포장
                throw new RuntimeException(e);
            }
        }
    }

위 add() 메소드를 사용하는 오브젝트는 SQLException을 처리하기 위해 불필요한 throws를 선언할 필요가 없고, 필요한 경우 DuplicateUserException을 이용해 아이디 중복 상황을 처리 할 수 있다.

 

> 애플리케이션 예외

시스템 또는 외부의 예외상황이 원인이 아니라 애플리케이션 자체의 로직에 의해 의도적으로 발생시켜 반드시 catch 해서 무엇인가 조치를 취하도록 요구하는 예외이다.

정상적인 흐름을 따르는 코드는 그대로 두고 비즈니스적 의미를 가진 예외를 던지도록 만든다.

        try {
            // withdraw() 메소드 수행 시 체크 예외를 던지도록 처리
            BigDecimal balance = account.withdraw(amount);
            // ...
            // 정상적인 처리 로직 수행
        } catch (InsufficientBalanceException e) {
            // InsufficientBalanceException 의 인출가능한 잔고금액 정보를 가지고 옴
            BigDecimal avaliFunds = e.getAvailFunds();
            // ...
            // 잔고부족 메세지 출력
        }

 

스프링 JdbcTemplate 예외 처리 전략

대부분의 SQLException은 복구가 불가능하다. 그리고 DAO 밖에서 SQLException을 다룰 수 있는 가능성은 거의 없다. 따라서 예외를 방치하지 말고 언체크/런타임 예외로 전환하는 전략을 사용해야 한다.

JdbcTemplate 템플릿과 콜백 안에서 발생하는 발생하는 모든 SQLException 을 런타임 예외인 DataAccessException으로 포장해서 던져준다. 따라서 JdbcTemplate을 사용하는 메소드에서는 꼭 필요한 경우에만 런타임 예외를 잡아서 처리하고 그외의 경우에는 무시해도 된다.

    // throws 가 선언되어 있지만 런타임 예외이므로 처리가 강제되지 않는다.
    public int update(PreparedStatementCreator psc) throws DataAccessException {
        return this.update(psc, (PreparedStatementSetter)null);
    }

 

반응형

댓글