토비의 스프링 Ver4

존스노우·2021년 11월 17일
0

스프링

목록 보기
4/22

예외

사라진 SQLException

초난감 예외처리

예외 블랙홀

이런 예외처리로 해왔는데..

따로 작업처리를 추가해 줘야된다..!

무의미하고 무책임한 throws

별로 의미없는 코드 나쁜습관이다..

예외의 종류와 특징

어떻게 예외를 다뤄야 될까?

ERROR

VM에서 발생시키는 에러이므로 굳이 안잡아도 된다.

Exception과 체크 예외

Exception 2가지로 체크 예외와 언체크 예외로 나뉜다.

전자는 Exception 서브 클래스 이면서 RuntimeException 클래스 상속 X
후자는 RuntimeException 클래스에 상속되는 친구들

전자는 좀 특별하게 다룸.

체크예외가 발생할 수 있는 메소드를 사용할 경우 반드시 예외처리를 하는 코드도 작성해야ㅑ됨

try/catch

RuntimeException과 언체크/런타입 예외

ERROR와 동일하게 굳이 catch나 throw로 선언하지 않아도 됨.

다시읽어볼 내용들 체크.

런타입 에러는 예쌍하지 못했던 예외상황에서 발생하는게 아님 굳이 catch나 throw를 사용 하지
않아도 되도록 만듬.

요즘은 가능한 예외상황을 다루는 예외를 체크 예외로 만들지 않는 경향임

예외처리 방법

예외 복구

예외처리 회피

드물게 사용함..

예외 전환

예외를 메소드 밖으로 던짐.

적절한 예외로 전환해서 던진다.

  1. 내부에서 발생한 예외를 그대로 던지는 것이 예외상황에 대한 적절한 의미를 부여해주지 못함
    의미를 분명하게 해줄 수 있는 예외로 바꿔주기 위해.ex) 사용자 등록 시도-> 같은 아이디가 잇음? SQL Exception 발생 이걸
    -> DuplicatetUserIIdException() 의미가 분명한 예외로 던지자.

중첩예외로 만들어도 좋음

주로 예외처리를 강제하는 체크 예외를 언체크 예외인 런타임 예외로 바꾸는 경우에 사용

대표적으로
EJBException

코드에서 로직상 예외조건이 발생할 경우 체크 예외를 사용하는것이 바람직 하다..

예외처리 전략

런타임 예외의 보편화

최근에는 예외를 체크 예외 대신 언체크 예외로 정의하는것이 일반화됨.?

add() 메소드의 예외처리

런타입 예외로 포장해 던져버리면 그 밖의 메소드들이 신경 쓰지 않게 해주는 편이 좋다.

런타임 에러로 처리하고 좀더 명확하게 에러를 표시해주기 위해 DuplicateUserIdException 날려준다.

런타임 예외를 일반화해서 사용하는 방법은 장점이 많음

사용할때 더 주의를 기울일 필요도 있음.
신경쓰지 않으면 예외상항을 충분히 고려하지 못하기 때문에.

애플리케이션 예외

런타임 예외 중심 전략 -> 낙관적인 예외처리 기법

복구할 수 있는 예외는 없다 가정 -> 어짜피 예외 생겨도 시스템 레벨에서 처리.

애플리케이션 자체의 로직에 의해 의도적 발생 및 반드시 catch 해서 무엇인가 조취하도록 하는 예외는 애플리케이션 예외라고 함.

SQLException은 어떻게 됐나?

스프링의 예외처리 전략 원칙

SQLExcption은 복구방법 X

필요없는 기계적인 throws 선언이 등장하도록 방치하지말고 가능한 빨리 언체크/런타임 예외로 전환해줘야된다.

JDBC는 모든 SQLExcption 런타임 예외인 DataAccessExcption으로 포장해서 던져줌.

예외전환

예외를 다른 것으로 바꿔서 던지는 예외 전환의 목적은 두 가지

  1. 런타임 예외로 포장해서 굳이 필요하지 않는 catch/throws를 줄여주는 것
  2. 로우레벨의 예외를 좀 더 의미 있고 추상하된 예외로 바꿔서 던져줌.

JDBC 경우 DataAccessExcption으로 SQLException을 포장해주면서 좀더 상세한 예외정보를 제공해줌

JDBC의 한계

연결 기능은 되지만 데이터를 엑세스 코드는 다 달라서 표준화되기 쉽지않음..?

유연한 코드를 보장해주지 못한다.

비표준 SQL

다양한 디비언어는 표준화되있지않는 코드를 제공한다.

해결방법은

DAO를 디비별로 만들거나

SQL을 외부로 독립시켜 바꿔 쓸 수 있게.

7장에서 좀더 자세히

호환성 없는 SQLException의 DB 에러 정보

디비마다 에러 종류와 원인도 제각각..

그래서 SQLExcption 하나에 모두 담아버림..

SQLExcption 하나에 모두 담아버리도록 설계

DB 에러코드 매핑을 통한 전환

SQLExcption의 비표준 에러코드와 SQL 상태정보에 대한 해결책을 알아보자.

DB 전용 에러코드가 더 정확한 정보이므로.

일관성이 유지된다.

해결방법:
DB별 에러코드를 참고해서 발생한 예외의 원인이 무엇인지 해석하는
기능을 만들어 주면 됨.

디비 종류 상관없이 동일한 상황에 일관된 예외를 전달해야 효과적임

스프링은 DataAccessExcption의 서브클래스로 세분화된 여러 예외클래스가
있다.

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

JdbcTemplate를 이용하면 JDBC에 발생하는 DB관련 예외는 거의 신경쓰지 않아도 됨

DAO 인터페이스와 DataAccessException 계층구조

DAO 인터페이스와 구현의 분리

DAO를 굳이 따로 만들어서 사용하는 이유는?

데이터 엑세스 로직을 담은 코드를 성격이 다른 코드에서 분리해놓기 위해

전략 패턴을 적용해 구현 방법 변경해서 사용할 수 있게만들기위해

데이터 엑세스기술로 DAO 구현을 전환하면 사용 못함.

구현기술마다 예외가 다르기 때문에 메소드의 선언이 달라짐.

다행히 JDO , Hibernate , JPA등 기술은 SQLException 같은 체크 예외 대신 런타임 예외 사용 throw 선언 안해줘도 됨..

데이터 액세스 예외 추상화와 DataAccessExcption 계층구조

스프링은 자바의 다양한 데이터 엑세스 기술 사용시
발생하는 예외를 추상화해 DataAccessException 계층구조에 정리해둠

JPA JDO 하이버네이트 처럼 오브젝트/엔티티 단위정보 업데이트는

낙관적인 락킹 발생할 수 있음.

같은 정보를 두명 이상의 사용자가 동시에 조회하고 순차적으로 업데이트 할때

뒤늦게 업데이트 한것이 먼저 업데이트 한것을 덮어쓰지않게 막아주는 기술

스프링의 예외 전환 방법을 적용하면 기술 상관없이 DataAccessException 의
서브클래스로 통일가능

기술에 독립적인 UserDao만들기

인터페이스 적용

테스트 보완

구체적으로 어떤예외가 발생했는지 확인해야된다.

DataAccessException 활용 시 주의사항

JDBC 경우 위와 같은 듀플리케이트 익셉션이 던져지지만

다른 JPA 나 하이버네이트같은경우 다른 예외가 발생 한다.

DB에러 코드를 해석하는 JDBC 와 달리 JPA나 하이버네이트 등 각 기술이 재정의한
예외를 가져와 DataAccessException 으로 변환함

예외를 세분화 하지 않음

정리

  1. 예외를 잡아서 아무런 조취를 취하지 않거나 의미 없는 throws 선언을 남발 X

  2. 예외는 복구하거나 예외처리 오브젝트로 의도적으로 전달하거나 적절한 예외로 전환

  3. 좀 더 의미 있는 예외로 변경하거나, 불필요한 catch/throws를 피하기 위해
    런타임 예외로 포장하는 두 가지 방법의 예외 전환이 있다.

  4. 복구할 수 없는 예외는 가능한 한 빨리 런타임 예외로 전환하는 것이 바람직하다.

  5. 애플리케이션의 로직을 담기 위한 예외느 체크 예외로 만든다.

  6. JDBC의 SQLExcption은 대부분 복구할 수 없는 예외이므로 런타임 예외로 포장해야 한다.

  7. SQLException의 에러 코드는 DB에 종속되기 때문에 DB에 독립적인 예외로 전환 될 필요가 있다.

  8. 스프링은 DataAccessException을 통해 DB에 독립적으로 적용 가능한 추상화된 런타임 예외 계층을 제공한다.

  9. DAO를 데이터 액세스 기술에서 독립시키려면 인터페이스 도입과 런타임 예외 전환,
    기술에 독립적인 추상화된 예외로 전환이 필요하다.

profile
어제의 나보다 한걸음 더

0개의 댓글