3.5.3 템플릿/콜백의 응용
- 템플릿 / 콜백의 재설계
- 제네릭스를 이용한 콜백 인터페이스
제네릭스를 적용하여 다양한 오브젝트 타입을 지원하는 인터페이스나 메소드를 정의해 보자.
//타입 파라미터를 적용한 LineCallback
public inteface LineCallback<T> {
T doSomethingWithLine(String line, T value);
}
//타입 파라미터를 추가해서 제네릭 메소드로 만든 lineReadTemplate()
public <T> T lineReadTemplate(String filepath, LineCallback<T> callback, T initVal)
throws IOException {
...
}
3.7 정리
- JDBC와 같은 예외가 발생할 가능성이 있으며 공유 리소스의 반환이 필요한 코드는 반드시 try/catch/finally 블록으로 관리해야 ㅇ한다.
- 일정한 작업 흐름이 반복되면서 그중 일부 기능만 바뀌는 코드가 존재한다면 전략 패턴을 적용한다. 바뀌지 않는 부분은 컨텍스트로, 바뀌는 부분은 전략으로 만들고 인터페이스를 통해 유연하게 전략을 변경할 수 있도록 구성한다.
- 같은 애플리케이션 안에서 여러 가지 종류의 전략을 다이내믹하게 구성하고 사용해야 한다면 컨텍스트를 이용하는 클라이언트 메소드에서 직접 전략을 정의하고 제공하게 만든다.
- 클라이언트 메소드 안에 익명 내부 클래스를 사용해서 전략 오브젝트를 구현하면 코드도 간결해지고 메소드의 정보를 직접 사용할 수 있어서 편리하다.
- 컨텍스트가 하나 이상의 클라이언트 오브젝트에서 사용된다면 클래스를 분리해서 공유하도록 만든다.
- 컨텍스트는 별도의 빈으로 등록해서 DI 받거나 클라이언트 클래스에서 직접 생성해서 사용한다. 클래스 내부에서 컨텍스트를 사용할 때 컨텍스트가 의존하는 외부의 오브젝트가 잇다면 직접 DI 해줄 수 있다.
- 단일 전략 메소드를 갖는 전략 패턴이면서 익명 내부 클래스를 사용해서 매번 전략을 새로 만들어 사용하고, 컨텍스트 호출과 동시에 전략 DI를 수행하는 방식을 템플릿/콜백 패턴이라고 한다.
- 콜백의 코드에도 일정한 패턴이 반복된다면 콜백을 템플릿에 넣고 재활용하는 것이 편리하다.
- 템플릿과 콜백의 타입이 다양하게 바뀔 수 잇다면 제네릭스를 이용한다.
- 스프링은 JDBC 코드 작성을 위해 JdbcTemplate을 기반으로 하는 다양한 템플릿과 콜백을 제공한다.
- 템플릿은 한 번에 하나 이상의 콜백을 사용할 수도 있고, 하나의 콜백을 여러 번 호출할 수도 있다.
- 템플릿/콜백을 설계할 때는 템플릿과 콜백 사이에 주고받는 정보에 관심을 둬야 한다.
4장. 예외
4.1 사라진 SQLException
JdbcContext -> JdbcTemplate SQLException이 사라진 것을 볼 수 있다. 어디로 간 것 일까?
4.1.1 초난감 예외처리
- 예외 블랙홀
모든 예외는 적절하게 복구되든지 아니면 작업을 중단시키고 운영자 또는 개발자에게 분명하게 통보돼야 한다.
- 무의미하고 무책임한 throws
//매우 안 좋은 예외처리 방법의 예, 의미없는 예외 호출
public void method1() throws Exception {
method2();
}
public void method2() throws Exception {
method3();
}
public void method3() throws Exception {
...
}
4.1.2 예외의 종류와 특징
- Error
java.lang.Error 클래스의 서브클래스들이다. 에러는 시스템에 뭔가 비정상적인 상황이 발생했을 경우에 사용된다.
- Exception과 체크 예외
개발자들이 만든 애플리케이션 코드의 작업 중에 예외상황이 발생했을 경우에 사용
체크 예외 - Exception 클래스의 서브클래스이면서 RuntimeException 클래스를 상속하지 않을 것들
언체크 예외 - RuntimeException 클래스를 상송한 것들
일반적인 예외라고 보면 된다.
- RuntimeException과 언체크/런타임 예외
java.lang.RuntimeException 클래스를 상속한 예외들은 명시적인 예외처리를 강제하지 않기 때문에 언체크 예외라고 불린다.
4.1.3 예외처리 방법
- 예외 복구
예외상황을 파악하고 문제를 해결해서 정상 상태로 돌려놓는 것
- 예외처리 회피
예외처리를 자신이 담당하지 않고 자신을 호출한 쪽으로 던져버리는 것
- 예외 전환
예외를 메소드 밖으로 던지는 것, 예외 회피와 달리 발생한 예외를 그대로 넘기는 게 아니라 적절한 예외로 전환해서 던진다는 특징이 있다.
4.1.4 예외처리 전략
- 런타임 예외의 보편화
대응 불가능한 체크 예외라면 빨리 런타임 예외러 전환해서 던지는 게 낫다.
- add() 메소드의 예외처리
- 애플리케이션 예외
4.1.5 SQLException은 어떻게 됐나?
필요도 없는 기계적인 throws 선언이 등장하도록 방치하지 말고 가능한 한 빨리 언체크/런타임 예외로 전환해줘야 한다.
스프링의 JdbcTemplate은 바로 이 예외처리 전략을 따르고있다. JdbcTemplate 템플릿과 콜백 안에서 발생하는 모든 SQLException을 런타임 예외인 DataAccessException으로 포장해서 던져준다.
4.2 예외 전환
4.2.1 JDBC의 한계
- 비표준 SQL
- 호환성 없는 SQLException의 DB 에러 정보
4.3 정리
- 예외를 잡아서 아무런 조치를 취핮 ㅣ않거나 의미 없는 throws 선언을 남발하는 것은 위험하다.
- 예외는 복구하거나 예외처리 오브젝트로 의도적으로 전달하거나 적절한 예외로 전환해야한다.
- 좀 더 의미 있는 예외로 변경하거나, 불필요한 catch/throws를 피하기 위해 런타임 예외로 포장하는 두 가지 방법의 예외 전환이 있다.
- 복구할 수 없는 예외는 가능한 한 빨리 런타임 예외로 전환하는 것이 바람직하다.
- 애플리케이션의 로직을 담기 위한 예외는 체크 예외로 만든다.
- JDBC의 SQLException의 에러 코드는 DB에 종속되기 때문에 DB에 독립적인 예외로 전환될 필요가 있다.
- 스프링은 DataAccessException을 통해 DB에 독립적으로 적용 가능한 추상화된 런타임 예외 계층을 제공한다.
- DAO를 데이터 액세스 기술에서 독립시키려면 인터페이스 도입과 런타임 예외 전환, 기술에 독립적인 추상화된 예외로 전환이 필요하다.
5장. 서비스 추상화
5.1 사용자 레벨 관리 기능 추가
5.1.1 필드 추가
- Level enum
int 상수로 level을 정의해 줄 수는 있지만 다른 종류의 정보를 넣는 실수를 해도 컴파일러가 체크해주지 못하기 때문에 심각한 오류가 발생할 수 있다. enum을 사용해서 안전하고 편리하게 기능을 만들자.
- User 필드 추가
public class User {
...
Level level;
int login;
int recommend;
public Level getLevel() {
return level;
}
...
}
- UserDaoTest 테스트 수정
- UserDaoJdbc 수정
5.1.2 사용자 수정 기능 추가
- 수정 기능 테스트 추가
- UserDao와 UserDaoJdbc 수정
- 수정 테스트 보완
5.1.3 UserService.upgradeLevels()
- UserService 클래스와 빈 등록
- UserServiceTest 테스트 클래스
- UpgradeLevels() 메소드
- UpgradeLevels() 테스트
5.1.4 UserService.add()
사용자 관리에 대한 비즈니스 로직을 담고 있는 UserService에 사용자의 level을 basic으로 세팅해 주는 메소드를 만들자.
5.1.5 코드 개선
- upgradeLevels() 메소드 코드의 문제점
if else를 많이 사용하여 코드가 깔금하지 않음
- upgradeLevels() 리팩토링
1. swith를 사용하여 깔금하게 리팩토링하자.
2. 예외처리 기능을 만들어주자.
- User 테스트
- UserServiceTest 개선
5.2 트랜잭션 서비스 추상화
5.2.1 모 아니면 도
- 테스트용 UserService 대역
UserService를 상속해서 일부 메소드를 오버라이딩
대부분 private으로 되어 있기에 protected로 변경 <- 권장되는 방법은 아님, 이번만큼은 예외
'Spring-Boot' 카테고리의 다른 글
토비의 스프링 3.1 Vol.1 450p ~ 550p 정리 (0) | 2024.01.02 |
---|---|
토비의 스프링 3.1 Vol.1 350p ~ 450p 정리 (0) | 2023.12.31 |
토비의 스프링 3.1 Vol.1 145p ~ 250p 정리 (1) | 2023.12.28 |
토비의 스프링 3.1 Vol.1 40p ~ 143p 정리 (1) | 2023.12.28 |
실시간 시세 시스템아키텍처에 대한 고민, feat.토스증권 (0) | 2023.10.14 |