스프링 DB 1(김영한 강의) - 섹션 6 : 스프링과 문제 해결(예외처리, 반복)

섹션 목적 : 남은 예외 누수와 JDBC 반복 문제를 스프링을 통해 해결해보자

 

1. 체크예외와 인터페이스

   (1) 서비스 계층은 가급적 특정 기술에 의존하지 않고 순수하게 유지하는 것이 좋다

   (2) 이렇게 하려면, 서비스에서 SQLException에 대한 의존성을 제거해야 함. 어떻게 해야할까?

   (3) Repository가 던지는 SQLException 체크 예외를 런타임 예외로 바꿔서 서비스에 던지자

   (4) 이렇게 하면 서비스는 해당 예외를 무시할 수 있고 예외에 대한 의존도를 제거할 수 있다

 

2. 인터페이스 도입

   (1) MemberRepository라는 인터페이스를 만들어서 repository를 구현기술에 따라 쉽게 변경할 수 있도록 하자

   (2) 이렇게 하면 service는 MemberRepository 인터페이스에만 의존하면 되므로, MemberRepository의 구현기술이 변경되더라도 service는 코드를 그대로 유지할 수 있다

   (3) 그런데 만약 인터페이스 구현체에 체크 예외를 사용하려면 인터페이스부터 체크 예외가 선언되어 있어야함

   (4) 인터페이스부터 해당 예외에 종속적이게 되므로 인터페이스가 오염됨

   (5) 따라서, 런타임 예외로 바꾸자

 

3. 런타임 예외 적용

   (1) MemberRepository 인터페이스를 상속받아서, SQLException을 던지는 코드를 런타임 예외인 MyDbException으로 감싸서 밖으로 던지도록 바꾼다

   (2) 이렇게 하면 서비스는 이제 SQLException이 제거되어 의존하지 않고, MemberRepository 인터페이스에만 의존하게 됨

   (3) 체크 예외를 언체크 예외로 변경해서 다음과 같은 이점이 생겼다

      ① 인터페이스와 서비스에 순수성을 유지할 수 있게 되었음

      ② 데이터 접근 계층이 JDBC에서 JPA로 변경되더라도 서비스 계층의 코드는 변경할 필요가 없음

   (4) 그런데, 어떨 때는 서비스가 리포지토리에서 넘어오는 특정 예외에 대해 복구를 시도할 수 있다

   (5) 지금 방식은 항상 MyDbException만 넘어와서 예외를 구분할 수 없다

   (6) 그럼 어떻게 예외를 구분할 수 있을까?

 

4. 데이터 접근 예외 직접 만들기

   (1) 데이터를 DB에 저장할 때 같은 id가 DB에 있다면, DB는 오류코드를 반환하고 JDBC 드라이버는 해당 오류코드를 감싸서 SQLException을 던진다

   (2) 그래서 SQLException에는 DB가 제공하는 errorCode가 있음

   (3) 예를 들어 H2에서 키 중복 오류 에러코드는 23505이다(e.getErrorCode()를 통해 확인할 수 있음)

   (4) 이를 활용해서 만약 errorCode가 23505일 경우 리포지토리는 throw new MyDuplicateKeyException(e)를 던지도록 구현한다

   (5) 남은 문제

      ① errorCode는 DB마다 달라서 DB가 변경될 때마다 errorCode도 모두 변경해야함

      ② DB가 전달하는 오류는 수천가지가 있는데, 이를 다 런타임 예외로 재정의해서 바꿔야함

 

5. 스프링 예외 추상화 이해

   (1) 스프링은 그래서 데이터 접근 계층에 대한 수십개의 예외를 정리해서 제공함. 특정 기술에 종속적이지 않음

   (2) 그래서 서비스에서도 스프링이 제공하는 이 예외를 사용하면 됨

   (3) 스프링은 또한 DB별로 발생하는 오류코드에 따라 스프링이 정의한 예외로 변환해주는 변환기도 제공함

   (4) 따라서, 우리는 단지 exTranslator.translate("save", sql, e)를 사용하면 예외를 쉽게 변환할 수 있다

 

6. JDBC 반복문제 해결 - JDBC Template

   (1) 서비스는 순수해짐. 이제 repository의 반복 문제를 해결해보자

   (2) JDBC 반복 패턴

      ① 커넥션 조회, 동기화

      ② PreparedStatement 생성 및 파라미터 바인딩

      ③ 쿼리 실행

      ④ 결과 바인딩

      ⑤ 예외 발생시 예외 변환기 실행

      ⑥ 리소스 종료

   (3) 리포지토리의 메소드들은 모두 위와 같은 형태를 띄고 있음

   (4) 이런 반복을 템플릿 콜백패턴인 JDBC Template을 사용해서 해결함

   (5) JDBC Template은 트랜잭션을 위한 커넥션 동기화, 스프링 예외 변환기까지 자동으로 실행해줌


이펙티브 자바 - 아이템 7 : 다 쓴 객체 참조를 해제하라

- 스택을 배열로 구현한 코드를 예시로 보자

- pop() 메소드에서, size만 줄여줄 뿐 배열에 담겨있는 객체를 처리하지 않는다

- 이렇게 되면 이 배열에 쌓이는 객체는 가비지 컬렉터가 회수해가지 않기 때문에, 메모리 누수가 일어난다

- 따라서, 해당 참조를 다 썼을 때 null처리를 하면 된다

- pop() 메소드에서 element[size] = null 로 하면 메모리 누수가 발생하지 않는다

- 가장 좋은 참조 해제 방법은 참조를 담은 변수를 유효범위 밖으로 밀어내는 것이다

- null 처리는 자기 메모리를 직접 관리하는 클래일 때 사용한다


코테준비

1. 프로그래머스 - N으로 표현

- bottom-up 방식으로 주어진 숫자를 사용해가며 가장 최소의 경우를 구한다

 

2. 프로그래머스 - 정수 삼각형

- DP는 결국 완전탐색에서 중복된 계산을 한번 더 하지 않는 것일 뿐이다

- 주어진 문제를 완전탐색으로 먼저 풀고 중복된 계산을 cache배열을 이용해서 줄이자

 

3. 프로그래머스 - 사칙연산

- 완전 탐색으로 먼저 풀고 중복된 계산을 줄이는 방법으로 풀었다


오늘 하루도 고생했다!!! 계속 꾸준하게 나아가자

'TIL(Today I Learned)' 카테고리의 다른 글

2023.07.04  (0) 2023.07.04
2023.07.03  (0) 2023.07.03
2023.06.29  (0) 2023.06.30
2023.06.28  (0) 2023.06.29
2023.06.27  (0) 2023.06.27

+ Recent posts