Validation
Validation์ ํ๋ก๊ทธ๋๋ฐ์ ํ๋๋ฐ์ ์์ด์ ๊ฐ์ฅ ์ค์ํ ๋ถ๋ถ ์ค ํ๋์
- Java๋ null ๊ฐ์ ๋ํ ์ ๊ทผ์ ๋ํด NullPointerException ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ธฐ ๋๋ฌธ์ ์ด๋ฌํ ๋ถ๋ถ์ ์๋ฐฉํ๊ธฐ ์ํด Validation ์ฆ, ๊ฒ์ฆ ๊ณผ์ ์ด ํ์ํจ
- Spring์์๋ null ํ์ธ ๋ฟ ์๋๋ผ ๋ฌธ์์ ๊ธธ์ด ์ธก์ ๊ณผ ๊ฐ์ ๋ค๋ฅธ ๊ฒ์ฆ ๊ณผ์ ๋ ์ฝ๊ฒ ์ฒ๋ฆฌํ ์ ์๋๋ก Bean Validation ์ ๊ณตํ๊ณ ์์
Bean Validation
| @NotNull | null ๋ถ๊ฐ |
| @NotEmpty | null, "" ๋ถ๊ฐ |
| @NotBlank | null, "", " " ๋ถ๊ฐ |
| @Size | ๋ฌธ์ ๊ธธ์ด ์ธก์ |
| @Max | ์ต๋๊ฐ |
| @Min | ์ต์๊ฐ |
| @Positive | ์์ |
| @Negative | ์์ |
| E-mail ํ์ | |
| @Pattern | ์ ๊ท ํํ์ |
๏นกValidation์ ์ฌ์ฉํ๊ธฐ ์ํด dependencies์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ถ๊ฐํด์ผํจ
implementation 'org.springframework.boot:spring-boot-starter-validation'
DTO์ Bean Validation ์ค์
package com.sparta.springauth.dto;
import jakarta.validation.constraints.*;
import lombok.Getter;
@Getter
public class ProductRequestDto {
@NotBlank
private String name;
@Email
private String email;
@Positive(message = "์์๋ง ๊ฐ๋ฅํฉ๋๋ค.")
private int price;
@Negative(message = "์์๋ง ๊ฐ๋ฅํฉ๋๋ค.")
private int discount;
@Size(min=2, max=10)
private String link;
@Max(10)
private int max;
@Min(2)
private int min;
}
Valid ๋์ ์ดํด
- Controller ๋ด ๋ฐ์ดํฐ ๊ฒ์ฆ์ ํ๊ณ ์ถ์ DTO ์์ @Valid ์ด๋ ธํ ์ด์ ์ถ๊ฐ
@PostMapping("/validation")
@ResponseBody
public ProductRequestDto testValid(@RequestBody @Valid ProductRequestDto requestDto) {
return requestDto;
}
์ ํํ ์ ๋ ฅ๊ฐ์ ๋ณด๋์ ๊ฒฝ์ฐ

์๋ชป๋ ์ ๋ ฅ๊ฐ์ ๋ณด๋์ ๊ฒฝ์ฐ


Validation ์์ธ์ฒ๋ฆฌ
ํ์๊ฐ์ DTO Validation ์ ์ฉ
package com.sparta.springauth.dto;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class SignupRequestDto {
@NotBlank
private String username;
@NotBlank
private String password;
@Email
@NotBlank
private String email;
private boolean admin = false;
private String adminToken = "";
}
Controller ๋จ์์ Validation ์์ธ์ฒ๋ฆฌํ๊ธฐ
- BindingResult๋ Validation์์ ์์ธ๊ฐ ๋ฐ์ํ๋ฉด BindingResult ๊ฐ์ฒด์ ์ค๋ฅ์ ๋ํ ์ ๋ณด๊ฐ ๋ด๊ฒจ์ ๋ค์ด์ด
@PostMapping("/user/signup")
// BindingResult: Validation์์ ์์ธ๊ฐ ๋ฐ์ํ๋ฉด BindingResult ๊ฐ์ฒด์ ์ค๋ฅ์ ๋ํ ์ ๋ณด ๋ด๊ฒจ์ ๋ค์ด์ด
public String signup(@Valid SignupRequestDto requestDto, BindingResult bindingResult) {
// Validation ์์ธ์ฒ๋ฆฌ
List<FieldError> fieldErrors = bindingResult.getFieldErrors(); // ์ค๋ฅ๊ฐ ๋ ํ๋ ๊ฐ์ ธ์ค๊ธฐ
if(fieldErrors.size() > 0) {
for (FieldError fieldError : bindingResult.getFieldErrors()) {
// ์ค๋ฅ๊ฐ ๋ ํ๋ ๊ฐ์ ธ์ค๊ธฐ
log.error(fieldError.getField() + " ํ๋ : " + fieldError.getDefaultMessage());
}
return "redirect:/api/user/signup";
}
userService.signup(requestDto);
return "redirect:/api/user/login-page";
}

์ ๊ท ํํ์(Regular Expression; Regex, Regexp)
์ ๊ท ํํ์์ ํน์ ํ ๊ท์น์ ๊ฐ์ง ๋ฌธ์์ด์ ์งํฉ์ ํํํ๊ธฐ ์ํด ์ฐ์ด๋ ํ์ ์ธ์ด๋ก,
์ด๋ค ํ ์คํธ ๋ด์์ 'ํน์ ํ ํํ๋ ๊ท์น์ ๊ฐ์ง ๋ฌธ์์ด'์ ์ฐพ๊ธฐ ์ํด ๊ทธ ํํ๋ ๊ท์น์ ๋ํ๋ด๋ ํจํด์ ์ ์ํ๋ ์์ ๋ปํจ
์ ๊ท ํํ์ ๊ธฐ๋ณธ ๋ฌธ๋ฒ
- ํจํด ๊ทธ๋๋ก๋ฅผ ๋งค์นญํ๋ ๊ฒฝ์ฐ: ๋จ์ด ๊ทธ๋๋ก๋ฅผ ํจํด์ผ๋ก ์ฌ์ฉํด ๋งค์นญ๋๋ ์์ญ์ ์ฐพ๋ ๋ฐฉ๋ฒ
- ๋ฉํ๋ฌธ์ ๋ฐ ์๋ ํ์ ์๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ: ์ ๊ท์ ํจํด์ ์ฐ์ด๋ ๋ฌธ์ ์ค์๋ ํน๋ณํ ์๋ฏธ๋ฅผ ์ง๋๋ ๋ฉํ ๋ฌธ์๋ค์ด ์๋๋ฐ, ์ด๋ฌํ ๋ฉํ๋ฌธ์์ ๊ทธ ๋ฉํ๋ฌธ์์ ๊ฐ์๋ฅผ ์ง์ (์๋ ํ์ ์์ ์ญํ )ํ์ฌ ํญ๋์ ํจํด์ ๋งค์นญํ๋ ๋ฐฉ๋ฒ
- ๊ทธ๋ฃน ๋ฐ Look around(์ , ํ๋ฐฉ ํ์) ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ: ํจํด์ ์ผ๋ถ๋ฅผ ๊ทธ๋ฃน์ผ๋ก ๋ฌถ๊ฑฐ๋, ํน์ ํจํด์ ์ ๋๋ ๋ค๋ก ๋ค๋ฅธ ํจํด์ด ์ค๋ ์กฐ๊ฑด์ ๋ํ๋ ๊ฒฝ์ฐ
์ ๊ท ํํ์ ๋ฉํ ๋ฌธ์
๋ฉํ ๋ฌธ์๋ ํน์ ํ ๋ฌธ์ ํน์ ๋ฌธ์ ๊ณ์ด์ ๋์ ํด ํ์ํ๋ ๋ฌธ์๋ก, ๋ฉํ ๋ฌธ์๋ฅผ ์ด์ฉํ๋ฉด ํน์ ํ ๊ท์น์ ๊ฐ์ง ์ฌ๋ฌ ๋จ์ด๋ฅผ ํ๋์ ํจํด์ผ๋ก ํจ์ถํ ์ ์์
- ๋ฉํ๋ฌธ์์์ ๋์๋ฌธ์๋ ์๋ก ๋ฐ๋๋๋ ์๋ฏธ๋ฅผ ์ง๋๋ ๊ฒฝ์ฐ๊ฐ ๋ง์!
๋ฉํ ๋ฌธ์ ์ ๋ฆฌ ์ฐธ๊ณ ์ฌ์ดํธ
์ ๊ทํํ์(Regex)์ ๊ฐ๋ ๊ณผ ๊ธฐ์ด ๋ฌธ๋ฒ
์ ๊ทํํ์์ด๋? : Regular Expression์ ์ค์ฌ์ Regex, Regexp ๋ฑ์ผ๋ก ๋ถ๋ฆฐ๋ค. Computer Science์ ์ ๊ท ์ธ์ด(Regular Language)๋ก๋ถํฐ ์ ๋ํ ๊ฒ์ผ๋ก, ํน์ ํ ๊ท์น์ ๊ฐ์ง ๋ฌธ์์ด์ ์งํฉ์ ํํํ๊ธฐ ์ํด ์ฐ์ด๋ *
co-no.tistory.com
์ ๊ท ํํ์์ ์ฌ์ฉํด ์ด๋ฉ์ผ Validation ์ค์
@Pattern(regexp = "^(.+)@(.+)$") // '@'๊ธฐํธ๋ง ํ์ธ
@Pattern(regexp = "[A-Za-z0-9+_.-]+@(.+)$") // ์ ๋ถ๋ถ๋ง ๊ท์น ์ค์ (A-Z, a-z, 0-9, _, . ๋ชจ๋ ํ์ฉ)
@Pattern(regexp = "[A-Za-z0-9_!#$%&'*+/=?`{|}~^.-]+@[A-Za-z0-9.-]+$") // ์ ๋ค ๋ชจ๋ ๊ฒ์ฆ(์์ ์ด๋ฉ์ผ์์ ํ์ฉํ๋ ๊ฒ๋ค ๋ชจ๋ ์ถ๊ฐํด๋ด)