Replies: 4 comments 2 replies
|
오 ! 강의 더 들으셨네요 수고하셨습니다 ~~ 👍 |
2 replies
|
수고하셨습니다! |
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.
체크 예외와 인터페이스
체크 예외와 인터페이스
-서비스 계층은 가급적 특정 구현 기술에 의존하지 않고, 순수하게 유지하는게 좋다. 이렇게 하려면 예외에 대한 의존도 함께 해결해야 한다.
인터페이스 도입
-인터페이스를 도입하면 MemberService는 MemberRepository 인터페이스만 의존하면 된다.
-이제 구현 기술을 변경하고 싶으면 DI 를 사용 MemberService 코드의 변경 없이 구현 기술 변경 가능하다.
**특정 기술에 종속되지 않은 순수한 인터페이스, 이 인터페이스 기반으로 특정 기술을 사용하는 구현체 만들면 된다.
체크 예외와 인터페이스
-기존에 이런 인터페이스를 만들지 않은 이유는 SQLException이 체크 예외이기 때문이다. 체크 예외를 사용하려면 인터페이스에도 해당 체크 예외가 선언 되어야 한다.
체크 예외 코드에 인터페이스 도입시 문제점
**인터페이스 메서드에 throws SQLException이 있는 것을 확인할 수 있다.
-인터페이스의 구현체가 체크 예외를 던지려면, 인터페이스 메서드에 먼저 체크 예외 던지는 부분이 선언 되어 있어야 한다.
그래야 구현 클래스의 메서드도 체크 예외를 던질 수 있다. (RepositoryV3 == RepositoryEx ==> throws SQLException 둘다 필요)
**구현 클래스의 메서드에 선언할 수 있는 예외는 부모 타입에서 던진 예외와 같거나 하위 타입이어야 한다.
인터페이스 메서드에 throws Exception 선언하면, 구현 클래스 메서드에 throws SQLException 가능하다. SQLException은 Exception 하위 타입이기 때문이다.
런타임 예외와 인터페이스
-인터페이스에 런타임 예외를 따로 선언하지 않아도 된다. 따라서 인터페이스가 특정 기술에 종속적일 필요가 없다.
MemberRepository 인터페이스
MyDbException 런타임 예외
**RuntimeException 상속 받음, MyDbException은 런타임 예외가 된다.
-MemberRepository 인터페이스를 구현한다.
**체크 예외를 런타임으로 변경해서 던지는게 이 코드 핵심
MemberServiceV4
-MemberRepository 인터페이스에 의존하도록 코드 변경된다.
-throws SQLException 부분이 제거된 것을 확인할 수 있다.
-순수한 서비스 완성
정리
-체크 예외를 런타임 예외로 변환하면서 인터페이스와 서비스 계층의 순수성을 유지할 수 있게 됐다.
-향후 다른 JDBC에서 다른 구현 기술로 변경해도, 서비스 계층의 코드를 변경하지 않고 유지 가능하다.
데이터 접근 예외 직접 만들기
-데이터를 DB에 저장할 때 같은 ID가 이미 데이터베이스에 저장되어 있다면, 데이터베이스는 오류 코드를 반환하고, 이 오류 코드를 받은 JDBC 드라이버는 SQLException 던진다. 그리고 SQLException 에는 데이터베이스가 제공 하는 errorCode가 들어있다.
-SQLException에 들어있는 오류 코드를 활용하기 위해 SQLException을 서비스 계층으로 던지게 되면, 서비스 계층이 SQLException 이라는 JDBC 기술에 의존하게 되면서, 지금까지 우리가 고민했던 서비스 계층의 순수성이 무너진다.
**이 문제를 해결하려면 리포지토리에 예외를 변환해서 던지면 된다. SQLException -> MyDuplicateKeyException
-기존에 사용했던 MyDbException을 상속 받아서 의미있는 계층을 형성한다. 이렇게 하면 데이터베이스 관련 예외라는 계층을 만들 수 있다.
-이름도 MyDuplicateKeyException으로 지었다. 이 예외는 데이터 중복의 경우에만 던져야 한다.
-이 예외는 직접 만들었기 때문에, JDBC나 JPA 같은 특정 기술에 종속적이지 않고, 이 예외를 사용하더라도 서비스 계층의 순수성을 유지할 수 있다.
**같은 ID 저장시, 중간에 예외를 잡아서 복구한 것이 확인된다.
정리
-SQL ErrorCode로 데이터베이스에 어떤 오류가 있는지 확인할 수 있었다.
-예외 변환을 통해 SQLException을 특정 기술에 의존하지 않는 직접 만든 예외인 MyDuplicateKeyException을 사용해서 문제를 복구, 서비스 계층의 순수성도 유지할 수 있었다.
남은 문제
=>SQL ErrorCode는 각각의 데이터베이스 마다 다르다. 데이터베이스가 변경될 때 마다 ErrorCode도 모두 변경해야하고 수십 수백가지 오류 코드에 맞는 예외를 지금처럼 다 만들어야 할까? 하는 문제가 발생한다.**
스프링 예외 추상화 이해
-스프링은 앞서 설명한 문제들을 해결하기 위해 데이터 접근과 관련된 예외를 추상화해서 제공한다.
-스프링은 데이터 접근 계층에 대한 수십 가지 예외를 정리해서 일관된 예외 계층을 제공한다.
-각각의 예외는 특정 기술에 종속적이지 않게 설계되어 있다. 따라서 서비스 계층에서도 스프링이 제공하는 예외를 사용하면 된다.
-JDBC나 JPA를 사용할 때 발생하는 예외를 스프링이 제공하는 예외로 변환해주는 역할도 스프링이 제공한다.
-예외의 최고 상위는 DataAccessException 이다. 런타임 예외를 상속 받았기 때문에 스프링이 제공하는 데이터 접근 계층의 모든 예외는 런타임 예외이다.
-DataAccessException은 크게 2가지로 구분한다. NonTransient 예외와 Transient 예외이다.
스프링이 제공하는 예외 변환기
-스프링은 데이터베이스에서 발생하는 오류 코드를 스프링이 정의한 예외로 자동으로 변환해주는 변환기를 제공한다.
SpringExceptionTranslatorTest
-translate() 메서드의 첫번째 파라미터는 읽을 수 있는 설명이고, 두번째는 실행한 sql 마지막은 발생된 SQLException을 전달하면 된다. 이렇게 하면 적절한 스프링 데이터 접근 계층의 예외로 변환해서 반환해준다.
-예제에서는 SQL 문법이 잘못되었으므로 BadSqlGrammerException 을 반환한다.
-눈에 보이는 반환 타입은 최상위 타입인 DataAccessException 이지만 실제로는 BadSqlGrammarExcetion 예외가 반환된다.
**BadSqlGrammarException은 최상위 타입인 DataAccessException을 상속 받아서 만들어진다.
-스프링 SQL 예외 변환기는 SQL ErrorCode를 이 파일에 대입해서 어떤 스프링 데이터 접근 예외로 전환해야 할지 찾아낸다.
정리
-스프링은 데이터 접근 계층에 대한 일관된 예외 추상화를 제공한다.
-스프링은 예외 변환기를 통해서 SQLException의 ErrorCode에 맞는 적절한 스프링 데이터 접근 예외로 변환해준다.
-만약 서비스, 컨트롤러 계층에서 예외 처리가 필요하면 특정 기술에 종속적인 SQLException 같은 예외를 직접 사용하는 것이 아니라, 스프링이 제공하는 데이터 접근 예외를 사용하면 된다.
-향후 JDBC에서 JPA로 구현 기술을 변경하더라도, 스프링은 JPA 예외를 적절한 스프링 데이터 접근 예외로 변환해준다.
-스프링이 제공하는 예외를 사용하기 때문에 스프링에 대한 기술 종속성은 발생한다.
스프링 예외 추상화 적용
MemberRepositoryV4_2
-스프링이 예외를 추상화해준 덕분에, 서비스 계층은 특정 리포지토리의 구현 기술과 예외에 종속적이지 않게 되었다. 추가로 서비스 계층에서 예외를 잡아서 복구해야 하는 경우, 예외가 스프링이 제공하는 데이터 접근 예외로 변경되어서 서비스 계층에 넘어오기 때문에 필요한 경우 예외를 잡아서 복구하면 된다.
JDBC 반복 문제해결 - JDBC Template
-JDBC 반복 문제 : 커넥션 조회, 커넥션 동기화, PreparedStatement 생성 및 파라미터 바인딩, 쿼리 실행, 결과 바인딩, 예외 발생시 스프링 예외 변환기 실행, 리소스 종료가 발생한다.
-리포지토리의 각각의 메서드를 살펴보면 많은 부분이 반복된다. 이런 반복을 효과적으로 처리하는 방법이 바로 템플릿 콜백 패턴이다. 스프링은 JDBC의 반복 문제를 해결하기 위해 JdbcTemplate 이라는 템플릿을 제공한다.
MemberRepositoryV5
**JdbcTemplate은 JDBC 개발할 때 발생하는 반복을 대부분 해결해 준다. 트랜잭션을 위한 커넥션 동기화는 물론이고, 예외 발생시 스프링 예외 변환기도 실행해준다.
정리
가) 트랜잭션 추상화 + 트랜잭션 AOP 덕분에 서비스 계층의 순수성을 최대한 유지하면서 서비스 계층에서 트랜잭션을 사용할 수 있다.
나) 스프링이 제공하는 예외 추상화와 예외 변환기 덕분에, 데이터 접근 기술이 변경되어도 서비스 계층의
순수성을 유지하면서 예외도 사용 할 수 있다.
다) 서비스 계층이 리포지토리 인터페이스에 의존한 덕분에 향후 리포지토리가 다른 구현 기술로 변경되어도
서비스 계층을 순수하게 유지 가능하다.
All reactions