유효성 검사(validation): 입력 내용이 요건에 만족하는지 타당성을 확인하는 입력 체크
두가지로 나뉜다
단일 항목 검사: 입력 항목 하나에 대해 설정하는 입력 체크 기능
Form 클래스 등의 필드에 어노테이션을 부여해서 사용한다.
어노테이션 | 기능 설명 | 사용 예 |
---|---|---|
@NotNull | null 값이 아닌 것을 검증합니다. | @NotNull Integer no; |
@NotEmpty | 문자열이 null 혹은 공백문자("")가 아닌 것을 검증한다. | @NotEmpty String name; |
@NotBlank | 문자열이 null 혹은 공백(스페이스나 탭 등)이 아닌 것을 검증한다. | @NotBlank String name; |
@Max | 지정한 숫자 이하인 것을 검증한다. | #100 이하인 것을 검증 @Max(100) Integer price; |
@Min | 지정한 숫자 이상인 것을 검증한다. | #10 이상인 것을 검증 @Min(10) Integer age; |
@Size | 문자열이나 컬렉션(Collection)이 지정한 범위의 크기 내인 것을 검증한다. | #요소의 수가 0에서 10의 범위인 것을 검증(문자열은 문자열 길이, 컬렉션은 사이즈) @Size(min=0, max=10) List selected; |
@AssertTrue | 값이 true인 것을 검증한다. | @AssertTrue Boolean empty; |
@AssertFalse | 값이 false인 것을 검증한다. | @AssertFalse Boolean empty; |
@Pattern | 지정한 정규 표현과 일치하는 것을 검증한다. | #영숫자 검증 @Pattern(regexp="[a-zA-Z0-9]*") |
@Range | 지정한 숫자 범위 안에 있는 것을 검증한다. | #1 이상, 10 이하인 것을 검증 @Range(min=1, max=10) Integer point; |
@DecimalMax | 지정한 숫자 이하인 것을 검증한다. | #100.0 이하 검증(소수점 이하를 포함해서 검증할 때는 Max가 아니고 DecimalMax를 사용) @DecimalMax("100.0") BigDecimal val; |
@DecimalMin | 지정한 숫자 이상인 것을 검증한다. | #10.0 이상 검증(소수점 이하를 포함해서 검증할 때는 Min이 아니라 DecimalMin을 사용) @DeciamlMin("10.0") BigDecimal val; |
@Digits | 정수부와 소수부의 자릿수를 검증한다. | #정수부가 3, 소수부가 1인 것을 검증 @Digits(integer=3, fraction=1) BigDecimal val; |
@Future | 미래의 날짜인 것을 검증한다. | @Future Date date; |
@Past | 과거의 날짜인 것을 검증한다. | @Past Date date; |
@Valid | 중첩된 Form을 검증한다. | @Valid SampleForm sampleForm; |
@Length | 문자열 길이가 지정한 범위 안에 있는 것을 검증한다(문자열 전용 Size). | @Length(min=0, max=10) String name; |
문자열이 이메일 주소 형식인지 검증한다. | @Email String email; | |
@CreditCardNumber | 문자열이 신용카드 번호 형식인지 검증한다. | @CreditCardNumber String card; |
@URL | 문자열이 URL 형식인지 검증한다. | @URL String url; |
어노테이션 | null인 경우 | 공백 문자("")인 경우 | 스페이스나 탭인 경우 |
---|---|---|---|
@NotNull | 체크 에러 | 허가 | 허가 |
@NotEmpty | 체크 에러 | 체크 에러 | 허가 |
@NotBlank | 체크 에러 | 체크 에러 | 체크 에러 |
상관 항목 검사: 여러 필드에 대해 혼합해 체크하는 것
상관 항목 검사를 수행하는 두 가지 방법
1. Bean Validation을 사용하는 방법
2. 스프링 프레임워크에서 제공하는 Validator 인터페이스를 구현하는 방법
생략
package com.example.ch8.form;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.NotNull;
@Data
public class CalcForm {
@NotNull(message = "왼쪽: 숫자를 입력해주세요.")
@Range(min=1, max=10, message = "왼쪽: {min}~{max} 범위의 숫자를 입력해주세요.")
private Integer leftNum;
@NotNull(message = "오른쪽: 숫자를 입력해주세요.")
@Range(min=1, max=10, message = "오른쪽: {min}~{max} 범위의 숫자를 입력해주세요.")
private Integer rightNum;
}
package com.example.ch8.controller;
import com.example.ch8.form.CalcForm;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
@Controller
public class ValidationController {
// form-backing bean 초기화
@ModelAttribute
public CalcForm seUpForm() {
return new CalcForm();
}
// 입력 화면 표시
@GetMapping("show")
public String showView(){
// 반환값으로 뷰 이름을 돌려줌
return "entry";
}
}
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>입력 화면</title>
</head>
<body>
<form th:action="@{/calc}" method="post" th:object="${calcForm}">
<div>
<input type="text" th:field="*{leftNum}">
+
<input type="text" th:field="*{rightNum}">
</div>
<input type="submit" value="계산">
</form>
</body>
</html>
@PostMapping("calc")
public String confirmView(@Validated CalcForm form, BindingResult bindingResult, Model model){
// 입력 체크에서 에러가 발생한 경우
if (bindingResult.hasErrors()){
// 입력 화면으로
return "entry";
}
// 값 더하기
Integer result = form.getLeftNum() + form.getRightNum();
// Model에 저장
model.addAttribute("result", result);
// 확인 화면으로
return "confirm";
}
<!--에러 표시-->
<ul th:if="${#fields.hasErrors('*')}">
<li th:each="err:${#fields.errors('*')}" th:text="${err}"></li>
</ul>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>확인 화면</title>
</head>
<body>
<h2>계산 결과</h2>
<h3>[[${calcForm.leftNum}]]+[[${calcForm.rightNum}]]=[[${result}]]</h3>
</body>
</html>
일반적으로 애플리케이션에서 표시하는 메시지는 프로그램과 별도로 관리한다.
메시지를 템플릿에서 분리해 메시지만 프로퍼티 파일로 관리하는 편이 유지 관리가 편리하기 때문
# entry 화면용
title.entry=입력 화면
button.send=계산
# CalcForm용
calcForm.leftNum=왼쪽
calcForm.rightNum=오른쪽
<!DOCTYPE html>
<html xmlns:th ="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title th:text="#{title.entry}">제목</title>
</head>
<body>
<form th:action="@{/calc}" method="post" th:object="${calcForm}">
<div>
<input type="text" th:field="*{leftNum}">
+
<input type="text" th:field="*{rightNum}">
</div>
<button type="submit" th:text="#{button.send}"></button>
<!-- 에러 표시 -->
<ul th:if="${#fields.hasErrors('*')}">
<li th:each="err:${#fields.errors('*')}" th:text="${err}"></li>
</ul>
</form>
</body>
</html>
# 단일 항목 검사용 메시지
javax.validation.constraints.NotNull.message={0}: 숫자를 입력해주세요.
org.hibernate.validator.constraints.Range.message={0}: {min}~{max} 범위에서 입력해주세요.
# 형변환 체크용 메시지
typeMismatch.java.lang.Integer={0}은 정수를 입력해주세요.
@Data
public class CalcForm {
@NotNull
@Range(min=1,max=10)
private Integer leftNum;
@NotNull
@Range(min=1,max=10)
private Integer rightNum;
}
Validator 인터페이스를 구현하는 커스텀 유효성 검사기를 만드는 절차는 다음과 같다.
1. 스프링 프레임워크가 제공하는 Validator 인터페이스를 구현하는 커스텀 유효성 검사기를 생성
2. 컨트롤러에 앞에서 만든 커스텀 유효성 검사기를 주입(인젝션)하고 WebDataBinder 인터페이스의 addValidator 메서드로 커스텀 유효성 검사기를 등록하여 스프링 MVC에서 이용할 수 있게 하기
package com.example.demo.validator;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import com.example.demo.form.CalcForm;
@Component
public class CalcValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
// 인수로 전달받은 Form이 입력 체크의 대상인지를 논리값으로 돌려줍니다.
return CalcForm.class.isAssignableFrom(clazz);
}
@Override
public void validate(Object target, Errors errors) {
// 대상 Form을 취득
CalcForm form = (CalcForm) target;
// 값이 입력되어 있는지 판단
if (form.getLeftNum() != null && form.getRightNum() != null) {
// 왼쪽 입력값이 홀수이고 오른쪽 입력값이 짝수가 아닌 경우
if (!((form.getLeftNum() % 2 == 1) && (form.getRightNum() % 2 == 0))) {
// 에러인 경우에는 인수 Errors 인터페이스의 reject 메서드에
// 에러 메시지의 키를 지정합니다.
errors.reject("com.example.demo.validator.CalcValidator.message");
}
}
}
}
# 커스텀 유효성 검사용
com.example.demo.validator.CalcValidator.message=왼쪽에는 홀수를, 오른쪽에는 짝수를 입력해주세요.
컨트롤러인 ValidationController에 커스텀 유효성 검사기를 추가
/** 주입(인젝션) */
@Autowired
CalcValidator calcValidator;
/** 커스텀 유효성 검사기 등록 */
@InitBinder("calcForm")
public void initBinder(WebDataBinder webDataBinder){
webDataBinder.addValidators(calcValidator);
}