[Spring Boot] Custom Exception 처리하기

wujin·2024년 2월 13일
post-thumbnail

애플리케이션을 개발할 때 예외 처리를 효과적으로 처리하는 것은 중요하다고 생각한다. 이를 통해 예외 상황에 대한 적절한 응답을 제공하고, 사용자 경험을 개선하며, 애플리케이션의 안정성을 높일 수 있다.

전역 예외 처리기를 통해 다양한 예외 상황을 처리하고, 사용자 정의 예외(Custom Exception)와 표준 예외에 대한 응답을 구성해보았다.

1. Custom Exception 클래스 정의

import lombok.Getter;

@Getter
public class CustomException extends RuntimeException {
    private final ErrorMessage errorMessage;

    public CustomException(ErrorMessage errorMessage) {
        super(errorMessage.getMessage());
        this.errorMessage = errorMessage;
    }

    public int getStatus() {
        return errorMessage.getStatus();
    }

    public String getCode() {
        return errorMessage.getCode();
    }

    public String getMessage() {
        return errorMessage.getMessage();
    }
}

위 코드에서 CustomException 클래스는 RuntimeException을 확장하며, ErrorMessage를 포함하여 사용자 정의 예외를 정의한다. 이를 통해 예외가 발생하면 사전에 정의된 상태 코드와 메시지를 반환할 수 있다.

2. ErrorMessage 정의

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum ErrorMessage {

    // 여기에 다양한 예외 유형과 메시지를 정의할 수 있다.
    INVALID_REQUEST(400, "ERR001", "잘못된 요청 형식입니다."),
    UNAUTHORIZED(401, "ERR002", "인가되지 않은 접근입니다."),
    // ...
    ORDER_NOT_FOUND(404, "ORDER001", "주문 정보를 찾을 수 없습니다."),
    INVALID_PAYMENT_TYPE(400, "ORDER002", "유효하지 않은 결제 유형입니다.");

    private final int status;
    private final String code;
    private final String message;

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

ErrorMessage는 예외의 상태 코드, 코드, 그리고 메시지를 정의한다. 각 열거 상수는 다양한 상황에 대한 예외를 포함한다.

3. GlobalExceptionHandler 정의

import kr.co.kcp.backendcoding.work.common.response.ErrorResponse;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.HttpStatus;
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 org.springframework.web.servlet.NoHandlerFoundException;
import java.nio.file.AccessDeniedException;
import java.util.stream.Collectors;

@RestControllerAdvice
public class GlobalExceptionHandler {

    // CustomException 처리기
    @ExceptionHandler(CustomException.class)
    public ResponseEntity<ErrorResponse> handleCustomException(CustomException e) {
        ErrorResponse errorResponse = ErrorResponse.builder()
                .status(e.getStatus())
                .code(e.getCode())
                .message(e.getMessage())
                .build();
        return new ResponseEntity<>(errorResponse, HttpStatus.valueOf(e.getStatus()));
    }

    // 유효성 검사 예외 처리기
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ErrorResponse> handleValidationExceptions(MethodArgumentNotValidException e) {
        // 유효성 검사 실패에 대한 메시지 생성
        String errorMessages = e.getBindingResult().getFieldErrors().stream()
                .map(fieldError -> fieldError.getField() + ": " + fieldError.getDefaultMessage())
                .collect(Collectors.joining(", "));

        ErrorResponse errorResponse = ErrorResponse.builder()
                .status(HttpStatus.BAD_REQUEST.value())
                .code("ERR_VALIDATION")
                .message("유효성 검사 오류: " + errorMessages)
                .build();

        return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
    }

    // ...
}

위의 GlobalExceptionHandler 클래스는 다양한 종류의 예외를 처리한다. @ExceptionHandler 어노테이션을 사용하여 각 예외 유형에 대한 처리기를 정의했다. 예를 들어, CustomException에 대한 처리기는 미리 정의된 상태 코드와 메시지를 반환한다.

4. ErrorResponse 클래스 정의

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;

@Getter
@AllArgsConstructor
@Builder
public class ErrorResponse {
    private final int status;
    private final String code;
    private final String message;
}

ErrorResponse 클래스는 예외가 발생했을 때 반환되는 응답을 정의한다. 이 클래스는 상태 코드, 코드, 그리고 메시지를 포함한다.

0개의 댓글