
BindingResult를 통해 직접 error를 컨트롤해서 클라이언트에게 에러 메세지 전달@PostMapping("/posts")
public Map<String, String> post(@RequestBody @Valid PostCreate params,
BindingResult result){
if(result.hasErrors()){
List<FieldError> fieldErrors = result.getFieldErrors();
FieldError firstFieldError = fieldErrors.get(0);
String fieldName = firstFieldError.getField();
String errorMessage = firstFieldError.getDefaultMessage();
Map<String, String> error = new HashMap<>();
error.put(fieldName, errorMessage);
return error;
}
return Map.of();
}
1. 메서드마다 검증 코드가 필요하다
2. 적절하지 않은 반환타입
HashMap 타입을 사용했는데,Map이 아니라 응답에 맞는 형태의 클래스를 만들어 사용하는게 좋음3. 여러 개의 에러 처리가 힘듦
fieldErrors.get(0))| 어노테이션 | @ControllerAdvice | @RestControllerAdvice |
|---|---|---|
| 기본 동작 | HTML 뷰 또는 JSON 데이터 반환 가능 | 기본적으로 JSON데이터(응답 본문)을 반환 |
@ResponseBody 필요여부 | JSON 응답 시 @ResponseBody를 메서드에 추가 | 자동으로 @ResponseBody 적용 |
| 주요 사용 사례 | HTML 뷰와 API응답을 혼용하는 프로젝트 | REST API 전용 프로젝트 |
| 내부 구현 | @ControllerAdvice | @ControllerAdvice + @ResponseBody |
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
// 특정 예외 타입에 대한 예외 처리
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public Map<String, String> handleValidationExceptions(MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getFieldErrors().forEach(error ->
errors.put(error.getField(), error.getDefaultMessage())
);
return errors;
}
}
컨트롤러에서 @RequestBody를 통해 요청 데이터를 PostCreate 객체에 매핑
getter(), setter()가 필요PostCreate에는 검증 어노테이션(@NotBlank 등)을 추가하고,
컨트롤러에는 @Vaild를 추가해 입력 데이터를 검증
요청 데이터 검증 과정에서 에러가 발생하면,
@ControllerAdvice와 @ExceptionHandler를 통해 에러를 처리
에러에 대한 정보를 반환하기 위해 ErrorResponse를 작성