인프런 커뮤니티 질문&답변

도토리님의 프로필 이미지

작성한 질문수

실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화

회원 등록 API

검증 오류 시 api 전송

작성

·

56

0

MemberApiController의 saveMemberV2()에서 @Valid에 의해 검증 오류가 발생한 경우에도 오류에 대한 api를 내려줘야 하잖아요. 이때에도 오류가 없는 경우와 마찬가지로 CreateMemberResponse를 반환해야 하는 건가요?

검증 오류가 발생했을 때 api를 어떻게 전달해야하는지를 잘 모르겠습니다.

답변 2

0

안녕하세요. 도토리님, 공식 서포터즈 코즈위버입니다.

많은 경우 ResultMessage 같은 객체를 작성하여 클라이언트가 항상 일관된 구조의 응답을 받을 수 있도록 제어합니다. 가령 아래와 같은 형태로 객체를 작성하여 두고

public class ResultMessage {
    private String resultCode;
    private String resultMessage;
    private Object data;
}

 

클라이언트의 요청결과를 담고 있는 객체가 CreateMemberResponse 라면 컨트롤러영역에서 다음과 같이 응답할 수 있습니다.

public class MemberController {
    public ResultMessage createMember(CreateMemberFormDto form) {
        .... logic ...
        CreateMemberResponse response = service.createMember(form);
        return new ResultMessage("200", "회원가입 성공", response);
    }
}

 

그러면 클라이언트에서 이 응답을 받아 resultCode 등으로 요청이 성공하였는지 실패하였는지 판단할 수 있습니다.

 

감사합니다.

0

안녕하세요, 인프런 AI 인턴입니다.
도토리님께서 질문하신 검증 오류 발생 시 API 응답에 관한 내용에 대해 도움을 드리겠습니다.

검증 오류가 발생했을 때 API가 올바른 에러 응답을 반환하도록 하는 방법은 여러 가지가 있습니다. 아래와 같은 방법을 활용할 수 있습니다.

  1. 전역 예외 처리(@ControllerAdvice 또는 @RestControllerAdvice) 사용:

    • Spring에서는 전역 예외 처리를 위해 @ControllerAdvice 또는 @RestControllerAdvice를 사용합니다. 예외 처리 메서드를 정의하여 특정 예외가 발생했을 때 해당 메서드가 호출되도록 설정할 수 있습니다.

    예를 들어, MethodArgumentNotValidException 예외가 발생했을 때 이를 처리하는 예제는 아래와 같습니다.

    @RestControllerAdvice
    public class GlobalExceptionHandler {
    
    
        @ExceptionHandler(MethodArgumentNotValidException.class)
        public ResponseEntity<ErrorResponse> handleValidationExceptions(MethodArgumentNotValidException ex) {
            List<String> errors = ex.getBindingResult()
                                     .getAllErrors()
                                     .stream()
                                     .map(DefaultMessageSourceResolvable::getDefaultMessage)
                                     .collect(Collectors.toList());
    
    
            ErrorResponse errorResponse = new ErrorResponse("Validation failed", errors);
            return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
        }
    }
    

    위 코드에서 ErrorResponse는 오류 메시지를 담기 위한 DTO 클래스입니다.

    public class ErrorResponse {
        private String message;
        private List<String> errors;
    
    
        public ErrorResponse(String message, List<String> errors) {
            this.message = message;
            this.errors = errors;
        }
    
    
        // getters and setters
    }
    
  2. 검증 오류가 발생한 경우 Custom Exception을 던지고 이를 처리:

    • 별도의 Custom Exception 클래스를 정의하고, 검증 오류 시 이 예외를 던지도록 할 수도 있습니다.
    public class ValidationException extends RuntimeException {
        private List<String> errors;
    
    
        public ValidationException(List<String> errors) {
            this.errors = errors;
        }
    
    
        public List<String> getErrors() {
            return errors;
        }
    }
    

    그리고 검증 오류가 발생하는 곳에서 이 예외를 던지도록 합니다.

    @PostMapping("/api/v2/members")
    public ResponseEntity<?> saveMemberV2(@RequestBody @Valid CreateMemberRequest request, BindingResult result) {
        if (result.hasErrors()) {
            List<String> errors = result.getAllErrors()
                                        .stream()
                                        .map(DefaultMessageSourceResolvable::getDefaultMessage)
                                        .collect(Collectors.toList());
            throw new ValidationException(errors);
        }
    
    
        Member member = new Member();
        member.setName(request.getName());
        Long id = memberService.join(member);
        return ResponseEntity.ok(new CreateMemberResponse(id));
    }
    

    이렇게 던진 예외를 @ControllerAdvice에서 처리합니다.

    @RestControllerAdvice
    public class GlobalExceptionHandler {
    
    
        @ExceptionHandler(ValidationException.class)
        public ResponseEntity<ErrorResponse> handleValidationException(ValidationException ex) {
            ErrorResponse errorResponse = new ErrorResponse("Validation failed", ex.getErrors());
            return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
        }
    }
    

위 두 방법 모두 유효성 검사 실패 시 적절한 에러 응답을 보내는 방법입니다.

유사한 질문에 대한 답변은 다음 링크에서도 확인하실 수 있습니다:

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.