본문 바로가기

IT 공부

20. @valid (유효성 검사)

 

팀 프로젝트를 진행하던 도중

 

예를 들어 로그인을 한다고 가정해보자

 

user_id / user_password

 

라는 데이터를 입력 받아서

 

서버 단에서 처리를 하게 될 것이다

 

하지만 만약 해당 id값 과 password 값이 프론트 단에서 빈 문자열로 넘어 왔다던지

 

아니면 id가 email 형식으로 넘어와야하는데 이메일 표시인 @가 없을 때 에러가 발생할껀데

 

이걸 어떤식으로 처리할 수 있을까??

 

 

 

 

프론트 단에서 데이터가 없을 때 JavaScript 등을 사용해 처리하는 방식으로 해당 에러를 처리할 수 있을 것이다

 

하지만 서버 단에서는 어떻게 처리해야할 까 ??

 

내가 모르는 다양한 방법이 있겠지만 

 

오늘은 유효성 검사에 대해서 알아보고자 한다

 

 

[ 참조 블로그 ]

 

https://bamdule.tistory.com/35

 

[Spring Boot] @Valid 어노테이션으로 Parameter 검증하기

java.validation의 @Valid 어노테이션 사용법 정리 글입니다. Spring Boot 라이브러리에서 기본적으로 탑재된 기능이며 따로 dependency해 줄 필요가 없습니다. Spring Boot Version은 2.2.2.RELEASE 입니다. 1. j..

bamdule.tistory.com


 

@valid

 

해당 어노테이션을 사용하면 어떤 일이 발생하게 될까 ??

 

먼저 코드를 보도록 하자

 

 

[ Controller ]

@PostMapping(value = "/user")
public String insertUser(@RequestBody @Valid UserDto userDto){
    log.info("@ param : {}", userDto);

    return "success";
}

 

 

위 코드는 컨트롤러 이다

 

컨트롤러에서 해당 RequestBody를 통해서 데이터를 받아올 때 

 

@Valid 어노테이션을 해당 Dto에서 들어오는 데이터에 뭔가 작용을 하게 되어있다

 

 

그렇다면 @Valid는 뭘까?

 

@Valid 어노테이션을 사용하게되면

 

데이터가 들어올 때 

 

해당 데이터가 지정된 방식에 유효한 지 유효성 검사를 진행하게 된다

 

 

그렇다면 데이터가 어떠한 방식으로 들어와야 하는지는 어떻게 체크하게 될까?

 

해당 데이터를 체크하는 방식을 보기 위해서는 데이터를 저장하는 클래스 DTO 클래스를 체크해볼 필요가 있다

 

 

[ DTO ]

 

@Data
@RequiredArgsConstructor
public class UserDto{

    @Null(message = "번호를 입력해주세요")
    private long no;

    @NotNull(message = "이름을 입력해주세요")
    private String name;

    @Min(value = 5000, message = "금액은 5000원이상이여야 합니다") // 5000원 보다 같거나, 크면 통과
    private long Amt;

}

 

DTO 클래스에서 주목해야할 점은

 

데이터를 저장하는 변수에 위에 작성되어있는 어노테이션들이다

 

해당 어노테이션은

 

import javax.validation.constraints.Null;

 

라는 클래스에 저장되어 있다

 

 

그러면 해당 어노테이션들을 살펴보도록하자

 

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 인가?

 

나는 해당 DTO에서

 

Min 이라는 어노테이션을 사용했다고 쳐보자

 

@Min(value = 5000, message = "금액은 5000원이상이여야 합니다") // 5000원 보다 같거나, 크면 통과
private long Amt;

 

해당 어노테이션에서 만약 해당 데이터 Amt가 5000 미만이면 예외 처리가 되고 해당 메시지가 전송된다

 

 

 

해당 예외 처리는 어떤식으로 하게 될까?

 

 

[ Error code ]

 


public enum ErrorCode {

    NOT_NULL("ERROR_CODE_0001", "필수값 누락"),
    MIN_VALUE("ERROR_CODE_0002", "최소값보다 커야합니다");

    @Getter
    private String code;
    @Getter
    private String message;

    ErrorCode(String code, String message) {
        this.code = code;
        this.message = message;
    }
}

 

에러 코드를 통해서 해당 데이터를 출력하도록 하였다

 

 

[ ErrorResponse ]

 

@Data
public class ErrorResponse {

    private String code;

    private String description;

    private String detail;

    public ErrorResponse(String code, String description) {
        this.code = code;
        this.description = description;
    }

    public ErrorResponse(String code, String description, String detail) {
        this.code = code;
        this.description = description;
        this.detail = detail;
    }
}

 

 

[ Exception Handler ]

 

@Slf4j
@ControllerAdvice
public class ExceptionController {

 

먼저 핸들러에서 주목할 점은 @ControllerAdvice 어노테이션을 사용해서

 

예외처리가 될 때 해당 클래스를 거쳐갈 수 있도록 해야한다는 점이 중요하다

 

 


 

● ControllerAdvice 정보 블로그

 

https://jeong-pro.tistory.com/195

 

@ControllerAdvice, @ExceptionHandler를 이용한 예외처리 분리, 통합하기(Spring에서 예외 관리하는 방법, 실

예외 처리 과정 프로그래밍에서 예외 처리는 아주 중요하면서도 아주 어렵다. 과하다할 만큼 상세하고 다양하게 예외를 잡아 처리해준다면, 클라이언트도 그렇고 서버도 그렇고 더 안정적인 프

jeong-pro.tistory.com

 


 

 

해당 클래스에 메소드는 2가지 존재한다

 

예외가 발생했을 때 처리하게 되는 methodValidException을 먼저 보도록하자

@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> methodValidException(MethodArgumentNotValidException e){

    ErrorResponse errorResponse = makeErrorResponse(e.getBindingResult());

    return new ResponseEntity<ErrorResponse>(errorResponse, HttpStatus.BAD_REQUEST);
}

 

 

해당 메소드에서 주목할 점은 ErrorResponse 에 makeErrorResponse 라는 메소드로 객체를 생성한다

 

해당 메소드를 보도록하자

 

 

private ErrorResponse makeErrorResponse(BindingResult bindingResult){
    String code = "";
    String description = "";
    String detail = "";

    //에러가 있다면
    if(bindingResult.hasErrors()){
        //DTO에 설정한 meaasge값을 가져온다
        detail = bindingResult.getFieldError().getDefaultMessage();


        //DTO에 유효성체크를 걸어놓은 어노테이션명을 가져온다.
        String bindResultCode = bindingResult.getFieldError().getCode();

        System.out.println(bindingResult.getAllErrors());
        System.out.println("detail : " + detail);
        System.out.println("bind : " + bindResultCode);


        switch (bindResultCode){
            case "NotNull":
                code = ErrorCode.NOT_NULL.getCode();
                description = ErrorCode.NOT_NULL.getMessage();
                break;
            case "Min":
                code = ErrorCode.MIN_VALUE.getCode();
                description = ErrorCode.MIN_VALUE.getMessage();
                break;
        }
    }

    return new ErrorResponse(code, description, detail);
}

 

여기서 주목할 점은 switch 문이다

 

bindResultCode에는 @Min 어노테이션에서 유효성 검사에서 실패하면 Min 이라는 데이터가 넘어오게 설정되어 있는데

 

그것을 체크해서 미리 만들어져있는 Enum 클래스 ErrorCode에서 데이터를 가져와서 반환할 수 있도록 설정해두었다

 

 

 

 

[ 결 과 ]

 

 

 

첫번 째 데이터에서 name 이라는 데이터에 NotNull 즉 Null 값은 허용하지 않는다고 해뒀다

 

그렇기 때문에 Name에 대한 데이터를 전송하지 않아서 Null이 되면 유효성 검사에서 예외 처리가 발생하게 되고

 

switch에서 

 

case "NotNull":
    code = ErrorCode.NOT_NULL.getCode();
    description = ErrorCode.NOT_NULL.getMessage();
    break;

 

Enum 데이터를 입력한다

 

NOT_NULL("ERROR_CODE_0001", "필수값 누락"),

 

 

그리고 마지막 데이터인 detail에는

 

detail = bindingResult.getFieldError().getDefaultMessage();

 

해당 데이터가 들어가게되고 해당 데이터는 DTO 클래스의

 

@NotNull(message = "이름을 입력해주세요")
private String name;

 

부분의 message 데이터를 가져와서 입력 받게 된다

 

 

 

동일한 방식으로 min 데이터를 5000보다 낮게 입력해서 강제로 유효성 검사에서 실패하면 해당 데이터가 출력되게 된다

 

만약 복수의 데이터가 동시에 유효성 검사에 걸리게 되면 가장 위에 있는 데이터의 유효성 검사가 뜨는걸 알 수 있다

'IT 공부' 카테고리의 다른 글

31. TDD  (0) 2022.11.02
21. [JAVA문법] While(val --> 0) 란?? [ --> 가 뭘까? ]  (0) 2022.09.03
13. JSON 방식으로 이미지 보내기  (0) 2022.08.08
11. Cors  (0) 2022.07.30
10. 카카오, 구글, 페이스북 로그인 설정  (0) 2022.07.25