들어가며,
DB에 접근하며 데이터를 저장하고 호출하는 과정에서 수많은 예외가 발생합니다.
개발자는 발생할 수 있는 예외에 대해 미리 지정하여 안정적으로 어플리케이션이 동작할 수 있도록 처리해야 합니다.
예외 계층
예외 종류
체크 예외 :
- SQLException: 데이터베이스에 대한 SQL 쿼리 수행 중 문제가 발생한 경우.
- IOException: 데이터베이스 연결 또는 파일 입출력과 관련된 문제가 발생한 경우.
언체크 예외 : 프로그램 실행 중에 발생할 수있는 예외
- NullPointerException (NPE): 객체 참조가 없는 상태에서 메소드를 호출할 때
- IllegalArgumentException: 메소드에 전달된 인수가 잘못된 경우
예외 규칙
기본적인 MVC 구조에서 예외는 Repository에서 발생하게 되며, 예외는 Repository를 호출한 Service에서 처리를 하거나 다시 던지거나 선택을 할 수 있습니다.
처리를 하는 것은 Catch로 잡고 던질 경우에는 Throw로 던지면 됩니다.
Catch
@Test
void checked_catch() {
Service service = new Service();
service.callCatch();
static class MyCheckedException extends Exception {
public MycheckedException(String message) {
super(message);
}
}
public void callCatch() {
try {
repository.call();
} catch (MyCheckedException e) {
log.info("예외 처리, message={}", e.getMessage(), e);
}
}
static class Repository {
public void call() throw MyCheckedException {
throw new MyCheckedException("ex");
}
}
}
catch(MycheckedException e)를 통해 MycheckedException 예외를 잡아 처리하는 Test를 진행했습니다.
해당 예외 처리에서는 log.info를 통해 예외에 대한 정보를 기록하게 됩니다.
Throw
@Test
void checked_throw() {
Service service = new Service();
assertThatThrowBy(() -> service.callThrow())
.isInstanceOf(MyCheckedException.class);
}
static class MyCheckedException extends Exception {
public MyCheckedException (String message) {
super(message);
}
}
static class Service {
Repository repository = new Repository();
public void callThrow() throws MyCheckedException {
repository.call();
}
}
static class Repository {
public void call() throws My checkedException {
throw new MyCheckedException("ex");
}
}
}
예외를 던지는 경우, assertj의 메서드를 통해 예외를 검증했습니다.
() -> service.callThrow()는 해당 메서드를 호출하는 람다식을 정의합니다.
.isInstanceOf(MyCheckedException.class)에서는 ()안의 예외 유형의 인스턴스와 같은지 검증하게 됩니다.
따라서 service에서 호출한 callThrow 메서드의 결과가 MycheckedException의 인스턴스와 같아야만 테스트가 성공합니다.
체크 예외와 언체크 예외 비교
체크 예외에서는 반드시 던지거나 처리를 해야만 했습니다. 그렇지 않을 경우 시스템이 종료되는 문제가 발생하기 때문입니다. 반면, 언체크 예외는 컴파일러가 예외를 체크하지 않기 때문에 생략이 가능합니다. 생략할 경우에는 자동으로 예외를 던지게 됩니다.
실제 적용 시에는?
기본적으로 언체크 예외를 사용하는 것이 좋습니다. 체크 예외는 비즈니스 로직상 의도적으로 던지는 경우에만 사용하는 것이 좋습니다.
상위 트리에 있는 Exception을 던지면?
결론을 먼저 말하면 throws Exception을 통해 모든 예외를 던지는 방법은 선택해서는 안됩니다. 앞서 실제 적용 시에 체크 예외는 의도적으로 던지는 경우에 사용하는 것이 좋은데, 모든 예외를 던지게 되면 어떤 예외를 잡고 던지는 것인지 불명확해지기 때문입니다.
기존 예외를 포함한 후 스택 트레이스 출력
로그를 출력할 때 마지막 파라미터에 기존 예외를 꼭 포함해야 한다.
log.info("message={}", "message", ex)` , 여기에서 마지막에 `ex` 를 전달하는 것을 확인할 수 있다.
'DB(MySQL, MongoDB, Redis, Kafka) > JDBC,JPA, Querydsl' 카테고리의 다른 글
SQL Mapper : Jdbc Template의 이해 (0) | 2024.01.14 |
---|---|
Connection Pool과 Data Source의 이해 (0) | 2024.01.13 |
JDBC의 이해, JDBC란? 개념 (1) | 2024.01.13 |