8-1 유효성 검사의 종류
뷰에 입력한 값에 대해 입력 체크를 수행하는 유효성 검사 기능에 관해 설명하겠습니다.
8-1-1 유효성 검사란?
입력 내용이 요건에 만족하는지 그 타당성을 확인하는 입력 체크를 말합니다.
- 단일 항목 검사
- 상관 항목 검사(서로 관련이 있는 항목을 함께 체크하는 방법)
8-1-2 단일 항목 검사란?
입력 항목 하나에 대해 설정하는 입력 체크 기능입니다. Form 클래스 등의 필드에 어노테이션을 부여해서 사용
입력체크를 위한 어노테이션은 java EE에서 제공하는 어노테이션이나 하이버네이트 프레임워크에서 제공하는 어노테이션이 있다. 수치 입력항목에 알파벳 등의 문자열을 입력한 경우 등의 '형변환 체크'는 입력 체크를 설정하는 것만으로도 이용 할 수 있기 때문에 '형변환 체크'용 어노테이션을 추가할 필요가 없다.
어노테이션 | 기능 설명 | 사용 예 |
@NotNull | null 값이 아닌것을 검증 | @NotNull, Integer no; |
@NotEmpty | 문자열이 null 혹은 공백문자가 아닌 것을 검증 | @NotEmpty String name; |
@NotBlank | 문자열이 null 혹은 공백이 아닌것을 검증 | @NotBlank String name; |
@Max | 지정한 숫자 이하인 것을 검증 | @max(100) Integer price; |
@Min | 지정한 숫자 이상인 것을 검증 | @Min(10) Integer age; |
@Size | 문자열이나 컬렉션이 지정한 범위의 크기내인것을 검증 | @Size(min=10, max=10) List<Integer> selected; |
@AssetTrue | 값이 true인 것을 검증 | @AssertTrue Boolean empty; |
@AssertFalse | 값이 False인것을 검증 | @AssertFalse Boolean empty; |
@Patten | 지정한 정규 표현과 일치하는 것을 검증 | #영숫자 검증 @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 | 지정한 숫자 이상인것을 검증 | #100.0 이상 검증(소수점 이하를 포함해서 검증할 때는 Min가 아니고 DecimalMin를 사용) @DecimalMin("100.0") BigDecimal val; |
@Digits | 정수부와 소수부의 자릿수를 검증 | #정수부가 3, 소수부가 1인것을 검증 @Digits(integer=3, fraction=1) BigDecimal val; |
@Future | 미래의 날짜인것을 검증 | @Future Date date; |
@Past | 과거의 날짜인 것을 검증 | @Past Date date; |
@Valid | 중첩된 Form을 검증 | @Vaild SampleForm smapleForm; |
문자열이 이메일 주소 형식인지 검증 | @Email String email; |
|
@CreditCardNumber | 문자열이 신용카드 번호 형식인지 검증 | @CreditCardNumber String card; |
@URL | 문자열이 URL인지 검증 | @URL @String url; |
8-1-3 커스텀 유효성 검사란?
단일 항목 검사는 하나의 필드를 체크합니다. 여러필드에 대해 혼합해서 체크하는 것을 상관 항목검사라고 합니다.
상관 항목 검사 두종류
- Bean Validation을 사용하는 방법
- 스프링 프레임워크에서 제공하는 Validator 인터페이스를 구현하는 방법
8-2 단일 항목 검사를 사용하는 프로그램만들기
단일 항목 검사를 사용해서 뷰에 입력한 값에 대해 유효성검사를 수행하는 프로그램을 만들겠습니다.
8-2-2 애플리케이션 레이어 생성
-.Form 클래스 생성
package com.example.demo.form;
import javax.validation.constraints.NotNull;
import org.hibernate.validator.constraints.Range;
import lombok.Data;
@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.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import com.example.demo.form.CalcForm;
@Controller
public class ValidationController {
@ModelAttribute
public CalcForm setUpForm() {
return new CalcForm();
}
@GetMapping("show")
public String showView() {
// 반환값으로 뷰 이름을 돌려줌
return "entry";
}
-. 뷰 생성
<!DOCTYPE html>
<html 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>
8~15번째 줄에서 th:object 속성을 설정하고 값을 Model에 저장된 Form 클래스의 소문자 카멜케이스이름을 설정 Form 클래스의 필드와 관계를 설정하기 위해 th:field 속성에 *{필드명}을 설정합니다. th:field 속성을 사용하면 HTML로 표시되었을때 id속성, name속성, value속성이 생성됩니다.
-. 컨트롤러에 추가
@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";
}
3번째 줄 @Validated 어노테이션을 단일 항목 검사 어노테이션을 설정한 Form 클래스에 부여하면 유효성 검사가 실행
실행한 결과는 BindingResult 인터페이스에 보관
6~9번째 줄과 같이 BindingResult 인터페이스의 hasErrors 메서드의 반환값으로 에러의 유무를 확인 에러가 발생한 경우에는 입력 화면으로 이동
유효성 검사를 실행할때 @Validated 어노테이션을 부여한 클래스와 BindingResult인터페이스를 함께 인수를 사용하고 @Validated -> BindingResult 순으로 사용
-. 뷰에 추가
<!-- 에러 표시 -->
<ul th:if="${#fields.hasErrors('*')}">
<li th:each="err:${#fields.errors('*')}" th:text="${err}"></li>
</ul>
<form> 태그 안에서 에러를 표시하고 싶은곳에 위의 내용을 추가
2번째 줄의 '#fileds.hasErrors' 메서드에서 에러가 발생했는지 판단
3번째 줄의 '#fileds.errors' 메서드에서 에러 메시지를 배열로 돌려주기 때문에 'th:each속성'을 이용해서 표시
모든필드의 에러를 받아서 출력하기 때문에 '#fileds.errors'메서드의 인수로 '*'를 전달 했지만 특정필드의 에러를 받아서 출력하고 싶을때는 인수에 '필드명'을 설정
-. 뷰 생성(확인 화면)
<!DOCTYPE html>
<html 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>
9번째 줄의 calcForm을 이용해'객체.필드'에 저장된 결과를 표시하고 result에 계산 결과를 표시
8-3 메시지 관리에 대해 알아보기
애플리케이션에서 표시하는 메시지는 프로그램과 별도로 관리 프로퍼티 파일의 사용법에 대해 배우겠습니다.
8-3-1 일반적인 메시지 관리
메시지는 프로그램과 별도로 관리합니다. 그렇게 하는 이유로는 메시지를 템플릿에서 분리해서 메시지만 프로퍼티 파일로 관리하는 편이 유지관리가 편리하기 때문
8-3-2 스프링 부트에서 메시지 관리하기
-. meassges.properties 생성
# entry 화면용
title.entry=입력 화면
button.send=계산
# CalcForm용
calcForm.leftNum=왼쪽
calcForm.rightNum=오른쪽
messages.propoerties 는 '키=값'의 형태로 프로퍼티를 정의
-. 뷰 수정
<!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>
-. ValidationMessanges.properties 생성
# 단일 항목 검사용 메시지
javax.validation.constraints.NotNull.message={0}: 숫자를 입력해주세요.
org.hibernate.validator.constraints.Range.message={0}: {min}~{max} 범위에서 입력해주세요.
# 형변환 체크용 메시지
typeMismatch.java.lang.Integer={0}은 정수를 입력해주세요.
단일 항목 검사 어노테이션과 메시지에 대응하기 위해서는 어노테이션의 FQCN.message가 메시지를 취득하기 위한 키
여기서 FQCN이란 '클래스가 속한 패키지명을 모두 포함한 이름'이라는 뜻입니다. 메시지중에서'{수치}'는 자리 표시자로서, 0부터 시작하는 수치에는 화면상의 항목이름이 설정 {min} 등의 영어에는 어노테이션의 속성에 지정된 값이 설정 또한 형변환 검사의 메시지는 'type.Missmatch.클래스의 FQCN'의 키로 설정합니다.
-. Form 클래스 수정
package com.example.demo.form;
import javax.validation.constraints.NotNull;
import org.hibernate.validator.constraints.Range;
import lombok.Data;
@Data
public class CalcForm {
@NotNull
@Range(min = 1, max = 10)
private Integer leftNum;
@NotNull
@Range(min = 1, max = 10)
private Integer rightNum;
}
8-4 커스텀 유효성 검사기를 사용하는 프로그램 만들기
스프링 프레임워크가 제공하는 Validator 인터페이스를 구현해서 커스텀 유효성 검사기를 만들겠습니다. 좌측입력항목이 홀수 이고 우측항목이 짝수가 아니면 에러가 발생하는 커스텀 유효성 검사기입니다.
8-4-1 커스텀 유효성 검사기 생성
-. Validator 생성
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");
}
}
}
}
9번째 줄 @Component 어노테이션을 클래스에 부여해서 인스턴스 생성 대상으로 지정
12~15번째 줄의 supports 메서드에서 인수를 전달된 Form이 입력 체크의 대상인지를 논리값으로 반환
18~31번째 줄의 validate 메서드에서 인수를 전달된 Object 타입의 target을 CalcForm 타입으로 변환해서 커스텀 유효성 검사를 수행 에러인 경우에는 인수로 전달된 Errors 타입의 errors의 reject 메서드에 메시지 키를 지정
-. meessages.propertes에 추가
# 커스텀 유효성 검사용
com.example.demo.validator.CalcValidator.message=왼쪽에는 홀수를, 오른쪽에는 짝수를 입력해주세요.
-. 컨트롤러에 추가
// 주입(인젝션)
@Autowired
CalcValidator calcValidator;
// 커스텀 유효성 검사기 등록
@InitBinder("calcForm")
public void initBinder(WebDataBinder webDataBinder){
webDataBinder.addValidators(calcValidator);
}
2~3번째 줄에서는 컨트롤러에 앞에서 만든 커스텀 유효성 검사기인 CalcValidator를 주입
6~9번째 줄에서는 @InitBinder 어노테이션을 부여한 메서드에 커스텀 유효성 검사기를 등록 @InitBinder 어노테이션에는 체크 대상 Form 클래스의 Model에 식별명을 지정합니다. '식별명'을 지정하지 않는 경우 Model에 저장되는 모든 객체에 대해 적용되어 유효성 검사를 통과하지 못하면 예외가 발생 WebDataBinder 인터페이스의 addValidators 메서드에 커스텀유효성 검사기를 등록하면 스프링 MVC에서 이용할 수 있습니다.
'북스터디 > 스프링 프레임워크 첫걸음' 카테고리의 다른 글
9장 애플리케이션 만들기 (0) | 2023.04.25 |
---|---|
7장 요청 파라미터 취득하기 (0) | 2023.04.12 |
5장 MVC 모델 알아보기 (0) | 2023.04.09 |
4장 데이터베이스 작업 (0) | 2023.04.02 |
3장 스프링 프레임워크의 핵심 기능 알아보기 (0) | 2023.03.26 |