본문 바로가기

Back-End/Spring Boot

Spring Boot Validation 사용

Validation이란?

Validation이란 프로그래미에 있어서 가장 필요한 부분이다. 특히 Java에서는 null 값에 대해서 접근 하려고 할 때

NullPointerException이 발생 함으로, 이러한 부분을 방지하기 위해서 미리 검증하는 과정을 Validation 이라고 한다.

 

이름과 비밀번호 나이가 입력으로 들어온다 했을 때, 단순하게 생각하면

public void validate(String name, String pwd, int age) {
	if(name == null || pwd == null) {
    	return;
    }
    if(age == 0) {
    	return;
    }
    // logic
}

위와 같이 작성할 수 있을것이다.

 

하지만 위와 같은 코드들이 반복될 수록 아래와 같은 문제가 생길 수 있다.

1. 검증해야할 값이 많은 경우 코드의 길이가 길어 진다.
2. 구현에 따라서 달라 질 수 있지만 Service Logic과 분리가 필요하다.
3. 흩어져 있는 경우 어디에서 검증을 하는지 알기가 어려우며, 재사용의 한계가 있다.
4. 구현에 따라 달라질 수 있지만, 검증 Logic이 변경 되는 경우 테스트 코드 등
    참조하는 클래스에서 Logic이 변경되어야 하는 부분이 발생할 수 있다.

 

 

Spring Boot에서 Validation

Spring Boot에서는 Validation을 Annotation을 사용하여 일관적으로 제공해준다.

Annotaion 내용
@Size 문자 길이 측정
@NotNull null불가
@NotEmpty null, ""불가
@NotBlank null, "", " " 불가
@Past 과거 날짜
@PastOrPresent 오늘이나 과거 날짜
@Future 미래 날짜
@FutureOrPresent 오늘이거나 미래 날짜
@Pattern 정규식 적용
@Email 이메일 형식 확인
@Max 최대값
@Min 최소값
@AssertTrue/ False 별도 Logic 적용
@Valid 해당 Object Validation 실행

 

하지만 이러한 Validation들은 기본적으로 제공해주는 것이 아니라서 gradle dependecies가 필요하다.

implementation("org.springframework.bot:spring-boot-starter-validation")

위의 dependecies를 추가했으면 이제 사용을 할 수 있다.

 

User class로 예시를 들자면

public class User {

    private Long id;
    
    @NotBlank
    private String name;  
    
    @Min(value = 1)
    private int age;
    
    @Pattern(
    	regexp = "^\\d{2,3}-\\d{3,4}-\\d{4}$", 
        message="핸드폰 번호는 000-0000-000 형식이여야합니다."
    )
    private String phoneNumber;
    
    @NotBlank
    private String loginId;
    
    @Pattern(regexp = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,10}$")
    private String password;
    
    @Email
    private String email;
    
    // yyyyMMdd로 들어오는 날짜
    @Size(min=8, max=8)
    private String reqDate;
    
    // reqDate에 대한 validation 로직 작성
    // 필드 변수에 대한 validation작성시 is+필드변수명+Validation을 항상 붙여서 만들어야함
    @AssertTrue
    public boolean isReqDateValidation() {
    	try {
        	LocalDate.parse(getReqDate(), DateTimeFormatter.ofPattern("yyyyMMdd"));
        } catch(Exeption e) {
        	return false;
        }
        return true;
    }
}

와 같이 사용할 수 있다.

 

 

Annotation을 붙였다고 User클래스를 사용할 때마다 검증이 되는 것은 아니다. 검증하기 위해서는 사용하는 곳에 @Valid를 붙여야 Annotation에 대한 검증이 시작된다.  

@PostMapping("/user")
// @Valid Annotation을 붙여서 검증 요청
public ResponseEntity User(@Valid @RequestBody User user, BindingResult bindingResult) {
    StringBuilder sb = new StringBuilder("");
    if(bindingResult.hasErrors()) {
    	bindingResult.getAllErrors.forEach(objectError -> {
            FieldError field = (FieldError) objectError; // Error 발생 필드
            String message = objectError.getDefaultMessage(); // Error 메시지
                
            sb.append("field : " + field.getField());
            sb.append("message : " + message);
        })
    }
    
    return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(sb.toString());
}

Controller에서 일부를 가져왔다.

위 코드는 @Valid로 검증을 요청하고 Error가 발생할 시 BindingResult로 Error를 가져와서 Error발생 필드와 해당 메시지를 가져와서 Status에 Body로 내려주는 코드이다.

 

위와 같이 User클래스를 받는 곳에 @Valid를 붙여야 사용할 수 있다.

 

그 외에도 Path Parameter에도 적용 시킬 수 있는데 이는 클래스에 작성한 것과는 비슷하게 작성해야한다.

클래스에 @Validated를 붙이고 객체 사용한 것 처럼 작성하면 된다.

@RestController
@RequestMapping("/api")
@Valitdated
public class RestApiController {
  @GetMapping("/get/{id}")
  public String get(
    @Size(min=1)
    @PathVariable Long id,
    @NotNull
    @RequestParam String name
 ) {
    return id + " " + name;
  } 
}

 

또한 만약에 Mapping관계에 있는 클래스에도 @Valid를 사용해야 해당 클래스를 가져올 때 @Valid가 적용이 된다.

public class User {

    // logic
	
    @Valid
    List<Board> boards;
}

※ 만약에 @Valid가 없으면 User가 들어오면서 Board가 같이 들어왔을 때, Board에 Validation이 붙어 있다 하더라도 검증을 진행하지 않아 ""나 null에 대한 처리를 하지 않게된다.

'Back-End > Spring Boot' 카테고리의 다른 글

Spring Boot Filter란  (2) 2024.06.16
Spring Boot @RestControllerAdvice를 이용한 예외 처리 방법  (0) 2024.06.09
AOP  (0) 2024.06.08
IoC와 DI  (0) 2024.06.08
Spring Boot Custom Validation만들기  (0) 2024.06.07