SpringBoot Exception 처리 :: BusinessException와 GlobalExceptionHandler

Jeong Choi(최현정)·2023년 5월 7일
0

SpringBoot

목록 보기
1/2

이 글은 SpringBoot에서의 exception 처리 흐름과 코드를 담고있습니다.

1. 비즈니스 레이어란?

SpringBoot에서 실질적으로 비즈니스 로직을 수행하는 레이어입니다. 주로 service 파일이 해당됩니다.

2. 비즈니스 로직이란?

SpringBoot service 내에서 처리되는 로직을 비즈니스 로직이라 합니다.

3. SpringBoot 에서의 예외 처리 흐름

1) 클라이언트가 작성한 데이터들을 @RequestBody와 같은 어노테이션을 통하여 Controller에 있는 API를 호출합니다.

2) Controller 에서 클라이언트의 데이터들을 아래와 같이 처리합니다.

  • 1) Controller에서 클라이언트가 보낸 데이터들에서 Exception이 발생하지 않은 경우 (-> Controller가 데이터들을 비즈니스 레이어로 전달)
1) 비즈니스 레이어에서 비즈니스 로직을 처리에서 Exception이 발생하지 않는 경우

	1. 비즈니스 로직을 수행한 return값을 Controller로 전달합니다.
   	2. Controller에서 클라이언트에게 비즈니스 로직이 성공적으로 수행되었다고 
    응답메세지(ResultCode)를 전송합니다.

2) 비즈니스 레이어에서 비즈니스 로직을 처리하는 와중 Exception이 발생한 경우
	
       1. 비즈니스 로직에서 Exception이 발생한 부분에 
	throw new [예외가 발생하는 클래스() --> BusinessException을 상속받은 클래스임)]를
	통해 Exception을 수행합니다.
	   2. 이에 GlobalExceptionHandler에 있는 
	@ExceptionHandler(BusinessExceptionHandler.class) 때문에 
    BusinessExceptionHandler에서 Exception을 catch합니다.
    	3. catch된 메소드가 실행이되면서 GlobalExceptionHandler에서
   구성한 응답 값을 구성하여 클라이언트에게 ErrorCode를 리턴합니다.
    
  • 2) Controller에서 클라이언트가 보낸 데이터들에서 Exception이 발생한 경우
1) 클라이언트의 데이터들이 비즈니스의 레이어로 가지 않고, 
@RestControllerAdvice가 있는 GlobalExceptionHandler에서 에러를 잡습니다. 

2) GlobalExceptionHandler에 있는 @ExceptionHandler 덕분에 에러를 발생시키지 않고
클라이언트에게 ErrorCode를 반환해줍니다.

3. 코드

1) 패키지 구조

2) GlobalExceptionHandler.java

package carrotTeam.carrot.global.error;

import carrotTeam.carrot.global.error.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import static carrotTeam.carrot.global.error.ErrorCode.INPUT_INVALID_VALUE;
import static org.springframework.http.HttpStatus.BAD_REQUEST;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(BusinessException.class)
    protected ResponseEntity<ErrorResponse> handleRuntimeException(BusinessException e) {
        final ErrorCode errorCode = e.getErrorCode();
        final ErrorResponse response =
                ErrorResponse.builder()
                        .errorMessage(errorCode.getMessage())
                        .businessCode(errorCode.getCode())
                        .build();
        log.warn(e.getMessage());
        return ResponseEntity.status(errorCode.getStatus()).body(response);
    }

    @ExceptionHandler
    protected ResponseEntity<ErrorResponse> handleMethodArgumentNotValidException(
            MethodArgumentNotValidException e) {
        final ErrorResponse response = ErrorResponse.of(INPUT_INVALID_VALUE, e.getBindingResult());
        log.warn(e.getMessage());
        return new ResponseEntity<>(response, BAD_REQUEST);
    }
}

3) BusinessException.java

package carrotTeam.carrot.global.error.exception;

import carrotTeam.carrot.global.error.ErrorCode;
import lombok.Getter;

@Getter
public class BusinessException extends RuntimeException{
    private final ErrorCode errorCode;

    public BusinessException(ErrorCode errorCode) {
        super(errorCode.getMessage());
        this.errorCode = errorCode;
    }
}
profile
Node와 DB를 사랑하는 백엔드 개발자입니다:)

0개의 댓글