본문 바로가기
Spring

[유효성검증] Spring Boot Validation

by 행운의나무 2023. 4. 14.
728x90
반응형

유효성 검증

  • 입력 값이나 데이터가 정해진 규칙에 부합하는지 검증하는 과정
  • 보안측면에서 중요하다.
    • 유효하지 않은 악의적인 코드 필터가 가능하다.

@Valid VS @Validated

  • @Valid : java.validation 패키지에서 제공하는 유효성 검사 어노테이션
  • @Validated : spring-boot-starter-validation으로 추가 하여 사용
  • 두 어노테이션은 기능적으로는 차이는 없다.
    • 참고 : https://mangkyu.tistory.com/174
    • @Valid : ArgumentResolver에 의해 처리
      • 예외 : MethodArgumentNotValidException 발생
      • 메소드 레벨에서 주로 사용
    • @Validated : AOP기반으로 처리
      • 예외 : ConstraintViolationException 발생
      • 클래스 레벨에서 주로 사용
        •  유효성 검사 그룹 지정
  • @Validated의 유효성 검증 그룹 (코드의 복잡성때문에 거의 사용하지 않음 -> 두 어노테이션이 같은 동작을 수행한다고 생각하면 된다.)
    • 동일한 클래스에 요청에 따라 제약조건이 달라질 수 있다.
      • ex) 동일한 UserRequestDto 객체에서 일반 유저와 관리자 유저 분리

Spring Boot Validation

dependency 추가

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-validation'
}

자주 유효성 검사에 사용되는 어노테이션

@NotNull // null 불가 / "", " " 허용
@NotEmpty // null, "" 불가 / " " 허용
@NotBlank // null, "", " " 불가
@Email
@Pattern(regexp="") // 정규식
@Size(min=, max=) // 문자길이 제한
@Max(), @Min() // 최대/최소 값 지정

모델 정의

UserRequestDto

@Data  
@NoArgsConstructor  
@AllArgsConstructor  
@Builder  
public class UserRequestDto {  
  
    @NotNull(message = "이름은 null일 수 없습니다.")  
    private String name;  
  
    @Email(message = "email 형식으로 입력해주세요.")  
    @NotBlank(message = "eamil을 입력해주세요.")  
    private String email;  
  
    @Range(min = 1, max = 150, message = "1~150살 이내로 입력하세요.")  
    private Integer age;  
  
    @Pattern(regexp = "^\\d{2,3}-\\d{3,4}-\\d{4}$", message = "핸드폰 번호의 양식과 맞지 않습니다. 01x-xxx(x)-xxxx")  
    private String phoneNumber;  
}

컨트롤러

  • 3가지 케이스로 알아보기

1. 유효성 검증에 대한 예외를 처리하지 않은 경우

  • 400 Bad Request 에러를 발생하여 어떤 에러인지 명확하지 않다.
@RestController  
@RequestMapping("/user")  
public class UserController {  
    @PostMapping("/add")  
    public ResponseEntity add(@Valid @RequestBody UserRequestDto userRequestDto  
    ){  
  
        return ResponseEntity.ok("addUser");  
    }
}

400 Bad Request

2. BindingResult 이용

=> Spring에서 Validate 오류 발생시 바인딩하여 결과값을 저장하고 있는 객체로 사용된다.

@RestController  
@RequestMapping("/user")  
public class UserController {  
  
  
  @PostMapping("/add")  
public ResponseEntity add(@Valid @RequestBody UserRequestDto userRequestDto  
        , BindingResult bindingResult  
){  
  
  
    if (bindingResult.hasErrors()) {  
        List<String> errors = bindingResult.getAllErrors().stream().map(e -> e.getDefaultMessage()).collect(Collectors.toList());  
        return ResponseEntity.badRequest().body(errors);  
    }  
  
    return ResponseEntity.ok("addUser");  
	}
}

BinidngResult객체로 예외 처리

3. 공통 예외처리로 개선

  • BindingResult를 유효성 검증을 하는 메소드마다 넣기는 번거롭기 때문에 공통 예외로 처리한다.
  • @RestControllerAdvice로 개선
  • GlobalException
@RestControllerAdvice  
public class GlobalException {  
  
    @ResponseStatus(HttpStatus.BAD_REQUEST)  
    @ExceptionHandler(MethodArgumentNotValidException.class)  
    public Map<String, String> handleValidationExceptions(  
            MethodArgumentNotValidException ex) {  
        Map<String, String> errors = new HashMap<>();  
        ex.getBindingResult().getAllErrors().forEach((error) -> {  
            String fieldName = ((FieldError) error).getField();  
            String errorMessage = error.getDefaultMessage();  
            errors.put(fieldName, errorMessage);  
        });  
        return errors;  
    }  
}
  • controller
@RestController  
@RequestMapping("/user")  
public class UserController {  
    @PostMapping("/add")  
    public ResponseEntity add(@Valid @RequestBody UserRequestDto userRequestDto  
    ){  
  
        return ResponseEntity.ok("addUser");  
    }
}

RestControllerAdvice 예외 처리

쿠팡으로 연결 클릭

 

제주삼다수 그린 무라벨

COUPANG

www.coupang.com

파트너스 활동을 통해 일정액의 수수료를 제공받을 수 있음

반응형