Search
Duplicate

Spring Validation

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๋Š” ๋ฐ˜๋“œ์‹œ @Validated ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ”๋กœ ๋‹ค์Œ์— ์œ„์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ˆœ์„œ๊ฐ€ ๋‹ค๋ฅผ ๊ฒฝ์šฐ ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

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
๋ณต์‚ฌ
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
์œ„์˜ ๋””๋ ‰ํ‹ฐ๋ธŒ ํƒœ๊ทธ๋ฅผ ๋ช…์‹œํ•ด์•ผ Spring Form ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด ๋””๋ ‰ํ‹ฐ๋ธŒ๊ฐ€ ์—†์œผ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค:
โ€ข
form:form, form:input ๋“ฑ์˜ ํƒœ๊ทธ๋ฅผ ์ธ์‹ํ•˜์ง€ ๋ชปํ•จ
โ€ข
์ปดํŒŒ์ผ ์—๋Ÿฌ ๋ฐœ์ƒ
โ€ข
ํŽ˜์ด์ง€ ๋ Œ๋”๋ง ์‹คํŒจ
Spring Form ํƒœ๊ทธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ด์ ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค:
โ€ข
๋ชจ๋ธ ๊ฐ์ฒด์™€ ์ž๋™ ๋ฐ”์ธ๋”ฉ
โ€ข
์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€ ํ‘œ์‹œ ๊ธฐ๋Šฅ
โ€ข
HTML ํผ ์š”์†Œ๋“ค์„ ๋” ์‰ฝ๊ฒŒ ์ฒ˜๋ฆฌ
โ€ข
Spring์˜ ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ ๊ธฐ๋Šฅ๊ณผ ์™„๋ฒฝํ•œ ํ†ตํ•ฉ

ํ•ต์‹ฌ ์ •๋ฆฌ

์š”์†Œ
์„ค๋ช…
DTO
์ž…๋ ฅ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ ์ •์˜ ๋ฐ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ์„ค์ •
Controller
@Validated, BindingResult๋กœ ์ž…๋ ฅ ๊ฒ€์ฆ ์ฒ˜๋ฆฌ
Service
๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ฒ˜๋ฆฌ
MyBatis
DB ์ €์žฅ ์ฒ˜๋ฆฌ
JSP
spring form ํƒœ๊ทธ๋กœ ์ž…๋ ฅ ๋ฐ ์˜ค๋ฅ˜ ํ‘œ์‹œ