Spring

[Spring Boot] @Valid 애노테이션 사용하여 검증하기

kyunge_ev 2023. 2. 1. 22:38

@Valid

 JSR-303 표준 스펙(자바 진영 스펙)으로서 빈 검증기(Bean Validator)를 이용해 객체의 제약 조건을 검증하도록 지시하는 애노테이션이다. 객체의 필드에 달린 애노테이션으로 편리하게 유효성검사를 제공한다.

 Spring Boot에서는 아래의 의존성만 추가해주면 @Valid 기능을 사용할 수 있다.

implementation group: 'org.springframework.boot', name: 'spring-boot-starter-validation'

 Service에서 검증로직을 작성하여 확인할 수 있지만, DTO 또는 객체를 검증해야할 때 별도로 검증 클래스를 만들어 사용하는 것이 아니라 @Valid 애노테이션을 사용하여 간단하게 검증할 수 있다.

🔍 java.validation 애노테이션 종류

Anotation 제약조건
@NotNull Null 불가
@Null Null만 입력 가능
@NotEmpty Null, 빈 문자열 불가
@NotBlank Null, 빈 문자열, 스페이스만 있는 문자열 불가
@Size(min=,max=) 문자열, 배열등의 크기가 만족하는가?
@Pattern(regex=) 정규식을 만족하는가?
@Max(숫자) 지정 값 이하인가?
@Min(숫자) 지정 값 이상인가
@Future 현재 보다 미래인가?
@Past 현재 보다 과거인가?
@Positive 양수만 가능
@PositiveOrZero 양수와 0만 가능
@Negative 음수만 가능
@NegativeOrZero 음수와 0만 가능
@Email 이메일 형식만 가능
@Digits(integer=, fraction = ) 대상 수가 지정된 정수와 소수 자리 수 보다 작은가?
@DecimalMax(value=)  지정된 값(실수) 이하인가?
@DecimalMin(value=) 지정된 값(실수) 이상인가?
@AssertFalse false 인가?
@AssertTrue true 인가?

@Valid / @ControllerAdvice를 이용한 Exception 처리

@ControllerAdvice 란

 @Controller 전역에서 발생할 수 있는 예외를 잡아 처리해주는 애노테이션

1. UserJoinController 👉 회원가입 API

Valid 를 사용할 DTO 앞에 @Valid 애노테이션을 달아준다.

@RestController
@RequestMapping("/api/v1/users")
@RequiredArgsConstructor
@Slf4j
public class UserRestController {

    private final UserService userService;

    @ApiOperation(
            value = "회원가입"
            , notes = "userName, password -> 회원가입")
    @PostMapping("/join")
    public Response<UserJoinResponse> join(@RequestBody @Valid UserJoinRequest userJoinRequest){
        log.debug("userName : {} password : {}  ", userJoinRequest.getUserName(), userJoinRequest.getPassword());
        UserJoinResponse userJoinResponse = userService.join(userJoinRequest.getUserName(), userJoinRequest.getPassword());
        log.debug("userJoinResponse : {} ", userJoinResponse);
        return Response.success(userJoinResponse);
    }
    
 }

2. ErrorResponse 클래스로 API에 응답해줄 에러 형태를 정한다.

@Getter
@AllArgsConstructor
public class ErrorResponse {
    public ErrorCode errorCode;
    public String message;
}

3. enum 클래스에 에러코드 정의

@AllArgsConstructor
@Getter
public enum ErrorCode {
    //...
   ;
   
	private final HttpStatus status;
	private final String message;
}

4. UserJoinRequest 클래스

사용할 @Valid 애노테이션을 컬럼에 달아준다.

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Data
public class UserJoinRequest {
    @NotNull(message = "userName은 필수 입력값입니다.")
    private String userName;
    
    @NotNull(message = "password는 필수 입력값입니다.")
    private String password;
    
}

5. RestControllerAdvice(ControllerAdvice)

@Valid 유효성 체크에 통과하지 못하면 MethodArgumentNotVaildException 이 발생한다.
애노테이션에 적어두었던 메시지가 에러 메시지로 반환된다.

@RestControllerAdvice
public class ExceptionController {

	@ExceptionHandler(MethodArgumentNotValidException.class)
	public ResponseEntity<?> MethodArgumentNotValidExceptionHandler(
			MethodArgumentNotValidException e) {
		return ResponseEntity.status(HttpStatus.BAD_REQUEST)
				.body(Response.error(new ErrorResponse(ErrorCode.INVALID_REQUEST,
						e.getBindingResult().getAllErrors().get(0).getDefaultMessage())));
	}
}

 

 

 

📚 참조블로그
- https://cchoimin.tistory.com/entry/Valid-%EC%99%80-ControllerAdvice%EB%A1%9C-DTO-%EC%98%88%EC%99%B8%EC%B2%98%EB%A6%AC%ED%95%98%EA%B8%B0