TIL | [Spring] 오류와 예외

6501 단어 TILSpringSpring

오류와 예외란?

자바에는 최상위 클래스 Object 아래 Throwable 클래스가 있고 그 아래 ErrorException 클래스가 존재한다. 그리고 Exception은 다시 CheckdException, UnCheckedException로 나눠진다.

Thorwoable
오류와 예외에 대한 자세한 메시지를 담고있는 최상위 클래스


오류(Error)프로그램의 코드로 처리할 수 없는 심각한 문제로 발생시 프로그램이 비정상 종료된다.

java.lang.Error의 패키지에 정의되며 시스템 레벨에서 발생하기에 프로그램 애플리케이션에서는 에러 처리를 할 수 없다.

대표적인 오류

  • StackOverflowError - 재귀가 반복되거나 호출의 깊이가 길어져 stack 영역 메모리 범위를 벗어날 때 던져지는 오류
  • OutOfMemotyError - JVM에서 할당된 메모리가 부족해 더 이상 객체를 할당할 수 없는 때 던져지는 오류

예외(Exception)프로그램 코드에 의해 수습될 수 있는 미약한 오류이다.

java.lang.Exception의 패키지에 정의되며 개발자의 코드 작업과 구현한 로직에서 문제가 있을 경우 발생한다.

언체크 예외 체크 예외

위에서도 언급했듯이 Exception체크 예외(CheckedException)언체크 예외(UncheckedException)로 다시 구분할 수 있다.

1. 언체크 예외(UncheckedException)

RuntimeException을 상속한 클래스라 런타임 예외라고 부르기도 한다. 자바에서 RuntimeException 클래스와 이를 상속한 클래스는 프로그램에 오류가 있을 때 발생하도록 의도된 오류이기에 IDE 등의 프로그램에서 예외 처리가 강요되지 않는다.

주로 프로그래머의 실수에 의해서 발생되는 오류로 컴파일에서는 문제되지 않으나 실행 단계에서 문제가 발생된다.

RuntimeException
자바 컴파일러가 처리할 필요가 없는 예외

  • NullPointerException - 할당되지 않은 객체 변수 사용시 발생
  • IllegalArgumentException - 허용되지 않은 파라미터로 메소드 호출시 발생

스프링에서는 @Transactional에서 Exception이 발생하면 rollback을시키고 Exception이 없다면 commit하게 되는데, 이때 rollback을 시키는 Exception은 정확히 말하자면 UncheckedException만 해당한다.

2. 체크 예외(CheckedException)

Exception클래스의 하위 클래스이면서 RuntimeException 클래스를 상속받지 않은 예외로 일반적 예외는 체크 예외를 뜻한다. RuntimeException 클래스를 상속받지 않았기에 IDE에서 예외 처리를 강요한다.

컴파일 단계에서 확인하기 때문에 예외 처리를 하지 않으면 컴파일 에러가 발생하게 된다. 보통 코드상의 문제라기 보다는 실행 상황상 구현 흐름상 발생할 수 있는 예외들로 사용자들에 의해 많이 발생한다.

예외 처리 방법

1. 예외 복구

Exception 상황을 파악한 후 문제를 해결해 정상 상태로 돌려놓은 것을 말한다.

예외 복구의 핵심은 Exception이 발생하여도 애플리케이션은 정상적으로 동작한다는 것이다.

Exception을 예측하여 다른 비지니스 로직으로 유도하거나, Exception이 발생하기 전의 상황으로 복구를 시도하는 로직을 추가하는 등의 방법이 있다.

2. 예외 회피

Exception이 발생하면 throws를 이용해 Exception 발생된 로직을 호출한 곳으로 Exception을 던져 버리는 방식이다.

주의할 점은 예외 복구처름 회피 또한 의도가 분명해야한다. 가령 호출 부분에서 Exception을 처리하는 것이 더 적합한 경우와 같이 Exception을 throw하는 것이 바람직하다고 확신이 드는 경우에 사용해야 한다.

3. 예외 전환

Exception 발생시 새로운 Exception으로 전환시키는 방식으로 예외 회피와 비슷하게 예외 복구로 정상적인 상태를 만들기 어려울 때 사용된다.

예외 회피와 다른 점은 발생한 Exception을 그냥 던지는 것이 아니라 어떤 Exception인지 더 분명한 의미를 부여할 수 있는 다른 Exception으로 던져줘야한다.

보통 CheckedException에서 예외 복구가 불가능할 때 Exception을 catch하여 UncheckedException으로 전환해 예외 처리를 단순화시키는 방법으로 사용된다.

스프링에서 예외 처리

위에서 CheckedException은 트랜잭션에서 rollback이 안된다고 하였다. 그렇기에 CheckedException은 Exception이 발생해도 트랜잭션이 작동되어 DB에 영향을 미치게 된다.

CheckedException은 기본적으로 try-catch문을 따르는데 대부분 스프링 서버단에서 마주하는 CheckedException은 catch라인에서 처리할 수 있는 것이 없다.

예를 들어 사용자가 입력한 키워드를 통해 DB 데이터를 요청하는데, 사용자가 어떤 값도 입력하지 않고 요청을 한다면 당연히 서버측에 오류가 발생하게 된다.

하지만 이런 경우 사실 사용자의 실수로 인한 오류이기 때문에 사용자에게 다시 키워드를 입력해 요청하도록 유도하는 방향으로 예외 처리하는 것이 좋다.

즉, UncheckedException을 재정의하여 코드의 흐름을 제어하는 것이 좋은 방법이다.

예시

  1. '키워드' 입력을 통해 검색을 시도
  2. 빈 칸을 입력해 서버에서 전달할 정보가 없어 Exception 발생
  3. 잘못된 입력이라는 것을 Client에 알리기 위해 RuntimeException을 재정의해 response(메시지) 내려주기

재정의 - RuntimeException 상속

public class NotExistKeywordException extends RuntimeException {
	private static final String MESSAGE = "입력된 값이 없습니다. 값을 입력해주세요.";
    public NotExistKeywordException ( String keyword ) { super(MESSAGE); }
}

재정의한 Exception 사용

private User findUserKeyword ( String keyword ) {
	return userRepository.findByKeyword(keyword).orElseThrow(
    	() -> new NotExistKeywordException(keyword));
}



[출처] Gadget-info
[출처] 토비의 스프링

좋은 웹페이지 즐겨찾기