IT/Spring

Spring Boot에서 @Valid와 @ExceptionHandler로 유효성 검사 에러 처리

iamhyeon 2025. 8. 5. 10:02

 

웹 애플리케이션에서 클라이언트로부터 데이터를 받을 때, 값이 유효하지 않다면 서비스 로직이 실행되기 전에 차단하는 것이 안전하다.
Spring Boot에서는 @Valid 또는 @Validated 어노테이션을 활용해 손쉽게 입력값 검증을 수행할 수 있다.

하지만 유효성 검증에서 실패하면 MethodArgumentNotValidException 같은 예외가 발생하고, 기본적으로는 깔끔한 JSON 형태로 응답되지 않는다.
@Valid 유효성 검사와 @ExceptionHandler를 활용하여 사용자 친화적인 에러 메시지 응답을 구현하는 방법 ⬇️

 

@Valid와 유효성 검사 어노테이션

Spring Boot에서는 DTO 클래스에 다양한 검증 어노테이션을 붙여 입력값을 제한할 수 있다.
대표적으로 다음과 같은 어노테이션이 있다.

@NotNull null 허용 안 함 @NotNull(message = "값을 입력해주세요.")
@Size 문자열 길이 제한 @Size(min = 3, max = 20)
@Email 이메일 형식 검증 @Email(message = "이메일 형식으로 입력해 주세요.")
@Pattern 정규식 패턴 매칭 @Pattern(regexp = "^[0-9]{4}$")

 

예시 DTO:

import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

public class UserRequest {

    @NotNull(message = "이름은 필수 입력값입니다.")
    @Size(min = 2, max = 20, message = "이름은 2~20자 사이여야 합니다.")
    private String name;

    @NotNull(message = "이메일은 필수 입력값입니다.")
    @Email(message = "이메일 형식으로 입력해 주세요.")
    private String email;

    @NotNull(message = "비밀번호는 필수 입력값입니다.")
    @Size(min = 8, message = "비밀번호는 최소 8자 이상이어야 합니다.")
    private String password;
    
    ...
}

 

 

Controller에서 @Valid 사용

컨트롤러에서 @RequestBody와 함께 @Valid를 붙이면, 요청 바디를 매핑할 때 자동으로 유효성 검증이 수행된다.

import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/users")
public class UserController {

    @PostMapping
    public ResponseEntity<String> createUser(@Valid @RequestBody UserRequest userRequest) {
        return ResponseEntity.ok("회원가입 성공");
    }
}

 

이 상태에서 유효성 검증을 통과하지 못하면 MethodArgumentNotValidException이 발생하게 된다.

 

@ExceptionHandler로 예외 처리하기

Spring Boot에서 전역 예외 처리를 위해 @ControllerAdvice@ExceptionHandler를 함께 사용한다.

아래 예시는 MethodArgumentNotValidException 예외를 잡아, 검증 실패한 필드와 메시지를 JSON 형태로 반환하는 방법이다.

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.HashMap;
import java.util.Map;

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex) {
        Map<String, String> errors = new HashMap<>();
        for (FieldError error : ex.getBindingResult().getFieldErrors()) {
            errors.put(error.getField(), error.getDefaultMessage());
        }
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errors);
    }
}

 

 

실행 예시

요청

POST /api/users
Content-Type: application/json

{
  "name": "A",
  "email": "invalid-email",
  "password": "123"
}

 

응답

HTTP 상태 코드 400 Bad Request

{
  "name": "이름은 2~20자 사이여야 합니다.",
  "email": "이메일 형식으로 입력해 주세요.",
  "password": "비밀번호는 최소 8자 이상이어야 합니다."
}

 

 

 

  • @Valid와 Bean Validation 어노테이션을 사용하면 서버 단에서 강력하고 간단한 유효성 검사를 할 수 있다.
  • 기본 예외 응답은 사용자 친화적이지 않을 수 있으므로, @RestControllerAdvice + @ExceptionHandler응답 포맷을 커스터마이징하는 것이 좋다.
  • 이 방법을 사용하면 프론트엔드나 API 클라이언트가 에러를 명확히 파악하고 처리할 수 있다.

 

 

반응형