Spring Validation
Spring Validation์ ์ฌ์ฉ์ ์
๋ ฅ ๋ฐ์ดํฐ์ ์ ํจ์ฑ์ ๊ฒ์ฆํ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. ์ ํ๋ฆฌ์ผ์ด์
์์ ์๋ชป๋ ๋ฐ์ดํฐ๊ฐ ์ฒ๋ฆฌ๋๋ ๊ฒ์ ๋ฐฉ์งํ๊ณ , ๋ฐ์ดํฐ์ ๋ฌด๊ฒฐ์ฑ์ ๋ณด์ฅํ๋๋ฐ ๋์์ ์ค๋๋ค.
์ฃผ์ ํน์ง
โข
Bean Validation API๋ฅผ ์ฌ์ฉํ ์ฌ์ด ์ ํจ์ฑ ๊ฒ์ฆ
โข
๋ค์ํ ๋ด์ฅ ๊ฒ์ฆ ์ด๋
ธํ
์ด์
์ ๊ณต
โข
์ปค์คํ
๊ฒ์ฆ ๋ก์ง ๊ตฌํ ๊ฐ๋ฅ
โข
์ปจํธ๋กค๋ฌ์์ ์๋ ๊ฒ์ฆ ์ฒ๋ฆฌ
โข
์ค๋ฅ ๋ฉ์์ง ์ปค์คํฐ๋ง์ด์ง ์ง์
์ด ๊ฐ์์์๋ Spring๊ณผ MyBatis๋ฅผ ์ด์ฉํ์ฌ user ํ
์ด๋ธ ๊ธฐ๋ฐ ํ์๊ฐ์
๊ธฐ๋ฅ์ ๊ตฌํํ๊ณ , Validation์ ์ ์ฉํ๋ ๋ฐฉ๋ฒ์ ํ์ตํฉ๋๋ค.
Validation ์ฃผ์ ์ด๋
ธํ
์ด์
์ด๋
ธํ
์ด์
| ์ค๋ช
|
@NotNull | null ๊ฐ ๋ถํ |
@NotBlank | null, ๋น ๋ฌธ์์ด, ๊ณต๋ฐฑ๋ง์ผ๋ก ์ด๋ฃจ์ด์ง ๋ฌธ์์ด ๋ถํ |
@Size | ๋ฌธ์์ด, ๋ฐฐ์ด์ ๊ธธ์ด ๊ฒ์ฆ (min, max ์์ฑ) |
@Email | ์ด๋ฉ์ผ ํ์ ๊ฒ์ฆ |
@Past | ๊ณผ๊ฑฐ ๋ ์ง๋ง ํ์ฉ |
@Future | ๋ฏธ๋ ๋ ์ง๋ง ํ์ฉ |
@Valid | ์ค์ฒฉ๋ ๊ฐ์ฒด์ ์ ํจ์ฑ ๊ฒ์ฌ ์คํ |
BidingResult ์ฃผ์ ๋ฉ์๋
๋ฉ์๋ | ์ค๋ช
|
hasErrors() | ์ด๋ค ์ข
๋ฅ๋ ์ค๋ฅ๊ฐ ์๋์ง ํ์ธ |
hasGlobalErrors() | ๊ฐ์ฒด ๋ ๋ฒจ์ ์ค๋ฅ๊ฐ ์๋์ง ํ์ธ |
hasFieldErrors() | ํ๋ ๋ ๋ฒจ์ ์ค๋ฅ๊ฐ ์๋์ง ํ์ธ |
getFieldError() | ํน์ ํ๋์ ์ฒซ ๋ฒ์งธ ์ค๋ฅ ๋ฉ์์ง ๋ฐํ |
getAllErrors() | ๋ชจ๋ ์ค๋ฅ ๋ชฉ๋ก ๋ฐํ |
DB ํ
์ด๋ธ ์ ์
CREATE TABLE `user` (
`no` INT AUTO_INCREMENT PRIMARY KEY,
`id` VARCHAR(64) UNIQUE,
`username` VARCHAR(100) UNIQUE,
`password` VARCHAR(100) NOT NULL,
`name` VARCHAR(100) NOT NULL,
`email` VARCHAR(100) NOT NULL,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
SQL
๋ณต์ฌ
DTO + Validation ์ด๋
ธํ
์ด์
์ด๋
ธํ
์ด์
| ์ค๋ช
|
@NotBlank | null ๋ฐ ๊ณต๋ฐฑ ๋ถํ |
@Size | ๊ธธ์ด ์ ์ฝ ์ค์ |
@Email | ์ด๋ฉ์ผ ํ์ ๊ฒ์ฆ |
User.java
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import java.util.Date;
public class User {
private Integer no;
@Size(min = 4, max = 64, message = "์์ด๋๋ 4์ ์ด์ 64์ ์ดํ๋ก ์
๋ ฅํ์ธ์.")
private String id;
@NotBlank(message = "์์ด๋๋ ํ์์
๋๋ค.")
private String username;
@NotBlank(message = "๋น๋ฐ๋ฒํธ๋ ํ์์
๋๋ค.")
private String password;
@NotBlank(message = "์ด๋ฆ์ ํ์์
๋๋ค.")
private String name;
@Email(message = "์ด๋ฉ์ผ ํ์์ด ์๋๋๋ค.")
@NotBlank(message = "์ด๋ฉ์ผ์ ํ์์
๋๋ค.")
private String email;
private Date createdAt;
private Date updatedAt;
}
Java
๋ณต์ฌ
Controller + Validation
UserController.java
@Controller
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/join")
public String joinForm(Model model) {
model.addAttribute("User", new User());
return "join";
}
@PostMapping("/join")
public String join(@Validated @ModelAttribute("User") User User,
BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "join";
}
userService.registerUser(User);
return "redirect:/login";
}
}
Java
๋ณต์ฌ
BindingResult ๋์ ๊ตฌ์กฐ
Spring์ Validation ์ฒ๋ฆฌ ๊ณผ์ ์์ BindingResult๋ ๋ค์๊ณผ ๊ฐ์ ์์๋ก ๋์ํฉ๋๋ค:
1.
์ ํจ์ฑ ๊ฒ์ฌ ์คํ: @Validated ์ด๋
ธํ
์ด์
์ด ๋ถ์ ๊ฐ์ฒด์ ๋ํด ๊ฒ์ฆ ์คํ
2.
์ค๋ฅ ์์ง: BindingResult ๊ฐ์ฒด๊ฐ ๊ฒ์ฆ ๊ณผ์ ์์ ๋ฐ์ํ ๋ชจ๋ ์ค๋ฅ ์ ๋ณด๋ฅผ ์์ง
โข
ํ๋ ์ค๋ฅ (Field Errors)
โข
๊ธ๋ก๋ฒ ์ค๋ฅ (Global Errors)
3.
์ค๋ฅ ์ฒ๋ฆฌ: bindingResult.hasErrors()๋ก ์ค๋ฅ ์กด์ฌ ์ฌ๋ถ ํ์ธ
โข
true ๋ฐํ ์ ํผ ํ์ด์ง๋ก ๋ค์ ์ด๋
โข
์ค๋ฅ ๋ฉ์์ง๋ ์๋์ผ๋ก Model์ ํฌํจ๋์ด ๋ทฐ๋ก ์ ๋ฌ
์์ ์ฝ๋ ๋์:
// 1. ํผ์์ ๋ฐ์ดํฐ ์ ์ถ
// 2. @Validated๋ก ๊ฒ์ฆ ์คํ
// 3. BindingResult์ ์ค๋ฅ ์ ๋ณด ์ ์ฅ
if (bindingResult.hasErrors()) {
// 4. ์ค๋ฅ ๋ฐ์ ์ ํผ ํ์ด์ง๋ก ๋ฆฌํด
// - ์ค๋ฅ ๋ฉ์์ง๊ฐ ์๋์ผ๋ก ๋ทฐ๋ก ์ ๋ฌ๋จ
// - form:errors ํ๊ทธ๋ฅผ ํตํด ์ค๋ฅ ํ์
return "join";
}
// 5. ๊ฒ์ฆ ํต๊ณผ ์ ์ ์ ์ฒ๋ฆฌ
Java
๋ณต์ฌ
JSP์์์ ์ค๋ฅ ํ์:
<form:errors path="username" cssClass="error" />
<!-- username ํ๋์ ์ค๋ฅ๊ฐ ์์ ๊ฒฝ์ฐ ๋ฉ์์ง ํ์ -->
HTML
๋ณต์ฌ
BindingResult์ ์๋ฌ ๋ฉ์์ง ์ฒ๋ฆฌ ๊ณผ์
BindingResult๊ฐ ํผ์ ์๋ฌ ๋ฉ์์ง๋ฅผ ์ ๋ฌํ๋ ๊ณผ์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
1.
์๋ฌ ๊ฐ์ง: Validation ์ด๋
ธํ
์ด์
๊ฒ์ฆ ์คํจ ์ ์๋ฌ ์ ๋ณด๊ฐ ์์ฑ๋จ
2.
์๋ฌ ์ ์ฅ: BindingResult ๊ฐ์ฒด์ ์๋ฌ ์ ๋ณด ์๋ ์ ์ฅ
โข
ํ๋ ์๋ฌ: FieldError ๊ฐ์ฒด๋ก ์ ์ฅ
โข
๊ธ๋ก๋ฒ ์๋ฌ: ObjectError ๊ฐ์ฒด๋ก ์ ์ฅ
3.
Model ์ ๋ฌ: Spring MVC๊ฐ ์๋์ผ๋ก BindingResult๋ฅผ Model์ ์ถ๊ฐ
โข
๋ณ๋์ model.addAttribute() ๋ถํ์
โข
๋ทฐ์์ ์๋์ผ๋ก ์ ๊ทผ ๊ฐ๋ฅ
4.
JSP ์ถ๋ ฅ: form:errors ํ๊ทธ๊ฐ ํด๋น ์๋ฌ ๋ฉ์์ง ํ์
โข
ํ๋๋ณ ์๋ฌ: <form:errors path="ํ๋๋ช
" />
โข
๊ธ๋ก๋ฒ ์๋ฌ: <form:errors path="*" />
// ์์: ์ปจํธ๋กค๋ฌ์์์ ์ฒ๋ฆฌ
@PostMapping("/join")
public String join(@Validated User user, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
// ์๋์ผ๋ก ์๋ฌ ์ ๋ณด๊ฐ ๋ทฐ๋ก ์ ๋ฌ๋จ
return "join";
}
// ๊ฒ์ฆ ํต๊ณผ์ ์ฒ๋ฆฌ
}
Java
๋ณต์ฌ
JSP์์๋ ๋ค์๊ณผ ๊ฐ์ด ์๋ฌ ๋ฉ์์ง๋ฅผ ํ์ํ ์ ์์ต๋๋ค:
<form:form modelAttribute="user">
<form:input path="username" />
<form:errors path="username" cssClass="error" />
<!-- ๋ชจ๋ ๊ธ๋ก๋ฒ ์๋ฌ ํ์ -->
<form:errors path="*" cssClass="error" />
</form:form>
HTML
๋ณต์ฌ
form:errors์ FieldError์ ๊ด๊ณ
form:errors ํ๊ทธ๋ BindingResult์ ์ ์ฅ๋ FieldError ๊ฐ์ฒด๋ก๋ถํฐ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ๊ฐ์ ธ์ ํ์ํฉ๋๋ค. ์ด ๊ณผ์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
1.
FieldError ์์ฑ: ๊ฒ์ฆ ์คํจ ์ Spring์ด ์๋์ผ๋ก FieldError ๊ฐ์ฒด ์์ฑ
โข
ํ๋๋ช
โข
๊ฑฐ์ ๋ ๊ฐ
โข
์๋ฌ ๋ฉ์์ง
2.
๋ฉ์์ง ๊ฒ์: form:errors ํ๊ทธ๊ฐ BindingResult์์ ํด๋น ํ๋์ FieldError๋ฅผ ์ฐพ์
3.
๋ฉ์์ง ์ถ๋ ฅ: FieldError์์ ์ค์ ๋ ๋ฉ์์ง๋ฅผ ํ๋ฉด์ ํ์
์์ ์ฝ๋:
// ์ปจํธ๋กค๋ฌ์์ FieldError ํ์ธ
if (bindingResult.hasFieldErrors("username")) {
FieldError error = bindingResult.getFieldError("username");
String message = error.getDefaultMessage(); // @NotBlank ๋ฑ์์ ์ค์ ํ ๋ฉ์์ง
}
Java
๋ณต์ฌ
JSP์์๋ ๊ฐ๋จํ ๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉ:
<form:errors path="username" /> <!-- username ํ๋์ ๋ชจ๋ ์๋ฌ ๋ฉ์์ง ํ์ -->
HTML
๋ณต์ฌ
MyBatis Mapper ์ค์
UserMapper.xml
<insert id="insertUser" parameterType="com.aloha.spring.dto.User">
INSERT INTO user (id, username, password, name, email)
VALUES (#{id}, #{username}, #{password}, #{name}, #{email})
</insert>
XML
๋ณต์ฌ
UserMapper.java
@Mapper
public interface UserMapper {
void insertUser(User User);
}
Java
๋ณต์ฌ
Service
โข
UserService.java
โข
UserServiceImpl.java
UserService.java
@Service
public interface UserService {
}
Java
๋ณต์ฌ
UserServiceImpl.java
@Service
public class UserServiceImpl implements UserService {
}
Java
๋ณต์ฌ
JSP ํผ ๊ตฌ์ฑ (spring form ํ๊ทธ)
join.jsp
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<h2>ํ์๊ฐ์
</h2>
<form:form modelAttribute="User" method="post" action="/join">
์์ด๋: <form:input path="id" />
<form:errors path="id" cssClass="error" /><br/>
์ฌ์ฉ์๋ช
: <form:input path="username" />
<form:errors path="username" cssClass="error" /><br/>
๋น๋ฐ๋ฒํธ: <form:password path="password" />
<form:errors path="password" cssClass="error" /><br/>
์ด๋ฆ: <form:input path="name" />
<form:errors path="name" cssClass="error" /><br/>
์ด๋ฉ์ผ: <form:input path="email" />
<form:errors path="email" cssClass="error" /><br/>
<button type="submit">ํ์๊ฐ์
</button>
</form:form>
HTML
๋ณต์ฌ
์์ ๋๋ ํฐ๋ธ ํ๊ทธ๋ฅผ ๋ช
์ํด์ผ Spring Form ํ๊ทธ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ด ๋๋ ํฐ๋ธ๊ฐ ์์ผ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค:
โข
form:form, form:input ๋ฑ์ ํ๊ทธ๋ฅผ ์ธ์ํ์ง ๋ชปํจ
โข
์ปดํ์ผ ์๋ฌ ๋ฐ์
โข
ํ์ด์ง ๋ ๋๋ง ์คํจ
Spring Form ํ๊ทธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๋ค์๊ณผ ๊ฐ์ ์ด์ ์ ์ ๊ณตํฉ๋๋ค:
โข
๋ชจ๋ธ ๊ฐ์ฒด์ ์๋ ๋ฐ์ธ๋ฉ
โข
์ ํจ์ฑ ๊ฒ์ฌ ์ค๋ฅ ๋ฉ์์ง ํ์ ๊ธฐ๋ฅ
โข
HTML ํผ ์์๋ค์ ๋ ์ฝ๊ฒ ์ฒ๋ฆฌ
โข
Spring์ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ ๊ธฐ๋ฅ๊ณผ ์๋ฒฝํ ํตํฉ
ํต์ฌ ์ ๋ฆฌ
์์ | ์ค๋ช
|
DTO | ์
๋ ฅ ๋ฐ์ดํฐ ๊ตฌ์กฐ ์ ์ ๋ฐ ์ ํจ์ฑ ๊ฒ์ฌ ์ค์ |
Controller | @Validated, BindingResult๋ก ์
๋ ฅ ๊ฒ์ฆ ์ฒ๋ฆฌ |
Service | ๋น์ฆ๋์ค ๋ก์ง ์ฒ๋ฆฌ |
MyBatis | DB ์ ์ฅ ์ฒ๋ฆฌ |
JSP | spring form ํ๊ทธ๋ก ์
๋ ฅ ๋ฐ ์ค๋ฅ ํ์ |