You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[Test worker] INFO hello.jdbc.exception.basic.CheckedTest - 예외 처리, message=ex
hello.jdbc.exception.basic.CheckedTest$MyCheckedException: ex
at hello.jdbc.exception.basic.CheckedTest$Repository.call(CheckedTest.java:64)
at hello.jdbc.exception.basic.CheckedTest$Service.callCatch(CheckedTest.java:45)
at hello.jdbc.exception.basic.CheckedTest.checked_catch(CheckedTest.java:14)
런타임 예외를 사용하면 중간에 기술이 변경되어도 해당 예외를 사용하지 않는 컨트롤러, 서비스에서는 코드를 변경하지 않아도 됨
구현 기술이 변경되는 경우, 예외를 공통으로 처리하는 곳에서는 예외에 따른 다른 처리가 필요할 수 있음
하지만 공통 처리하는 한곳만 변경하면 되기 때문에 변경의 영향 범위는 최소화 됨
런타임 예외는 문서화
런타임 예외는 문서화를 잘해야함
또는 코드에 throws 런타임예외를 남겨 중요한 예외를 인지할 수 있게해야함
JPA EntityManager
/** * Make an instance managed and persistent. * @param entity entity instance * @throws EntityExistsException if the entity already exists. * @throws IllegalArgumentException if the instance is not an * entity * @throws TransactionRequiredException if there is no transaction when * invoked on a container-managed entity manager of that is of type * <code>PersistenceContextType.TRANSACTION</code> */publicvoidpersist(Objectentity);
문서에 예외를 명시한 예시
스프링 JdbcTemplate
/** * Issue a single SQL execute, typically a DDL statement. * @param sql static SQL to execute * @throws DataAccessException if there is any problem */voidexecute(Stringsql) throwsDataAccessException;
method() throws DataAccessException 와 같이 문서화 + 코드에도 명시
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
5. 자바 예외 이해
#️⃣ 목차
예외 계층
예외 계층
ObjectObject이므로 예외의 최상위 부모도ObjectThrowableException과Error가 있음Errorcatch로 잡으면 그 하위 예외까지 함께 잡음Throwable예외도 잡으면 안되는데, 앞서 말한Error예외도 함께 잡을 수 있기 때문임. 애플리케이션 로직은 이런 이유로Exception부터 필요한 예외로 생각하고 잡으면 됨Error도 언체크 예외임Exception: 체크 예외Exception과 그 하위 예외는 모두 컴파일러가 체크하는 체크 예외임. 단,RuntimeException은 예외로 함RuntimeException: 언체크 예외, 런타임 예외RuntimeException과 그 자식 예외는 모두 언체크 예외임RuntimeException의 이름을 따라서RuntimeException과 그 하위 언체크 예외를 런타임 예외라고 많이 부름예외 기본 규칙
예외에 대해서는 2가지 기본 규칙을 기억해야 함
참고 - 예외를 처리하지 못하고 계속 던지면 어떻게 될까?
main()쓰레드의 경우 예외 로그를 출력하면서 시스템이 종료됨체크 예외 기본 이해
Exception과 그 하위 예외는 모두 컴파일러가 체크하는 예외RuntimeException은 예외로 함체크 예외 전체 코드 - CheckedTest
예외를 처리하는 테스트
실행순서 분석
test(checked_catch)->service.callCatch()->repository.call()(예외 발생하고, 예외를 던짐)test(checked_catch)<-service.callCatch()(catch로 예외 처리) <-repository.call()test(checked_catch)(정상 흐름) <-service.callCatch()<-repository.call()실행결과
e)예외를 처리하지 않고 밖으로 던지는 테스트
실행순서 분석
test(checked_throw)->service.callThrow()->repository.call()(예외 발생하고, 예외를 던짐)test(checked_throw)<-service.callThrow()(예외 던짐) <-repository.call()test(checked_throw)(예외 도착) ->service.callThrow()->repository.call()체크 예외의 장단점
체크 예외는 예외를 잡아서 처리할 수 없을 때, 예외를 밖으로 던지는
throws 예외를 필수로 선언해야 함. 그렇지 않으면 컴파일 오류가 발생함언체크 예외 기본 이해
RuntimeException과 하위 예외는 언체크 예외throws를 선언하지 않고 생략할 수 있다는 점체크 예외 vs 언체크 예외
throws에 던지는 예외를 선언해야 함throws를 생략할 수 있음언체크 예외 - UncheckedTest
언체크 예외의 장단점
언체크 예외는 예외를 잡아서 처리할 수 없을 때, 예외를 밖으로 던지는
throws 예외를 생략할 수 있음throws 예외를 선언해야 하지만, 언체크 예외는 이 부분을 생략 가능체크 예외 활용
언제 체크 예외를 사용하고 언제 언체크(런타임)예외를 사용하는가?
체크 예외의 문제점
method() throws 예외로 선언해야 함SQLException체크 예외를 던짐NetworkClient는 외부 네트워크에 접속해서 어떤 기능을 처리하는 객체 ->ConnectException체크 예외를 던짐NetworkClient를 둘 다 호출함SQLException과ConnectionException을 처리해야 함ConnectException처럼 연결이 실패하거나,SQLException처럼 데이터베이스에서 발생하는 문제처럼 심각한 문제들은 대부분 애플리케이션 로직에서 처리할 방법이 XSQLException과ConnectException를 처리할 수 없으므로 둘 다 밖으로 던짐method() throws SQLException, ConnectExceptionmethod() throws SQLException, ConnectExceptionControllerAdvice에서 이런 예외를 공통으로 처리함체크 예외 문제점 - CheckedAppTest
2가지 문제 존재
1. 복구 불가능한 예외
SQLException을 예로 들자면, 데이터베이스에 무언가 문제가 있어서 발생하는 예외로 복구가 불가능함ControllerAdvice를 사용하면 이런 부분을 깔끔하게 공통으로 해결 가능함2. 의존 관계에 대한 문제
throws를 통해 던지는 예외를 선언해야 하는 문제체크 예외 throws 선언
java.sql.SQLException을 의존하기 때문에 문제가 됨SQLException이 아니라 예를 들어서JPAException으로 예외가 변경된다면 어떻게 될까?SQLException에 의존하던 모든 서비스, 컨트롤러의 코드를JPAException에 의존하도록 고쳐야 함체크 예외 구현 기술 변경시 파급 효과
logic() throws SQLException->logic() throws JPAException정리
throws Exception
SQLException,ConnectException같은 시스템 예외는 컨트롤러나 서비스에서 대부분 복구가 불가능하고 처리할 수 없는 체크 예외임. 따라서 다음과 같이 처리함그런데 최상위 예외인
Exception을 던져도 문제를 해결할 수 있음Exception은 최상위 타입이라 모든 체크 예외를 다 밖으로 던지데 죔언체크 예외 활용
런타입 예외 사용
SQLException을 런타임 예외인RuntimeSQLException으로 변환함ConnectException대신에RuntimeConnectException으로 변환함런타임 예외 사용 변환 - UncheckedAppTest
예외 전환
SQLException이 발생하면 런타임 예외인RuntimeSQLException으로 전환해서 예외를 던짐NetworkClient는 단순히 기존 체크 예외를RuntimeConnectException이라는 런타임 예외가 발생하도록 코드를 바꿈런타임 예외 - 대부분 복구 불가능한 예외
시스템에서 발생한 예외는 대부분 복구 불가능한 예외임. 런타임 예외를 사용하면 서비스나 컨트롤러가 이런 복구 불가능한 예외를 신경쓰지 않아도 됨. 물론 이렇게 복구 불가능한 예외는 일관성 있게 공통으로 처리해야 함
런타임 예외 - 의존 관계에 대한 문제
런타임 예외는 해당 객체가 처리할 수 없는 예외는 무시하면 됨
런타임 예외 throws 생략
런타임 예외 구현 기술 변경시 파급 효과
런타임 예외는 문서화
throws 런타임예외를 남겨 중요한 예외를 인지할 수 있게해야함JPA EntityManager
스프링 JdbcTemplate
method() throws DataAccessException와 같이 문서화 + 코드에도 명시예외 포함과 스택 트레이스
예외를 전환할 때는 꼭 기존 예외를 포함해야 함
log.info("message={}", "message", ex)log.info("ex", ex)System.out에 스택 트레이스를 출력하려면e.printStackTrace()를 사용하면 됨기존 예외를 포함하는 경우
java.sql.SQLException과 스택 트레이스를 확인할 수 있음기존 예외를 포함하지 않는 경우
java.sql.SQLException과 스택 트레이스를 확인할 수 없음RuntimeSQLException부터 예외를 확인할 수 있음예외를 전환할 때는 꼭 기존 예외 포함하기!
🔗 출처
All reactions