본문 바로가기
IT/Spring

토비 스프링 - 예외

by 봉즙 2019. 10. 28.

예외 발생 이후 try/catch를 통해 잡아낸 후 아무것도 하지 않는 다면 메모리나 리소스가 소진되거나 다른 오작동을 일으키게 될것이다.

모든 예외는 적절하게 복구 되던가 작업을 중단 시키며 운영자 또는 개발자에게 분명하게 통보되어야 한다.

 

체크 예외 : 명시적인 처리가 필요한 예외

 

throw를 통해 발생시킬 수 있는 예외

  1. Error : java.lang.Error의 서브 클래스들이다. 에러는 시스템에 비정상적인 상황이 발생했을 경우 사용된다. 그렇기에 주로 자바 VM이 발생시키며 어플리케이션 코드에서 잡으려 하면 안된다.  OutOfMemoeryError나 ThreadDeath같은 에러는 Catch블럭으로 잡아봐야 대응방법이없다.
    즉, 시스템 레벨에서 특별한 작업을 하는게 아니라면 어플리케이션에서는 이러한 에러 처리는 신경쓰지 않아도된다.
  2. Exception과 체크 예외 : 개발자들이 만든 어플리케이션 코드의 작업 중에 예외 상황이 발생한 경우 사용된다. Exception 클래스는 체크 예외와 언체크 예외로 구분된다. 체크 예외는 Exception클래스의 서브클래스 이면서 RuntimeException 클래스를 상속하지 않은 것들이고, 언체크 예외는 RuntimeException을 상속한 클래스를 말한다.
  3. RuntimeException과 언체크/런타임 예외 : java.lang.RuntimeException 클래스를 상속한 예외들은 명시적인 예외처리를 강제 하지 않기 때문에 언체크 예외라고 불린다. 또는 대표 클래스 이름을 따서 런타임 예외라고도 한다. 런타임 예외는 에러와 마찬가지로 잡아주지 않아도된다. 주로 런타임예외는 오류가 있을 때 발생하도록 의도된 것들이다. NullPointException이나 IllegalArgumentException 등이 있다.

 

예외 처리 방법

  1. 예외 복구 : 예외 상황을 파악하고 문제를 해결해서 정상 상태로 돌려놓는 것 (ex. 연결 재시도)
  2. 예외 처리 회피 : 자신이 처리를 담당하지 않고 호출한 쪽으로 던져 버리는 것. (ex. throws SQException)
    다른 오브젝트에게 예외 처리 책임을 분명하게 지게 하거나 최선의 방법이라는 확신이 있어야 한다.
  3. 예외의 전환 : 예외를 복구해서 정상적인 상태로는 만들 수 없어 예외를 메소드 밖으로 던지는 것이다. 예외 회피와는 달리 발생한 예외를 그대로 넘기는 게 아니라 적절한 예외로 전환해서 던진다.
    목적은 1) 내부에서 발생한 예외를 그대로 던지는 것이 그 예외 상황에 대한 적절한 의미를 부여하지 못하는 경우에
    2) 예외를 처리하고 쉽고 단순하게 만들기 위해서 포장하는 것. 주로 예외처리를 강제하는 체크 예외를 언체크 예외로 바꾸는 경우가 많다. 무의미하게 체크 예외를 계속 넘기는 것은 장점이 없기에 런타임 예외로 포장해여 던져 다른 계층의 메소드에 throw가 불필요하게 들어가는 것을 막는다.
public void add(User user) throws DuplicateUserIdException, SQLException {
	try {
    //user정보 추가하는 코드
    }
    catch(SQLException e){//MySQL의 Duplicate Entry(1062)이면 예외전환
    if(e.gerErrorCode() == MYsqlErrorNUmbers.ER_DUP_ENTRY)
    	throw DuplicateUserIdException();
    else
    	throw e;//이외의 경우 그대로
    }
}

위의 코드는 예외의 전환 첫번째 경우

 

 

예외 처리 전략

자바 엔터프라이즈의 경우 다수의 사용자가 사용하며 에러가 발생하기에 중단을 통해 해결하는 것이 불가능하기에, 예외 발생환경에서 해당 요청을 취소하고 서버관리자나 개발자에게 통보하는 편이 좋다. 이러한 이유로 대응이 불가능한 체크 예외라면 런타임 예외로 전환해서 던지는 것이 좋다.

대부분의 SQLException의 경우 대응이불가능하기에 런타임 예외로 포장하여 처리하는 전략이 좋다.

public class DuplicateUserIdException exteds RuntimeException {
	public DuplicateUserIdException(Throwable cause){
    	super(cause);
    }
}
public void add() throws DuplicateUserIdException {
	try {
    }
    catch (SQLException e){
    if(e.gerErroCode() == MysqlErrorNumbers.ER_DUP_ENTRY)
    	throw new DuplicateUserIdException(e); //예외 전환
    else
    	throw new RuntimeException(e); //예외 포장
    }
}

위와 같이 처리하면 아이디 중복시 추천 아이디를 제안 할 수 도 있게된다.

 

 

어플리케이션 예외 : 시스템 또는 외부의 예외 상황이 원인이 아닌 어플리케이션 자체의 로직에 의해 의도적으로 발생시키고, 반드시 catch해서 무엇인가 조치를 취하도록 요구하는 예외
ex)은행 출금

어플리케이션 예외 설계방법

1) 정상적인 출금과 잔고 부족의 경우 다른 리턴 값을 보여주게되면 정상적인 흐름이지만 예외 상황에 대해 처리할 수 있다.
2) 정상적인 흐름의 코드는 그대로 두고 예외 상황에 대해서 비즈니스적인 의미를 띤 예외를 던지는데, 의도적으로 체크 예외를 사용하여 개발자가 잊지 않고 예외상황에 대한 로직 구현을 강제 하는 것이 좋다.

 

 

 

JdbcTemplate은 DB의 에러코드를 DataAccessException 계층구조의 클래스 중 하나로 매핑 해준다. 드라이버나 DB 메타 정보를 참고해서 미리 준비된 리스트의 매핑 정보를 참고하기에 같은 종류의 에러인 경우 동일한 예외를 받는 것이 가능하다. 그럼에도 추가적인 예외에 대해 선언하고 싶다면 아래와 같이 처리하면된다.

public void add() throws DuplicateUserIdException {
	try {
    }
    catch (DuplicateKeyException e){
    //추가 작업
    	throw new DuplicateUserIdException(e); //예외 포장
    }
}

 

'IT > Spring' 카테고리의 다른 글

토비 스프링 - AOP  (0) 2019.11.04
토비 스트링 - 트랜잭션  (0) 2019.11.01
토비 스프링 - 템플릿 / 콜백  (0) 2019.10.23
토비 스프링 - 템플릿  (0) 2019.10.20
토비 스프링 - 학습 테스트, 버그 테스트  (0) 2019.10.20

댓글