클라이언트에게 데이터만 반환하는 것이 아니라
상태 코드도 함께 반환하고 싶을 때 어떻게 할까?
대표적인 방법 두 가지
- 반환 타입으로 ResponseEntity<>를 사용하기
- @RestControllerAdvice와 @ControllerAdvice 어노테이션을 사용하기
ResponseEntity<>
HTTP 응답을 나타내는 클래스(REST API의 응답을 위해 사용하는 클래스)로
클라이언트에게 응답의 상태코드, 헤더, 바디(body)를 포함하여 반환한다.
각 응답할 데이터는
- status() - 상태코드 작성 공간
- header() - 헤더 작성 공간
- body() - 바디 작성 공간
를 사용해서 상태코드, 헤더, 바디를 반환한다.
status() 안에 상태 코드를 작성할 때 HttpStatus를 사용하게 된다.
HttpsStatus는
HTTP 응답의 상태 코드를 관리하는 클래스로, 다양한 Enum 타입과 관련한 메서드를 가지고 있다.
일반적으로 사용되는 몇 가지 HttpStatus의 상수 정리
- HttpStatus.OK = 200 OK
- HttpStatus.CREATED = 201 Created
- HttpStatus.NO_CONTENT = 204 No Content
- HttpStatus.BAD_REQUEST = 400 Bad Request
- HttpStatusUNAUTHORIZED = 401 Unauthorized
- HttpStatus.FORBIDDEN = 403 Forbidden
- HttpStatus.NOT_FOUND = 404 Not Found
- HttpStatus.INTERNAL_SERVER_ERROR = 500 Internal Server Error
예시 코드
public ResponseEntity<testDto> Aupdate(...) {
...
if(...){
return ResponseEntity.status(HttpStatus.OK).body(testDto);
}
...
}
HttpsStatus.OK는 상태 코드 200을 의미하므로
상태코드 200과 testDto의 데이터를 body에 JSON으로 전송하게 된다.
만약 값이 잘못 되어 데이터를 반환하지 말고 상태 코드만 반환해야 한다면
public ResponseEntity<testDto> Aupdate(...) {
...
if(...){
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
}
...
}
HttpsStatus를 BAD(상태 코드 400)으로 반환하고 body에는 null로 데이터를 반환하지 않는다.
@RestControllerAdvice와 @ControllerAdvice
@RestControllerAdvice와 @ControllerAdvice는 모두
스프링에서 전역으로 예외 처리를 담당하는 클래스에 붙이는 어노테이션으로
여러 컨트롤러에 대해 전역적으로 @ExceptionHandler를 적용해준다.
@ExceptionHandler를 사용하면
value로 원하는 예외를 지정할 수 있고 해당 에러를 핸들링 할 수 있다.
그래서 해당 예외에 대해 세부적인 정보를 응답으로 반환할 수 있다.
(상태코드, 헤더, 바디)
@ControllerAdvice 사용 예제
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ResponseEntity<String> handleException(Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("An internal server error occurred");
}
}
@RestControllerAdvice 사용 예제
@RestControllerAdvice
public class GlobalRestExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ResponseEntity<String> handleException(Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("An internal server error occurred");
}
}
이렇게 둘 모두 사용 방법은 동일하다.
따로 전역으로 예외 처리를 담당하는 클래스를 만들고
해당 클래스에 @RestControllerAdvice 또는 @ControllerAdvice 어노테이션을 붙여준다.
@ExceptionHandler 어노테이션은
특정 예외 타입이 발생하면 처리하는 메서드를 지정해준다.
즉, 특정 예외가 발생하면 해당 메서드를 호출하게 된다.
@ResponseStatus 어노테이션은
해당 메서드가 처리하는 예외에 대한 HTTP 응답 상태 코드를 지정해준다.
그리고 @ExceptionHandler와 함께 사용하게 되면
특정 예외가 발생했을 때 해당 메서드에서 지정한 상태 코드로 응답을 반환한다.
호출되는 메서드의 반환값은 상태코드도 반환을 해줘야 하기때문에 반환 타입을 ResponseEntity를 사용하고
상태 코드, 헤더, 바디 등을 반환하면 된다.
위의 코드 해석
- Exception 예외 발생
- @RestControllerAdvice 또는 @ControllerAdvice가 적용된 클래스 Global...클래스 동작
- Exception 예외가 발생하면 호출되어야 하는 메서드를 @ExceptionHandler 어노테이션을 통해서 찾음
- handleException 메서드를 수행해서 상태코드, 헤더, 바디를 반환한다.
+
만약 @ResponseStatus에서 작성한 상태 코드와 return에 작성한 ResponseEntity.status의 상태코드를 다르게 작성하면?
@ResponseStatus에 지정된 HTTP 응답 상태 코드가 우선으로 적용된다.
(즉, ResponseEntity.status에 작성한 상태 코드는 무시된다.)
@ResponseStatus 어노테이션을 적용하지 않았다면,
메서드에서 반환하는 ResponseEntity 객체가 전체 응답을 결정하게 된다.
(즉, @ResponseStatus를 사용하지 않았다면 return에 작성한 상태코드가 반환된다.)
@RestControllerAdvice와 @ControllerAdvice의 차이점
@ControllerAdvice는
주로 MVC 컨트롤러의 View 기반에서 사용된다.
메서드가 반환하는 값이 주로 View를 나타내는 것이 일반적이며,
ModelAndView 같은 객체를 반환할 수 있다.
@RestControllerAdvice는
@ControllerAdvice에 @ResponseBody가 추가된 어노테이션이다. (다른 것들도 추가가 되어있다.)
그래서 응답(반환)을 할 때 주로 JSON형식으로 전달하게 된다.
주로 Restful 웹 서비스에서 사용된다.
메서드가 반환하는 값이 주로 HTTP 응답 본문(body)을 나타내는 것이 일반적이며,
ResponseEntity 같은 객체를 반환할 수 있다.
정리
- @ControllerAdvice는 View를 반환하는 전통적인 MVC 애플리케이션에서 사용
- @RestControllerAdvice는 RESTful API에서 JSON 또는 XML 형식의 데이터를 반환할 때 사용
ResponseEntity와 RestControllerAdvice(ControllerAdvice)의 장단점
ResponseEntity
장점
- 특정 예외 처리에 대해 세부적으로 지정해줄 수 있다.
즉, 예외 발생시 상태 코드, 헤더, 바디 등 세밀하게 조작할 수가 있다. - 반환을 할 떄 다양한 반환 타입을 지원하기 때문에 때에 따라서 반환 타입을 객체, 컬렉션, 파일 등을 포함한 형태의 응답을 생성할 수 있다.
단점
- 예외 처리를 해줘야 하는 상황이 있을 때마다 매번 코드를 작성을 해줘야 한다.
그러다 보면 코드 수가 길어지고 코드의 가독성이 떨어지게 된다. - 매번 코드를 작성해야 하다 보니 반복적인 코드를 작성하게 된다.
@RestControllerAdvice(@ControllerAdvice)
장점
- 특정 예외 처리를 전역적으로 지정을 해줘서 코드의 중복을 방지하고 유지보수성이 좋아진다.
즉, 전역적으로 예외 처리를 지정해주다 보니 한 번만 작성하면 해당 예외가 발생시 자동으로 처리가 된다. - 매번 같은 코드를 작성하는 것이 아닌 적역적으로 하나의 코드만 작성하니 가독성이 좋아진다.
단점
- 특정 예외 처리를 한 코드로 전역으로 적용하다 보니 일반화된 로직으로 처리하게 된다.
즉, 해당 예외에 대해 모두 동일한 방식으로 처리가 되어서 상황에 알맞게 세밀한 처리가 어려워 진다.
정리
- ResponseEntity는 세밀한 제어가 필요한 경우에 유용
- @RestControllerAdvice는 간단하고 효율적으로 예외 처리를 관리할 때 유용
'Spring Boot' 카테고리의 다른 글
Spring Security에 대해서 (0) | 2024.04.18 |
---|---|
자동으로 데이터의 생성일, 수정일, 생성자, 수정자 저장하기 (Auditing) (0) | 2024.01.22 |
application.yaml에 작성한 내용 설명 (0) | 2023.12.22 |
서버 정지할 때 Build cancelled while executing task 에러 해결하기 (0) | 2023.12.18 |
Spring Boot 프로젝트에서 build.gradle 파일 역할 (0) | 2023.12.13 |