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 νƒœκ·Έλ‘œ μž…λ ₯ 및 였λ₯˜ ν‘œμ‹œ