비즈니스 로직에 대한 예외 처리

seongmin·2022년 10월 26일
0

Spring

목록 보기
25/38
post-thumbnail
  • 체크 예외는 말 그대로 발생한 예외를 잡아서(catch) 체크한 후에 해당 예외를 복구 하든가 아니면 회피 하든가 등의 어떤 구체적인 처리를 해야 하는 예외다.

    Java에서 흔히 볼 수 있는 대표적인 체크 예외로는 ClassNotFoundException 등을 들 수 있다.

  • 반면에 언체크 예외는 예외를 잡아서(catch) 해당 예외에 대한 어떤 처리를 할 필요가 없는 예외를 의미한다. 따라서 언체크 예외는 명시적으로 잡아서(catch) 어떤 처리를 할 필요가 없다.

    대표적인 언체크 예외로는 NullPointerException , ArrayIndexOutOfBoundsException 등이 있다.

    흔히 개발자가 코드를 잘못 작성해서 발생하는 이런 오류들은 모두 RuntimeException 을 상속한 예외들이다.

예외 throw/catch

  • 서비스 계층에서 예외 던지기
 @Service
public class MemberService {
    ...
		...

    public Member findMember(long memberId) {
        // TODO should business logic
				
				// (1)
        throw new RuntimeException("Not found member");
    }

		...
		... 
        
        }
  • 예외 잡기
@RestControllerAdvice
public class GlobalExceptionAdvice {
    ...
		...
		
		// (1)
    @ExceptionHandler
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ErrorResponse handleResourceNotFoundException(RuntimeException e) {
        System.out.println(e.getMessage());

        return null;
    }
}

사용자 정의 예외

  • 예외 코드 정의 예시
import lombok.Getter;

public enum ExceptionCode {
    MEMBER_NOT_FOUND(404, "Member Not Found");

    @Getter
    private int status;

    @Getter
    private String message;

    ExceptionCode(int status, String message) {
        this.status = status;
        this.message = message;
    }
}

서비스 계층에서 던질 Custom Exception에 사용할 ExceptionCode를 enum으로 정의한다.

이처럼 ExceptionCode를 enum으로 정의하면 비즈니스 로직에서 발생하는 다양한 유형의 예외를 enum에 추가해서 사용할 수 있다.

  • 서비스 계층에서 사용할 BusinessLogicException 이라는 Custom Exception을 정의
import lombok.Getter;

public class BusinessLogicException extends RuntimeException {
    @Getter
    private ExceptionCode exceptionCode;

    public BusinessLogicException(ExceptionCode exceptionCode) {
        super(exceptionCode.getMessage());
        this.exceptionCode = exceptionCode;
    }
}

BusinessLogicException 은 RuntimeException을 상속하고 있으며 ExceptionCode를 멤버 변수로 지정하여 생성자를 통해서 조금 더 구체적인 예외 정보들을 제공해줄 수 있다.

그리고 상위 클래스인 RuntimeException의 생성자(super)로 예외 메시지를 전달해준다.

BusinessLogicException 은 서비스 계층에서 개발자가 의도적으로 예외를 던져야 하는 다양한 상황에서 ExceptionCode 정보만 바꿔가며 던질 수 있다.

  • 서비스 계층에 BusinessLogicException 적용
@Service
public class MemberService {
    ...
		...

    public Member findMember(long memberId) {
        // TODO should business logic

				// (1)
        throw new BusinessLogicException(ExceptionCode.MEMBER_NOT_FOUND);
    }

    ...
		...
}
  • Exception Advice에서 BusinessLogicException 처리
@RestControllerAdvice
public class GlobalExceptionAdvice {
    ...
		...

    @ExceptionHandler
    public ResponseEntity handleBusinessLogicException(BusinessLogicException e) {
        System.out.println(e.getExceptionCode().getStatus());
        System.out.println(e.getMessage());

        return new ResponseEntity<>(HttpStatus.valueOf(e.getExceptionCode().getStatus()));
    }
}

@RestControllerAdvice에서 @ResponseStatus 와 ResponseEntity 의 사용 방법

한가지 유형으로 고정된 예외를 처리할 경우에는 @ResponseStatus 로 HttpStatus를 지정해서 사용하면 되고, BusinessLogicException 처럼 다양한 유형의 Custom Exception을 처리하고자 할 경우에는 ResponseEntity 를 사용하면 된다.

정리

  • 체크 예외(Checked Exception)는 예외를 잡아서(catch) 체크한 후에 해당 예외를 복구 하든가 아니면 회피를 하든가 등의 어떤 구체적인 처리를 해야하는 예외이다.

  • 언체크 예외(Unchecked Exception)는 예외를 잡아서(catch) 해당 예외에 대한 어떤 처리를 할 필요가 없는 예외를 의미한다.

  • RuntimeException을 상속한 예외는 모두 언체크 예외(Unchked Exception)이다.

  • RuntimeException을 상속해서 개발자가 직접 사용자 정의 예외(Custom Exception)를 만들 수 있다.

  • 사용자 정의 예외(Custom Exception)를 정의해서 서비스 계층의 비즈니스 로직에서 발생하는 다양한 예외를 던질 수 있고, 던져진 예외는 Exception Advice에서 처리할 수 있다.

  • @ResponseStatus 애너테이션은 고정된 예외를 처리할 경우에 사용할 수 있다.

  • HttpStatus가 동적으로 변경되는 경우에는 ResponseEntity 를 사용한다.

0개의 댓글