본문 바로가기

학원/복기

[Spring] 스프링 검증(Spring Validation)

스프링 검증(Spring Validation)은 사용자 입력값에 대한 유효성 검사를 구현하기 위한 기능이다.

 

순서

1. validation-api 라이브러리를 프로젝트에 빌드 처리 - 메이븐 : pom.xml
2. HTML 태그 대신 Spring 태그를 사용하여 페이지 요청시 입력값이 전달되도록 뷰 작성
3. Controller 클래스의 요청 처리 메소드에서 전달값이 저장된 Command 객체를 저장하는 매개변수에 @Valid 어노테이션을 사용하여 Command 객체를 생성하는 VO 클래스에서 유효성 검증이 되도록 설정

 

 

DTO 클래스

@Data
public class Employee {
	//@NotNull : 전달값이 [null]인 경우 에러를 발생하는 어노테이션
	//@NotBlank : 전달값이 [null]이거나 전달값에 공백이 있는 경우 에러를 발생하는 어노테이션
	//@NotEmpty : 전달값이 [null]이거나 [""] 경우 에러를 발생하는 어노테이션
	// => 에러 발생시 기본적인 메세지를 제공받아 뷰에게 전달
	//message 속성 : 뷰에게 전달할 에러 메세지를 속성값으로 설정
	@NotEmpty(message = "아이디를 입력해 주세요.")
	//@Size : 전달값의 크기를 비교하여 에러를 발생하는 어노테이션
	//min 속성 : 전달값의 최소 크기를 속성값으로 설정
	//max 속성 : 전달값의 최대 크기를 속성값으로 설정
	//@Size(min = 6, max = 20, message = "아이디는 최소 6자 이상 최대 20자 이하로만 입력해 주세요.")
	//@Pattern : 정규표현식의 패턴과 같지 않은 경우 에러를 발생하는 어노테이션
	//regexp 속성 : 전달값의 패턴을 비교하기 위한 정규표현식을 속성값으로 설정
	@Pattern(regexp = "^[a-zA-Z]\\w{5,19}$", message = "아이디를 형식에 맞게 입력해 주세요.")
	private String id;
	@NotEmpty(message = "비밀번호를 입력해 주세요.")
	@Pattern(regexp = "^(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[~!@#$%^&*_-]).{6,20}$", message = "비밀번호를 형식에 맞게 입력해 주세요.")
	private String passwd;
	@NotEmpty(message = "이름을 입력해 주세요.")
	private String name;
	@NotEmpty(message = "이메일을 입력해 주세요.")
	//@Email : 이메일 형식이 틀린 경우 에러를 발생하는 어노테이션
	@Email(message = "이메일을 형식에 맞게 입력해 주세요.")
	private String email;
	@NotEmpty(message = "성별을 입력해 주세요.")
	private String gender;
}

 

 

1. validation-api 라이브러리를 프로젝트에 빌드 처리 

 

https://mvnrepository.com/artifact/javax.validation/validation-api/2.0.1.Final

https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator/6.2.5.Final

 

 

 

2. HTML 태그 대신 Spring 태그를 사용하여 페이지 요청시 입력값이 전달되도록 뷰 작성

 

html_form.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%-- JavaScript(jQuery)를 이용하여 사용자 입력값의 검증 - 클라이언트 --%>    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SPRING</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<style type="text/css">
.error {
	color: red;
}
</style>
</head>
<body>
	<h1>사원등록</h1>
	<hr>
	<c:url value="/valid/html" var="url"/>
	<form action="${url}" method="post" id="joinForm">
	<table>
		<tr>
			<td>아이디</td>
			<td>
				<input type="text" name="id" id="id" value="${employee.id }">
				<span id="idMsg" class="error">${idMsg }</span>
			</td>
		</tr>
		<tr>
			<td>비밀번호</td>
			<td>
				<input type="password" name="passwd" id="passwd">
				<span id="passwdMsg" class="error"></span>
			</td>
		</tr>
		<tr>
			<td>이름</td>
			<td>
				<input type="text" name="name" id="name">
				<span id="nameMsg" class="error"></span>
			</td>
		</tr>
		<tr>
			<td>이메일</td>
			<td>
				<input type="text" name="email" id="email">
				<span id="emailMsg" class="error"></span>
			</td>
		</tr>
		<tr>
			<td>성별</td>
			<td>
				남자<input type="radio" name="gender" value="남자" class="gender">&nbsp;&nbsp;
				여자<input type="radio" name="gender" value="여자" class="gender">
				<span id="genderMsg" class="error"></span>
			</td>
		</tr>
		<tr>
			<td colspan="2">
				<button type="submit">등록</button>
			</td>
		</tr>
	</table>
	</form>
	
	<script type="text/javascript">
	$("#joinForm").submit(function() {
		var submitResult=true;
		
		$(".error").hide();

		/*	
		var idReg=/^[a-zA-Z]\w{5,19}$/g;
		if($("#id").val()=="") {
			$("#idMsg").html("아이디를 입력해 주세요.");
			
			submitResult=false;
		} else if(!idReg.test($("#id").val())) {
			$("#idMsg").html("아이디를 형식에 맞게 입력해 주세요.").show();
			submitResult=false;
		}
		*/
		
		var passwdReg=/^(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[~!@#$%^&*_-]).{6,20}$/g;
		if($("#passwd").val()=="") {
			$("#passwdMsg").html("비밀번호를 입력해 주세요.");
			submitResult=false;
		} else if(!passwdReg.test($("#passwd").val())) {
			$("#passwdMsg").html("비밀번호를 형식에 맞게 입력해 주세요.");
			submitResult=false;
		} 
		
		if($("#name").val()=="") {
			$("#nameMsg").html("이름을 입력해 주세요.");
			submitResult=false;
		}
		
		var emailReg=/^([a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+(\.[-a-zA-Z0-9]+)+)*$/g;
		if($("#email").val()=="") {
			$("#emailMsg").html("이메일을 입력해 주세요.");
			submitResult=false;
		} else if(!emailReg.test($("#email").val())) {
			$("#emailMsg").html("이메일을 형식에 맞게 입력해 주세요.");
			submitResult=false;
		}
		
		if($(".gender").filter(":checked").length == 0) {
			$("#genderMsg").html("성별을 선택해 주세요.");
			submitResult=false;
		}
		
		$(".error").show();
		
		return submitResult;
	});
	</script>
</body>
</html>

 

spring_form.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%-- Spring 프레임워크에서 제공하는 폼태그 라이브러리 포함 --%>
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SPRING</title>
<style type="text/css">
.error {
	color: red;
}
</style>
</head>
<body>
	<h1>사원등록</h1>
	<hr>
	<c:url value="/valid/spring" var="url"/>
	<%-- Spring Form 태그 : 페이지를 요청하여 입력값을 전달하는 태그 --%>
	<%-- modelAttribute 속성(필수) : 요청 처리 메소드 매개변수에 저장된 Command 객체의 속성명을 속성값으로 설정 --%>
	<%-- => 유효성 검증 실패시 사용자 입력값이 저장된 Command 객체를 제공받아 사용 --%>
	<form:form action="${url }" method="post" modelAttribute="employee">
	<table>
		<tr>
			<td>아이디</td>
			<td>
				<%-- Spring input 태그 : 문자열을 입력받기 위한 태그 --%>
				<%-- => input 태그의 type 속성값을 [text]로 설정하는 것과 동일 --%>
				<%-- path 속성 : 값을 전달하기 위한 이름을 속성값으로 설정 --%>
				<%-- => input 태그의 name 속성값과 id 속성값을 동시에 설정하는 것과 동일 --%>
				<%-- => 유효성 검증이 실패하는 경우 value 속성값을 설정하는 것과 동일 --%>
				<form:input path="id"/>
				<%-- Spring errors 태그 : 에러메세지를 제공받아 출력하는 태그 --%>
				<%-- path 속성 : 에러메세지를 제공받아 출력하기 위한 식별자(전달값의 이름)를 속성값으로 설정 --%>
				<%-- cssClass 속성 : 에러메세지를 출력하기 위한 CSS 스타일의 클래스 선택자를 속성값으로 설정 --%>
				<%-- element 속성 : 에러메세지를 출력하기 위한 태그를 속성값으로 설정  --%>
				<%-- delimiter 속성 : 에러메세지가 여러개인 경우 구분하기 위한 구분자를 속성값으로 설정 - 기본 구분자 : <br> --%>
				<form:errors path="id" cssClass="error" element="span" delimiter=" "/>
			</td>
		</tr>
		<tr>
			<td>비밀번호</td>
			<td>
				<%-- Spring password 태그 : 문자열을 입력받기 위한 태그 --%>
				<%-- => input 태그의 type 속성값을 [password]로 설정하는 것과 동일 --%>
				<form:password path="passwd"/>
				<form:errors path="passwd" cssClass="error" element="span" delimiter=" "/>
			</td>
		</tr>
		<tr>
			<td>이름</td>
			<td>
				<form:input path="name"/>
				<form:errors path="name" cssClass="error" element="span" delimiter=" "/>
			</td>
		</tr>
		<tr>
			<td>이메일</td>
			<td>
				<form:input path="email"/>
				<form:errors path="email" cssClass="error" element="span" delimiter=" "/>
			</td>
		</tr>
		<tr>
			<td>성별</td>
			<td>
				<%-- Spring radiobutton 태그 : 목록 중 하나를 선택하여 전달하기 위한 태그 --%>
				<%-- => input 태그의 type 속성값을 [radio]로 설정하는 것과 동일 --%>
				<%-- 
				남자<form:radiobutton path="gender" class="gender" value="남자"/>&nbsp;&nbsp;
				여자<form:radiobutton path="gender" class="gender" value="여자"/>
				--%>
				<%-- Spring radiobuttons 태그 : 목록 중 하나를 선택하여 전달하기 위한 태그 --%>
				<%-- => List 객체의 요소값을 제공받아 선택 가능 목록 제공 --%>
				<%-- items 속성 : List 객체(EL)를 속성값으로 설정 --%>
				<%-- <form:radiobuttons path="gender" items="${genderList }"/> --%>
				
				<%-- Spring select 태그 : 목록 중 하나를 선택하여 전달하기 위한 태그 --%>
				<%-- => select 태그와 option 태그를 설정하는 것과 동일 --%>
				<form:select path="gender" items="${genderList }"/>
				<form:errors path="gender" cssClass="error" element="span" delimiter=" "/>
			</td>
		</tr>
		<tr>
			<td colspan="2">
				<%-- Spring button 태그 : 제출 이벤트를 발생하기 위한 태그 --%>
				<%-- => button 태그의 type 속성값을 [submit]로 설정하는 것과 동일 --%>
				<form:button>등록</form:button>
			</td>
		</tr>
	</table>
	</form:form>
	<%-- 
	<script type="text/javascript">
	$("#joinForm").submit(function() {
		var submitResult=true;
		
		$(".error").hide();

		var idReg=/^[a-zA-Z]\w{5,19}$/g;
		if($("#id").val()=="") {
			$("#idMsg").html("아이디를 입력해 주세요.");
			
			submitResult=false;
		} else if(!idReg.test($("#id").val())) {
			$("#idMsg").html("아이디를 형식에 맞게 입력해 주세요.").show();
			submitResult=false;
		}
		
		var passwdReg=/^(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[~!@#$%^&*_-]).{6,20}$/g;
		if($("#passwd").val()=="") {
			$("#passwdMsg").html("비밀번호를 입력해 주세요.");
			submitResult=false;
		} else if(!passwdReg.test($("#passwd").val())) {
			$("#passwdMsg").html("비밀번호를 형식에 맞게 입력해 주세요.");
			submitResult=false;
		} 
		
		if($("#name").val()=="") {
			$("#nameMsg").html("이름을 입력해 주세요.");
			submitResult=false;
		}
		
		var emailReg=/^([a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+(\.[-a-zA-Z0-9]+)+)*$/g;
		if($("#email").val()=="") {
			$("#emailMsg").html("이메일을 입력해 주세요.");
			submitResult=false;
		} else if(!emailReg.test($("#email").val())) {
			$("#emailMsg").html("이메일을 형식에 맞게 입력해 주세요.");
			submitResult=false;
		}
		
		if($(".gender").filter(":checked").length == 0) {
			$("#genderMsg").html("성별을 선택해 주세요.");
			submitResult=false;
		}
		
		$(".error").show();
		
		return submitResult;
	});	
	--%>
</body>
</html>

 

result.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SPRING</title>
</head>
<body>
	<h1>사원정보확인</h1>
	<hr>
	<ul>
		<li>아이디 = ${employee.id }</li>
		<li>비밀번호 = ${employee.passwd }</li>
		<li>이름 = ${employee.name }</li>
		<li>이메일 = ${employee.email }</li>
		<li>성별 = ${employee.gender }</li>
	</ul>
</body>
</html>

 

 

3. Controller 클래스의 요청 처리 메소드에서 전달값이 저장된 Command 객체를 저장하는 매개변수에 @Valid 어노테이션을 사용하여 Command 객체를 생성하는 VO 클래스에서 유효성 검증이 되도록 설정

 

 

컨트롤러

package xyz.itwill10.controller;

import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;

import javax.validation.Valid;

import org.mindrot.jbcrypt.BCrypt;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import xyz.itwill10.dto.Employee;

//스프링 검증(Spring Validation) : 사용자 입력값에 대한 유효성 검사를 구현하기 위한 기능
//1.validation-api 라이브러리를 프로젝트에 빌드 처리 - 메이븐 : pom.xml
//2.HTML 태그 대신 Spring 태그를 사용하여 페이지 요청시 입력값이 전달되도록 뷰 작성
//3.Controller 클래스의 요청 처리 메소드에서 전달값이 저장된 Command 객체를 저장하는 매개변수에
//@Valid 어노테이션을 사용하여 Command 객체를 생성하는 VO 클래스에서 유효성 검증이 되도록 설정

@Controller
@RequestMapping("/valid")
public class ValidController {
	@RequestMapping(value = "/html", method = RequestMethod.GET)
	public String html() {
		return "valid/html_form";
	}
	
	@RequestMapping(value = "/html", method = RequestMethod.POST)
	public String html(@ModelAttribute Employee employee, Model model) {
		//전달값에 대한 입력값 검증 - 서버
		if(employee.getId() == null || employee.getId().equals("")) {
			model.addAttribute("idMsg", "아이디를 입력해 주세요.");
			return "valid/html_form";
		}
		
		String idReg="^[a-zA-Z]\\w{5,19}$";
		if(!Pattern.matches(idReg, employee.getId())) {
			model.addAttribute("idMsg", "아이디를 형식에 맞게 입력해 주세요.");
			return "valid/html_form";
		}
		
		employee.setPasswd(BCrypt.hashpw(employee.getPasswd(), BCrypt.gensalt()));
				
		return "valid/result";
	}
	
	//Spring Form 태그에서 사용하기 위한 Command 객체를 저장할 매개변수 선언
	@RequestMapping(value = "/spring", method = RequestMethod.GET)
	public String spring(@ModelAttribute Employee employee) {
		//List 객체를 생성하여 뷰에게 제공
		//model.addAttribute("genderList", Arrays.asList("남자", "여자"));
		return "valid/spring_form";
	}
	
	//@Valid  : Spring 태그에 의해 전달된 값을 Command 객체의 필드에 저장하기 전에 전달값에
	//대한 유효성 검증 기능을 제공하기 위한 어노테이션
	// => VO(DTO) 클래스의 필드에 유효성 검증 관련 어노테이션 사용 - hibernate-validator 
	//라이브러리를 프로젝트에 빌드 처리 - 메이븐 : pom.xml
	//Errors 객체 : 유효성 검증 후 발생되는 모든 에러 관련 정보를 저장하기 위한 객체
	@RequestMapping(value = "/spring", method = RequestMethod.POST)
	public String spring(@ModelAttribute @Valid Employee employee, Errors errors) {
		//Errors.hasErrors() : Errors 객체에 에러 관련 정보가 존재할 경우 [true]를 반환하는 메소드
		if(errors.hasErrors()) {
			//model.addAttribute("genderList", Arrays.asList("남자", "여자"));
			return "valid/spring_form";
		}
		
		employee.setPasswd(BCrypt.hashpw(employee.getPasswd(), BCrypt.gensalt()));

		return "valid/result";
	}
	
	//모든 요청 처리 메소드의 뷰에게 반환값을 제공하는 어노테이션
	@ModelAttribute("genderList")
	public List<String> genderList() {
		return Arrays.asList("남자", "여자");
	}
}

 

 

 

 

'학원 > 복기' 카테고리의 다른 글

[Spring] Spring Security 로그인 커스터마이징  (0) 2023.09.07
[Spring] Spring Security  (0) 2023.09.06
[Spring] @RestController - 수정  (0) 2023.08.19
[Spring] RESTful API  (0) 2023.08.19
[Spring] 자료실 만들기  (0) 2023.08.15