게시물을 등록하기 전(폼(form)을 전송(Submit) 하기 전)에 입력한 데이터가 정확한지 Validation(밸리데이션)하여 입력값이 정확하지 않으면 사용자에게 알려주어 다시 입력하게 하는 것을 Client-Side Validation이라고 합니다.
이전에서 처리한 등록 버튼 script처럼 단순하게 입력란에 입력한 데이터가 있는지만 판단하는 정도라면 JavaScript Validation API를 사용하여 처리할 수 있습니다.
JavaScript Validation API는 입력한 데이터의 유무뿐만 아니라 입력한 데이터의 길이가 긴지 짧은지, 패턴과 일치하는지, 숫자가 아닌 문자가 있는지, 숫자가 큰지 작은지 검사할 수 있습니다.
JavaScript Validation API는 DOM 지원하는 모든 웹 브라우저에서 지원됩니다.
그럼 JavaScript Validation API를 사용하여 form(폼)에 있는 입력 요소들이 유효한 데이터를 가지고 있는지 검사해 보도록 하겠습니다.
JavaScript Validation API에서 제공하는 DOM 메서드인 checkValidity() 메서드를 사용하면 검사할 수 있습니다.
checkValidity() 메서드는 입력 요소의 속성 정보를 사용하여 입력한 데이터가 있는지, 데이터의 길이가 긴지 짧은지, 패턴과 일치하는지, 숫자가 아닌 문자가 있는지, 숫자가 큰지 작은지 검사하고 Boolean(부울) 값으로 리턴합니다.
checkValidity() 메서드는 입력 요소에 required 속성이 있어야 검사를 진행하게 되어 있습니다. 즉, 필수 입력 요소들만 검사하게 됩니다.
checkValidity() 메서드가 실행되면 JavaScript Validation API에서 제공하는 DOM 속성인 validity 속성에 유효성별로 검사 결과가 Boolean(부울) 값으로 적용되어 리턴됩니다. 그리고 validity에 있는 유효성 속성 중에 false가 있으면 DOM 속성인 validationMessage 속성에 웹 브라우저에서 출력되는 유효성 검사 메시지가 리턴됩니다.
그럼 테스트를 통해 checkValidity() 메서드와 validity 속성, validationMessage 속성에 대해 알아보겠습니다.
Maven Spring Project에 JavaScript Validation API 적용하기
1. /src/main/webapp/WEB-INF/views/board/boardform.jsp 파일을 오픈하고 게시물 적성 시 필수 입력 요소인 작성자(registrationId)와 subject(제목) <form:input> 태그에 required 속성을 추가합니다.
<form:form modelAttribute="board" autocomplete="off">
<table>
<colgroup>
<col style="width:18.5%">
<col style="width:auto">
</colgroup>
<tbody>
<tr>
<th scope="row">작성자</th>
<td><form:input path="registrationId" placeholder="아이디를 입력하세요." required="required" /></td>
</tr>
<tr>
<th scope="row">제목</th>
<td><form:input path="subject" placeholder="제목을 입력하세요." required="required" /></td>
</tr>
<tr>
<th scope="row">내용</th>
<td><form:textarea path="content" placeholder="내용을 입력하세요." rows="10"/></td>
</tr>
</tbody>
</table>
</form:form>
2. <script>에서 기존 등록 버튼에 있는 script는 주석처리하고 테스트를 위해 작성자(registrationId)에 checkValidity() 메서드를 적용합니다.
- required 속성은 필수 입력 요소를 나타내는 것이기 때문에 입력란에 데이터가 입력되지 않으면 checkValidity() 메서드는 false를 리턴하게 됩니다.
- checkValidity() 메서드의 리턴 값이 false이면 DOM 속성인 validationMessage(DOM 속성인 validity에 있는 유효성 속성 중에 false가 있을 때 웹 브라우저에서 출력되는 유효성 검사 메시지)를 알럿으로 보겠습니다.
$(function() {
$('#saveBtn').click(function() {
/*
var registrationId = $('#registrationId').val();
if (registrationId == null || registrationId == "") {
alert("아이디를 입력하세요.");
$("#registrationId").focus();
return;
}
var subject = $('#subject').val();
if (subject == null || subject == "") {
alert("제목을 입력하세요.");
$("#subject").focus();
return;
}
$('#board').attr("action", "/board/addboard.do");
$('#board').submit();
*/
if (!$('#registrationId')[0].checkValidity()) {
alert($('#registrationId')[0].validationMessage);
}
});
});
Maven Spring Project를 실행하여 웹 브라우저로 확인하기
1. "Servers"탭에서 "Tomcat9"를 선택하고 "start"버튼(start the server)을 클릭하면 Tomcat이 실행됩니다.
2. 웹 브라우저에서 "http://localhost:9000/index.do"를 입력하고 등록 버튼을 클릭하면 게시물 입력 폼(/board/addform.do)으로 이동됩니다.
3. 등록 버튼을 누르면 checkValidity() 메서드가 실행되면서 메시지가 알럿으로 보입니다.
그럼 기존 등록 버튼에 있는 script에 DOM 속성인 validity를 콘솔로 출력해서 어떤 유형별로 되어 있는지 확인해 보겠습니다.
if (!$('#registrationId')[0].checkValidity()) {
alert($('#registrationId')[0].validationMessage);
}
console.log($('#registrationId')[0].validity);
validity를 콘솔로 출력하면 ValidityState로 나타납니다.
작성자(registrationId)에 입력된 데이터가 없으면 valid가 false가 되고 valueMissing이 true가 됩니다.
- valid : 입력 요소에 값이 유효하면 true, 유효하지 않으면 false를 리턴합니다.
- valueMissing : 입력 요소 속성에 required가 있는데 입력된 데이터가 없으면 true, 있으면 false를 리턴합니다.
작성자(registrationId)에 입력된 데이터가 있으면 valid가 true가 되고 valueMissing이 false가 됩니다.
작성자(registrationId)에 입력되는 데이터가 최소 2자 이상이고 최대 20자 이하로 되게 작성자(registrationId)의 <form:input> 태그에 minlength 속성과 maxlength 속성을 추가합니다.
<tr>
<th scope="row">작성자</th>
<td><form:input path="registrationId" placeholder="아이디를 입력하세요." minlength="2" maxlength="20" required="required" /></td>
</tr>
새로고침 후 작성자(registrationId)에 "1"를 입력하고 등록 버튼을 누릅니다.
콘솔에서 validity를 확인해 보면 작성자(registrationId)에 입력된 데이터가 1글자 이기 때문에 tooShort가 true가 되고 valid가 false가 됩니다.
- tooLong : 입력 요소(input type='text', textarea) 속성에 maxlength가 있고 입력 값 길이가 maxlength 보다 크면 true를 작거나 같으면 false를 리턴합니다.
- tooShort : 입력 요소(input type='text', textarea) 속성에 minlength가 있고 입력 값 길이가 minlength 보다 작으면 true를 크거나 같으면 false를 리턴합니다.
<input type='text'> 태그나 <textarea> 태그에서 maxlength가 설정되면 웹 브라우저에서 입력되는 데이터가 maxlength보다 크게 입력이 되지 않게 제어되기 때문에 tooLong 속성이 true가 나오지 않습니다.
그럼 다른 유형들도 테스트를 통해서 알아보겠습니다.
테스트를 위해 바탕화면에 test.html를 생성하였습니다.
숫자만 입력할 수 있는 <input type="number"> 태그로 최소 1부터 최대 100까지 설정할 수 있게 하고 score 버튼을 눌러 검사하도록 코딩합니다.
<input id="score" type="number" min="1" max="100" required="required">
<button onclick="myScore()">Score</button>
<script>
function myScore() {
const scoreObject = document.getElementById("score");
if (!scoreObject.checkValidity()) {
console.log(scoreObject.validity);
alert(scoreObject.validationMessage);
}
}
</script>
test.html를 웹 브라우저에서 실행하고 입력란에 "0"를 입력한 후 Score 버튼을 누릅니다.
콘솔에서 validity를 확인해 보면 score에 입력된 숫자가 0 이기 때문에 rangeUnderflow가 true가 되고 valid가 false가 됩니다.
- rangeUnderflow : 입력 요소(Input type='number') 속성에 min이 있고 min 보다 작으면 true를 크거나 같으면 false를 리턴합니다.
- rangeOverflow : 입력 요소(Input type='number') 속성에 max이 있고 max 보다 크면 true를 작거나 같으면 false를 리턴합니다.
입력란에 "101"를 입력한 후 Score 버튼을 누릅니다.
콘솔에서 validity를 확인해 보면 score에 입력된 숫자가 101 이기 때문에 rangeOverflow가 true가 되고 valid가 false가 됩니다.
만약 입력란에 숫자가 아닌 문자를 입력하고 Score 버튼을 누르면 badInput이 true가 되고 valid가 false가 됩니다.
- badInput : 입력 요소(Input type='number')에 숫자가 아닌 문자가 있으면 true를 숫자면 false를 리턴합니다.
만약 step이 2로 설정되어 있다면 다음에 증가할 숫자는 현재의 숫자보다 2가 커야 합니다. 그러나 입력된 숫자가 다음에 증가할 step이 아닌 숫자가 오면 stepMismatch가 true가 되고 valid가 false가 됩니다.
<input id="score" type="number" min="1" max="100" step="2" required="required">
<button onclick="myScore()">Score</button>
<script>
function myScore() {
const scoreObject = document.getElementById("score");
if (!scoreObject.checkValidity()) {
console.log(scoreObject.validity);
alert(scoreObject.validationMessage);
}
}
</script>
만약 입력란에 "4"를 입력하고 Score 버튼을 누르면 stepMismatch가 true가 되고 valid가 false가 됩니다.
- stepMismatch : 입력 요소(Input type='number') 속성에 step이 있고 step으로 나눈 나머지가 있으면 true를 그렇지 않으면 false를 리턴합니다.
전화번호를 입력할 수 있는 <input type="tel"> 태그에 휴대폰 번호에 대한 pattern(패턴) 설정할 수 있게 하고 tel버튼을 눌러 검사하도록 코딩합니다.
<input id="tel1" type="tel" pattern="01[0|1|6|7|8|9]" required="required">
<input id="tel2" type="tel" pattern="[0-9]{3,4}" required="required">
<input id="tel3" type="tel" pattern="[0-9]{4}" required="required">
<button onclick="myTel()">tel</button>
<script>
function myTel() {
const tel1Object = document.getElementById("tel1");
if (!tel1Object.checkValidity()) {
console.log(tel1Object.validity);
alert(tel1Object.validationMessage);
}
}
</script>
test.html를 웹 브라우저에서 실행하고 tel1 입력란에 "111"를 입력한 후 tel 버튼을 누릅니다.
콘솔에서 validity를 확인해 보면 tel1에 입력된 숫자가 pattern(패턴)과 일치하지 않기 때문에 patternMismatch가 true가 되고 valid가 false가 됩니다.
- patternMismatch : 입력 요소(Input type='text, tel, email, url, password, search') 속성에 pattern(패턴)이 있고 pattern(패턴)과 일치하지 않으면 true를 일치하면 false를 리턴합니다.
email를 입력할 수 있는 <input type="email"> 태그에 데이터를 입력하여 email버튼을 눌러 검사하도록 코딩합니다.
<input id="email" type="email" required="required"/>
<button onclick="myEmail()">email</button>
<script>
function myEmail() {
const emailObject = document.getElementById("email");
if (!emailObject.checkValidity()) {
console.log(emailObject.validity);
alert(emailObject.validationMessage);
}
}
</script>
test.html를 웹 브라우저에서 실행하고 email 입력란에 "test.com"를 입력한 후 email 버튼을 누릅니다.
콘솔에서 validity를 확인해 보면 email에 입력된 데이터가 email pattern(패턴)과 다르기 때문에 typeMismatch가 true가 되고 valid가 false가 됩니다.
- typeMismatch : 입력 요소(Input type='email, url')에 pattern(패턴)과 일치하지 않으면 true를 일치하면 false를 리턴합니다.
다시 게시물을 등록하는 소스를 돌아와서 진행하겠습니다.
웹 브라우저에서 출력되는 유효성 검사 메시지를 보면 일반적인 메시지이고 영어 문장이 번역된 것이기 때문에 자연스럽지 않습니다. 그래서 JavaScript Validation API에서 제공하는 DOM 메서드인 setCustomValidity() 메서드를 사용하여 메시지를 변경하도록 하겠습니다.
- setCustomValidity() : 입력 요소에 있는 유효성 검사 메시지(validationMessage) 속성을 변경합니다.
주석처리된 부분은 삭제하였습니다. 그리고 검사 유형에 맞게 메시지를 변경하였습니다.
$(function() {
$('#saveBtn').click(function() {
var registrationId = $('#registrationId')[0];
if (!registrationId.checkValidity()) {
if (registrationId.validity.valueMissing) {
registrationId.setCustomValidity('작성자 입력란에 아이디가 입력되지 않았습니다.\n아이디를 입력하세요.');
} else if (registrationId.validity.tooShort) {
registrationId.setCustomValidity('작성자 입력란에 아이디는 최소 2자이상 최대 20자 이내로 입력하세요.');
}
alert(registrationId.validationMessage);
$('#registrationId').focus();
registrationId.setCustomValidity("");
return;
}
var subject = $('#subject')[0];
if (!subject.checkValidity()) {
if (subject.validity.valueMissing) {
subject.setCustomValidity('제목 입력란에 제목이 입력되지 않았습니다.\n제목을 입력하세요.');
}
alert(subject.validationMessage);
$('#subject').focus();
subject.setCustomValidity("");
return;
}
$('#board').attr("action", "/board/addboard.do");
$('#board').submit();
});
});
알럿 후에 setCustomValidity() 메서드를 빈 값으로 호출하는 이유는 customError 속성이 true로 유지되기 때문입니다.
- customError : setCustomValidity() 메서드를 사용하여 사용자 정의 메시지가 있으면 true를 없으면 false를 리턴합니다.
새로고침 후 등록 버튼을 누릅니다. 그러면 작성자(registrationId)에 입력된 데이터가 없어 변경된 메시지로 메시지가 알럿으로 보입니다.
작성자(registrationId)에 "t"를 입력하고 등록 버튼을 누릅니다. 그러면 길이에 대해 변경된 메시지가 알럿으로 보입니다.
작성자(registrationId)에 "testid3"를 입력하고 등록 버튼을 누릅니다. 이번에는 제목에 입력된 데이터가 없어 변경된 메시지로 메시지가 알럿으로 보입니다.
이렇게 JavaScript Validation API를 사용하면 조금 코딩이 줄기도 하지만 오히려 늘어날 수 있습니다.
그래서 다른 방법으로 checkValidity() 메서드와 CSS의 :valid와 :invalid를 사용하여 처리해 보겠습니다.
'Spring > Maven Project' 카테고리의 다른 글
Spring에 Server-Side Validation 처리 (0) | 2023.02.12 |
---|---|
Spring에 JavaScript Validation API 적용 - form checkValidity, CSS :valid vs :invalid (0) | 2023.01.29 |
Spring에 게시물 등록 처리 - Create, Client-Side Validation (0) | 2023.01.08 |
Spring에 Pagination(페이지네이션) 처리 및 적용 3 (0) | 2023.01.01 |
Spring에 Pagination(페이지네이션) 처리 및 적용 2 (0) | 2022.12.25 |