예외처리 : 프로그램 실행 중 발생할 수 있는 문제에 대비하는 방법

예외의 종류와 특징

  • Error
    • java.lang.Error 클래스의 서브클래스
    • 시스템에 비정상적인 상황이 발생할 때 사용
    • 주로 자바 VM에서 발생시키며 애플리케이션 코드에서 잡지 않아야 함
    • 예: OutOfMemoryError, ThreadDeath
  • Exception
    • java.lang.Exception 클래스와 그 서브클래스들
    • 애플리케이션 코드에서 발생할 수 있는 예외 상황에 사용
    • 체크 예외와 언체크 예외(RuntimeException)로 구분됨
    • 체크 예외: Exception 클래스의 서브클래스이지만 RuntimeException을 상속하지 않음
    • 체크 예외는 반드시 예외처리 코드가 필요함
    • 예: IOException, SQLException
  • RuntimeException
    • java.lang.RuntimeException 클래스를 상속한 예외들
    • 명시적인 예외처리를 강제하지 않음
    • 프로그램 오류가 있을 때 주로 발생
    • 예: NullPointerException, IllegalArgumentException

잘못된 예외처리

  • try/catch
      try {
          ... 
      }
      catch(SQLException e){
      }
      //
      try {
          ... 
      }
      catch(SQLException e){
          System.out.println(e);
      }
      //
      try {
          ... 
      }
      catch(SQLException e){
          e.printStackTrace();
      }
    
  • 모든 예외는 적절하게 복구되든지 아니면 작업을 중단시키고 개발자나 운영자에게 확실하게 통보돼야함

  • throws
      public void method1() throws Exception {
          method2();
          ...
      }
    	
      public void method2() throws Exception {
          method3();
          ...
      }
    	
      public void method3() throws Exception {
          ...
      }
    

예외처리 방법

  • 예외 복구
    • 예외상황을 파악하고 문제를 해결해서 정상 상태로 돌려놓는 것
  • 예외처리 회피
    • 예외처리를 자신이 담당하지 않고 자신을 호출한 쪽으로 던져버리는 것
  • 예외 전환
    • 발생한 예외를 그대로 넘기는 게 아니라 적절한 예외로 전환해서 던지는 것
    • 내부에서 발생한 예외를 그대로 던지는 것이 그 예외상황에 대한 적절한 의미를 부여해주지 못하는 경우
      • 의미를 가지는 새로운 예외를 만들고 원래 발생한 예외를 담아서 중첩 예외로 던져주는 것
    • 예외 처리를 강제하는 체크예외를 언체크예외로 바꾸기 위해

예외처리 전략

자바의 환경이 서버로 이동하며 체크예외의 가치가 떨어지고 있음

  • 최근에 등장하는 오픈소스 프레임워크에서는 API가 발생시키는 예외를 언체크예외로 정의하는것이 일반화
  •  대부분 복구 불가능하고 따로 포장해서 던져야하기때문에 애초부터 런타임 에러를 던지도록 만든다

  • 런타임 예외 중심 전략
    • 어떻게든 처리 되겠지 라는 낙관적인 태도를 기반으로 함
  • 애플리케이션 예외
    • 시스템 또는 외부의 예외상황이 원인이 아니라 애플리케이션 자체의 로직에 의해 의도적으로 발생시키고, 반드시 catch 해서 무엇인가 조치를 취하도록 요구 (ex 계좌 출금, 송금 실패 안내)
  • 설계 방법
    • 상황에 따라 다른 리턴 타입으로 구분
      • 명확하지 않은 리턴값으로 인해 문제 발생 가능성
    • 해당 의미를 지닌 예외를 생성하여 던짐
      • 확실한 처리를 위한 체크 예외로 생성

JDBC의 한계

Connection, Statement, ResultSet 등의 표준 인터페이스를 통해 그 기능을 제공해주기 때문에 개발자들은 표준화된 JDBC의 API에만 익숙해지면 DB의 종류에 상관없이 일관된 방법으로 프로그램을 개발할 수 있다

DB를 자유롭게 변경하는 유연한 코드를 보장해주지는 않음

  • 비표준 SQL
    • 해당 DB의 특별한 기능, 최적화된 SQL 생성에 유용
  • 호환성 없는 DB에러 정보
    • DB마다 에러의 종류와 원인이 다름
    • SQL 상태정보를 참조하는 코드가 다름
    • getSQLState()을 통해 표준화된 상태코드를 가져와야함(그런데 제대로 만들어주지 않는다는 점)

스프링은 DB별 에러코드를 분류해서 스프링이 정의한 예외 클래스와 매핑해놓은 에러코드 매핑정보 테이블을 만들어두고 이용한다

  • 오라클 에러 코드 매핑 파일
      <bean id="Oracle" class="org.springframework.jdbc.support.SQLErrorCodes">
      <property name="badSqlGrammarCodes"〉
          <value>900,903,904,917,936,942,17006</value>
      </property> 
      <property name="invalidResultSetAccessCodes"> 
          <value>17003</val니e>
      </property>
      <property name="duplicateKeyCodes">
          <value>1</value>
      </property>
      <property name="dataIntegrityViolationCodes">
          <value>1400,1722,2291,2292</value>
      </property>
      <property name="dataAccessResourceFailureCodes"〉
          <value>17002,17447</value>
      </property>
    

DataAccessException

스프링은 데이터 엑세스 기술을 사용할 떄 발생하는 예외들을 추상화해서 DataAccessException 계층구조 안에 정리해놓음 (SQLException을 전환할 때 사용)

예외 전환 + 예외 추상화 = 데이터 엑세스 기술과 구현 방법에 독립적인 DAO

어느정도 추상화된 공통 예외로 변환해주지만 전부는 아님

카테고리:

업데이트:

댓글남기기