본문 바로가기
Spring

Spring API 예외처리 / ResponseEntitiy

by sehunbang 2024. 2. 19.

예외 처리를 따로 배우는 이유!

 

1. 웹 애플리케이션의 “예외”에 대하여 다시 한 번 인지할 필요가 있습니다.

 

2. 웹 애플리케이션에서의 에러를 Client와 Server 모두가 잘 알지 못하면, 서비스하는 환경에서 발생하는 에러에 대해서 제대로 대응 할 수가 없습니다.

 

3. AOP를 배웠던 만큼, 에러를 처리하는 것 역시 관심사를 분리해서 더 효율적으로 처리 할 수 있지 않을까 고민해보는 시간이 필요해서 입니다.

 

서버가 응답을 보낼 때 start-line에 있는 응답 코드를 보겠습니다. 응답 헤더에는 API 요청에 대한 상태코드를 함께 보냅니다.

 

Response 메시지 :

start-line (상태줄) : API 요청 결과 (상태 코드, 상태 텍스트)  // HTTP/1.1 404 Not Found

(복습)

200 성공

300 redirection

400 클라이언트 에러 // e.g request api 가 다를 경우

500 서버 에서 에러.....

 

이런 에러를 잘 표현 하기 위해서 srpring 에서는 

HttpStatus Emun 을 제공 해줍니다.

 

public enum HttpStatus {
    // 1xx Informational
    CONTINUE(100, Series.INFORMATIONAL, "Continue"),
    // ...

    // 2xx Success
    OK(200, Series.SUCCESSFUL, "OK"),
    CREATED(201, Series.SUCCESSFUL, "Created"),
    // ...

    // 3xx Redirection
    MULTIPLE_CHOICES(300, Series.REDIRECTION, "Multiple Choices"),
    MOVED_PERMANENTLY(301, Series.REDIRECTION, "Moved Permanently"),
    FOUND(302, Series.REDIRECTION, "Found"),
    // ...

    // --- 4xx Client Error ---
    BAD_REQUEST(400, Series.CLIENT_ERROR, "Bad Request"),
    UNAUTHORIZED(401, Series.CLIENT_ERROR, "Unauthorized"),
    PAYMENT_REQUIRED(402, Series.CLIENT_ERROR, "Payment Required"),
    FORBIDDEN(403, Series.CLIENT_ERROR, "Forbidden"),
    // ...


    // --- 5xx Server Error ---
    INTERNAL_SERVER_ERROR(500, Series.SERVER_ERROR, "Internal Server Error"),
    NOT_IMPLEMENTED(501, Series.SERVER_ERROR, "Not Implemented"),
    BAD_GATEWAY(502, Series.SERVER_ERROR, "Bad Gateway"),
// ...

 

주의 !

@Deplicated 가 있으면 더이상 허용 되지 않는 다는 뜻 입니다.

보통 버전이 업그레이드 되면서 필요 없어진 emun 들에 게 추가가 됩니다.

그래서 버젼 업 하면 사용하던게 안되는 상황이 발생합니다.

 

ResponseEntitiy

api 요청을 받을때 사용했습니다. 

하지만 api 응답을 할때도 사용이 가능 합니다.

 

Spring에서 제공하는 ResponseEntity 클래스를 사용해보겠습니다.

//

우선  객체 RestApiException 을 만듭니다.

@Getter
@AllArgsConstructor
public class RestApiException {
    private String errorMessage;
    private int statusCode;
}

 

 

@PostMapping("/folders")
public ResponseEntity<RestApiException> addFolders(@RequestBody FolderRequestDto folderRequestDto,
                                                   @AuthenticationPrincipal UserDetailsImpl userDetails) {
    try {
        List<String> folderNames = folderRequestDto.getFolderNames();

        folderService.addFolders(folderNames, userDetails.getUser());
        return new ResponseEntity<>(HttpStatus.OK);
    } catch(IllegalArgumentException ex) {
        RestApiException restApiException = new RestApiException(ex.getMessage(), HttpStatus.BAD_REQUEST.value());
        return new ResponseEntity<>(
                // HTTP body
                restApiException,
                // HTTP status code
                HttpStatus.BAD_REQUEST);
    }
}

 

성공 했을때 

return new ResponseEntity<>(HttpStatus.OK);

 

실패 했을때 

RestApiException restApiException = new RestApiException(ex.getMessage(), HttpStatus.BAD_REQUEST.value()); 

return new ResponseEntity<>( restApiExceptionHttpStatus.BAD_REQUEST);

 

 

restApiException  는 HTTP body 

HttpStatus.BAD_REQUEST  은 HTTP status code

 

이렇게 나뒤어서 응답을 내주는 것 을 볼 수 있습니다. 에러문구도 캐치하고,

그에 따라서 어느 부문에서 오류가 났는지 적어서 보내 줄 수 있습니다.

 

 

@ExceptionHandler 사용

@ExceptionHandler 는 Spring에서 예외처리를 위한 애너테이션

이 애너테이션은 특정 Controller에서 발생한 예외를 처리하기 위해 사용됩니다.

@ExceptionHandler 가 붙어있는 메서드는 Controller에서 예외가 발생했을 때 호출 되며, 해당 예외를 처리하는 로직을 담고 있습니다.

 

 

 

AOP를 이용한 예외처리 방식 ( try catch할 필요없음) 

 

 

@ExceptionHandler({IllegalArgumentException.class})
public ResponseEntity<RestApiException> handleException(IllegalArgumentException ex) {
    RestApiException restApiException = new RestApiException(ex.getMessage(), HttpStatus.BAD_REQUEST.value());
    return new ResponseEntity<>(
            restApiException,   // HTTP body
            HttpStatus.BAD_REQUEST  // HTTP status code
    );
}

 

 

 

p.s

에러가 있을때 클라 쪽에저