Replies: 2 comments
|
수고하셨습니다 ! |
0 replies
|
수고하셨습니다 !! |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
체크 예외와 인터페이스
SQLException에 대한 의존을 제거하려면 어떻게 해야할까?서비스가 처리할 수 없는 리포지토리가 던지는
SQLException체크 예외를 런타임 예외로 전환해서 서비스 계층에 던지자. 이렇게 하면 서비스 계층이 해당 예외를 무시할 수 있기 때문에 특정 구현 기술에 의존하는 부분을 제거하고 서비스 계층을 순수하게 유지할 수 있다.먼저 인터페이스를 도입한다.
‘MemberRepository’
SQLException는 체크 예외이기 때문에 사용하려면 인터페이스에도 해당 체크 예외가 선언되어 있어야 한다.체크 예외 코드에 인터페이스 도입시 문제점 : 인터페이스
throws SQLExceptrion이 있는 것을 확인할 수 있다.체크 예외 코드에 인터페이스 도입시 문제점 : 구현 클래스
인터페이스의 구현체가 체크 예외를 던지려면, 인터페이스 메서드에 먼저 체크 예외를 던지는 부분이 선언되어 있어야 한다. 그래야 구현 클래스의 메서드도 체크 예외를 던질 수 있다.
쉽게 얘기해 ‘MemberRepositoryV3’가 ‘throws SQLException’을 하려면 ‘MemberRepositoryEx’ 인터페이스에도 ‘throws SQLException’이 필요하다.
참고로 구현 클래스에메 메서드 선언할 수 있는 예외는 부모타입에서 던진 예외와 같거나 하위 타입이어야 한다.
SQLException은Exception의 하위 타입이기 때문이다.특정 기술에 종속되는 인터페이스
구현 기술을 쉽게 변경하기 위해서 인터페이스를 도입하더라도
SQLException과 같은 특정 구현 기술에 종속적인 체크 예외를 사용하게 되면 인터페이스에도 해당 예외를 포함해야 한다.하지만 이것은 우리가 원하던 순수 인터페이스가 아니다. JDBC 기술에 종속적인 인터페이스일 뿐이다. 인터페이스를 만드는 목적은 구현체를 쉽게 변경하기 위함인데 이미 인터페이스가 특정 구현 기술에 오염이 되어버렸다. 향후 JDBC가 아닌 다른 기술로 변경한다면 인터페이스 자체를 변경해야 한다.
“런타임 예외와 인터페이스”
런타임 예외는 이런 부분에서 자유롭다. 인터페이스에 런타임 예외를 따로 선언하지 않아도 된다.
따라서 인터페이스가 특정 기술에 종속적일 필요가 없다.
런타임 예외 적용
실제 코드에 런타임 예외를 사용하도록 적용해보자.
예외변환
MyDbException이 내부에 SQLException을 포함하고 있다고 이해하면 된다.다음과 같이 작성하면 안된다.
예외를 변환할때는 기존 예외를 꼭 포함하자. 장애가 발생하고 로그에서 진짜 원인이 남지 않는 심각한 문제가 발생할 수 있다.
정리
남은 문제
리포지토리에서 넘어오는 특정한 예외의 경우 복구를 시도할 수도 있다. 그런데 지금 방식은 항상
MyDbException이라는 예외만 넘어오기 때문에 예외를 구분할 수 없는 단점이 있다. 만약 특정 상황에서는 예외를 잡아서 복구하고 싶으면 예외를 어떻게 구분해서 처리할 수 있을까?데이터 접근 예외 직접 만들기
특정 예외는 복구처리하고 싶을 수 있다.
예) 회원가입시 DB에 이미 같은 ID가 있으면 ID 뒤에 숫자를 붙여 새로운 ID를 만들어야한다고 가정
데이터를 DB에 저장할때 같은 ID가 이미 데이터 베이스에 저장되어 있다면 데이터 베이스는 오류코드를 반환하고 이 오류코드를 받은 JDBC 드라이버는 SQLException을 던진다. 그리고 SQLException에는 데이터 베이스가 제공하는 errorCode라는것이 들어있다.
H2 데이터베이스의 키 중복 오류 코드
SQLException내부에 들어있는 errorCode를 활용하면 데이터 베이스에 어떤 문제가 발생했는지 확인할 수 있다.H2 데이터 베이스 ex
참고로 같은 오류여도 각각의 데이터 베이스 마다 정의된 오류코드가 다르다. 따라서 오류코드를 사용할때는 데이터 베이스 메뉴얼을 확인해야 한다.
ex) 키 중복 오류 코드
H2 데이터베이스 오류 코드 참고
서비스 계층에서는 예외 복구를 위해 키 중복 오류를 확인할 수 있어야 한다. 그래야 새로운 ID를 만들어서 다시 저장을 시도할 수 있기 대문이다. 이러한 과정이 바로 예외를 확인해서 복구하는 과정이다. 리포지토리는 SQLException을 서비스 계층에 던지고 서비스 계층은 이 예외의 오류코드를 확인해서 키 중복 오류(23505)인 경우 새로운 ID를 만들어서 다시 저장하면 된다.
그런데 SQLException에 들어있는 오류코드를 활용하기 위해 SQLException을 서비스 계층으로 던지게 되면 서비스 계층이 SQLException이라는 JDBC 기술에 의존하게 되면서 지금까지 우리가 고민했던 서비스 계층의 순수성이 무너진다.
이 문제를 해결하려면 앞서 배운 것처럼 리포지토리에서 예외를 변환해서 던지면 된다.
SQLException ⇒ MyDuplicateKeyException
먼저 필요한 예외를 만들어보자.
MyDuplicateKeyException
MyDbException을 던진다.MyDuplicateKeyException예외가 올라오면 이 예외를 잡는다.generatedNewId(memberId)로 새로운 ID생성을 시도한다. 그리고 다시 저장한다. 여기가 예외를 복구하는 부분이다.정리
MyDuplicateKeyException로 변환 할 수 있었다.MyDuplicateKeyException을 사용해서 문제를 복구하고, 서비스 계층의 순수성도 유지할 수 있었다.남은문제
MySQL: 1062All reactions