Validation

마자나다·2024년 2월 7일

Spring

목록 보기
7/9

Spring Validation

  • 스프링 프레임워크에서 Validation 기능은 데이터 유효성을 검증하는 프로세스를 지원한다.
  • 사용자로부터 입력된 데이터의 형식이나 값이 정확한지 확인하는데 사용된다.

Validation 기능

  1. 어노테이션 기반 유효성 검사 : 자바 클래스나 해당 필드에 어노테이션을 사용하여 검증 규칙을 정의 할 수 있다. @Notnull, @Size, @Email 등 어노테이션을 사용하여 필드에 대한 유효성을 지정한다.
  2. Validator 인터페이스 : 개발자가 직접 Validator 인터페이스를 구현하여 복잡한 유효성 검사를 정의할 수 있다.
  3. BindingResult : 유효성 검사 결과를 담는 객체이다. 컨트롤러에서 BindingResult를 사용하여 유효성 검사 에러를 처리할 수 있다.
  4. Exception Handling : 유효성 검사에 실패할 경우 Spring은 자동으로 'MethodArgumentNotValidException'을 발생시키고, 이를 컨트롤러에서 적절하게 처리하여 클라이언트에게 에러메세지를 반환할 수 있다.

Validation 설정 및 사용

  • Gradle 설정을 사용하였다.

        implementation 'org.springframework.boot:spring-boot-starter-validation'
  • DTO클래스에서 view 모듈에서 클라이언트에게 받아오는 데이터 값을 바로 확인할 수 있도록 설계하였다.

    public class SignupDto {
       @NotBlank(message = "Please enter a username")
       private String userName;
    
       @Password
       @NotBlank(message = "Please enter a password")
       private String password;
    
       @NotBlank(message = "Please enter a name")
       @Email(message = "Please enter a valid email address")
       private String email;
       private String companyName;
       private String address;
       private boolean store;
       private boolean user;
    }

    위 DTO 클래스에서 알 수 있듯 @NotBlank어노테이션으로 빈칸에 대한 데이터를 불가능하도록 설정하였고, Email 검증등 다양한 어노테이션을 추가하였다.
    @Password라는 어노테이션이 있는데 이건 나중에 따로 검증을 위해 커스텀 어노테이션이다. 다음 블로그에서 따로 상세히 작성하겠다.

  • 컨트롤러에 유효성 검사 적용을 위한 @Valid 어노테이션도 적용하였다.

    public class UserSignupViewController {
       private final RestTemplate restTemplate = new RestTemplate();
       @GetMapping("/signup")
       public String showSignUpForm() {
           return "signup_form";
       }
       @RequestMapping(value = "/signup", method = RequestMethod.POST)
       public ResponseEntity<String> registerUser(@RequestBody @Valid SignupDto signupDTO, @Value("${api.url}") String url) {
           ResponseEntity<String> signupStatus = restTemplate.postForEntity( url + "/user/signup", signupDTO, String.class);
    
           return signupStatus;
       }
    }

    api 모듈쪽에 DTO를 파라미터로 받을때 추가해줘도 되지만 처음 데이터가 들어올때부터 검증을 위해 UI모듈에 @Valid 어노테이션을 추가하여 유효성 검사를 진행하였다.

  • 다음과 같은 방법으로 BindingResult 객체를 파라미터로 받아 유효성 검사결과를 확인할 수 있다.

 import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

@RestController
@Validated
public class UserController {

    @PostMapping("/users")
    public ResponseEntity<String> createUser(@Valid @RequestBody User user, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            // 유효성 검사 실패 시 처리
            return ResponseEntity.badRequest().body("Validation errors: " + bindingResult.getAllErrors());
        }
        
        // 유효성 검사 통과 시 처리
        return ResponseEntity.ok("User created successfully");
    }
}

자주 사용되는 어노테이션

  1. @NotNull: 해당 필드가 null이 아닌지 검사합니다.
  2. @Size: 문자열의 길이나 컬렉션의 크기를 제한합니다.
  3. @Min: 숫자 필드의 최소값을 지정합니다.
  4. @Max: 숫자 필드의 최대값을 지정합니다.
  5. @Email: 이메일 주소 형식의 문자열인지 확인합니다.
  6. @Pattern: 지정된 정규 표현식에 맞는 문자열인지 확인합니다.
  7. @NotBlank: 문자열이 비어 있지 않은지 확인합니다. (null과 공백 문자를 모두 체크)
  8. @NotEmpty: 문자열이나 컬렉션이 비어 있지 않은지 확인합니다. (null과 빈 문자열, 빈 컬렉션을 모두 체크)
  9. @Valid: 내부 객체에 대한 유효성 검사를 수행합니다. (주로 중첩된 객체의 유효성을 검사할 때 사용)
  10. @AssertTrue: 지정된 조건이 true인지 확인합니다. (boolean 필드에 사용)
  11. @AssertFalse: 지정된 조건이 false인지 확인합니다. (boolean 필드에 사용)
  12. @DecimalMin: 숫자 필드가 지정된 최소값 이상인지 확인합니다.
  13. @DecimalMax: 숫자 필드가 지정된 최대값 이하인지 확인합니다.
  14. @Digits: 숫자의 정수부 및 소수부 자릿수를 지정합니다.

Validated

@Valid는 프론트 컨트롤러인 디스패처 서블릿을 통해 컨트롤러로 전달된다. 이 때 전달과정에서 메소드 객체를 만들어주는 ArgumentResolver가 동작하는데, @Valid 역시 ArgumentResolver에 의해 처리가 된다.
이러한 같은 이유로 @Valid는 컨트롤러에서만 동작하며 다른계층에선 검증이 되지않는다.
다른 계층에서 파라미터를 검증하기 위해선 @Validated와 결합 되어야 한다.

Validated를 이용한 유효성 검증

  • 입력 파라미터의 유효성 검증은 최대한 컨트롤러에서 처리하고 넘겨주는 것이 좋다 하지만 불가피하게 다른곳에서 검증해야 할 때가 있다.
  • 스프링은 이를위해 AOP기반으로 메소드의 요청을 가로채서 유효성 검증을 진행해주는 @Validated를 제공한다.
  • JSR표준 기술이 아니며 스프링 프레임워크에서 제공하는 어노테이션 및 기능이다.
@Service
@Validated
public class UserService {

	public void addUser(@Valid AddUserRequest addUserRequest) {
		...
	}
}

다음과 같이 클래스에 @Validated를 붙여주고 유효성 검증할 파라미터에 @Valid를 붙여주면 된다.


Validated의 동작원리와 주의사항

특정 ArgumnetResolver에 의해 유효성 검사가 진행되었던 @Valid와 달리, @Validated는 AOP 기반으로 메소드 요청을 인터셉터하여 처리된다. @Validated를 클래스 레벨에 선언하면 해당 클래스에 유효성 검증을 위한 AOP의 어드바이스 또는 인터셉터(MethodValidationInterceptor)가 등록된다. 이러한 이유로 @Validated를 사용하면 컨트롤러, 서비스, 레포지토리 등 계층에 무관하게 스프링 빈이라면 유효성 검증을 진행할 수 있다.
이러한 이유로 @Valid에 의한 예외는 MethodArgumentNotValidException이며, @Validated에 의한 예외는  ConstraintViolationException이다. 이를 알고 있으면 나중에 예외 처리를 할 때 도움이 된다.

출처 및 참고
https://mangkyu.tistory.com/174
https://ajdahrdl.tistory.com/138

profile
우왕좌왕 개발

0개의 댓글