HTTP Status Code 제어 및 Exception Handling
HTTP Status Code 제어
이번 포스팅에서는 Spring Boot에서는 Http Status Code
를 어떻게 제어하는지와 Exception Handling
을 어떻게 했는지에 대해 공부한 내용을 정리해보려 한다.
User Controller
유저를 만드는 기능을 하는 POST 방식의 메소드가 하나 있다.
@PostMapping("/users")
public ResponseEntity<User> createUser(@RequestBody User user) {
User createdUser = service.save(user);
URI location = ServletUriComponentsBuilder.fromCurrentRequest()
.path("/{id}")
.buildAndExpand(createdUser.getId())
.toUri();
return ResponseEntity.created(location).build();
}
UriComponentsBuilder
클래스를 상속하는 ServletUriComponentsBuilder
클래스는 UriComponentBuilder
클래스의 정적 팩토리 메소드와 더불어 추가적인 메소드를 제공한다.
ServletUriComponentsBuilder
의 fromCurrentRequest
메소드에서 문서에 따르면 HttpServeltRequest
의 scheme, host, port, path, and quertstring
을 복사해서 빌더를 전달한다.
다음으로 path
메소드를 통해서 경로를 지정해주고 buildAndExpand
메소드에서 UriComponents
인스턴스를 빌드하고 전달된 인자 값으로 URI의 템플릿 변수로 대체한다.
마지막으로 toUri
메소드까지 실행되면 location
에 결과로 사용될 URI가 들어간다.
마지막으로 상태코드는 ResponseEntity
를 이용해 created(201)
에 location
을 포함해서 반환한다.
결과 이미지를 보면 201코드와 location
이 잘 전달되서 반환됐다.
HTTP Status Code 제어를 위한 Exception Handling
필자가 여태까지 사용해오던 Node.js환경의 Express프레임워크에서도 특정 Http Status Code의 경우를 핸들링하기 위한 방법들이 존재했다. 그리고 분명 실무에서 이 특정 상태 코드를 캐치해서 핸들링해야할 상황이 발생한다. 그래서 Spring Boot에서 특정 상태 코드를 핸들링하는 방법을 알아봤다.
프로젝트 루트레벨에 먼저 exception이란 이름으로 패키지를 생성했다.
ExceptionResponse.class
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ExceptionResponse {
private Date timestamp; // Exception 발생 시간
private String message; // 메세지
private String details; // 상세 메세지
}
Exception
이 발생했을 때 반환할 필드를 가진 ExceptionResponse class
를 생성한다.
다음으로 일반화된 에러를 처리하기 위한 핸들러 클래스를 생성한다.
CustomizeResponseEntityExceptionHandler.java
@RestController
@ControllerAdvice
public class CustomizeResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(Exception.class)
// 모든 예외를 처리하는 일반화된 Exception
public final ResponseEntity<Object> handleAllExceptions(Exception ex, WebRequest request) {
ExceptionResponse res = new ExceptionResponse(new Date(), ex.getMessage(), request.getDescription(false));
return new ResponseEntity(res, HttpStatus.INTERNAL_SERVER_ERROR);
}
@ExceptionHandler(UserNotFoundException.class)
// 404 Not Found Exception
public final ResponseEntity<Object> handleUserNotFoundException(Exception ex, WebRequest request) {
ExceptionResponse res = new ExceptionResponse(new Date(), ex.getMessage(), request.getDescription(false));
return new ResponseEntity(res, HttpStatus.NOT_FOUND);
}
...
}
모든 에러를 처리하는 handleAllException
에서는 현재 시간과 전달받은 기본 메세지와 내부 서버 에러를 뜻하는 500에러를 전달한다.
그리고 특정 404코드의 경우를 핸들링 하기 위해 UserNotFoundException class
를 생성한다.
class 상단에 ResponseCode를 Not Found를 의미하는 400으로 등록해둔다.
위 코드에서 handleUserNotFoundException
메소드는 ExceptionHandler
로 UserNotFoundException Class
로 등록해둬서 404일 경우 실행된다.
@ResponseStatus(HttpStatus.NOT_FOUND)
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(String message) {
super(message);
}
}