본문 바로가기
HTML CSS JS

[HTML, CSS, JS] 회원가입 유효성 검사

by code_learner 2022. 4. 13.

팀 프로젝트를 하기 앞서 회원가입 폼을 만들어두면 유용하게 쓰일 것 같아서 어느 정도 틀을 잡아 보았다.

class, id, 태그등은 네이버의 회원가입 틀을 보고 참고하였다.

 

 

[register.jsp]

더보기
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<script type="text/javascript">
//주소검색시 사용되는 script
	// opener관련 오류가 발생하는 경우 아래 주석을 해지하고, 사용자의 도메인정보를 입력합니다. ("팝업API 호출 소스"도 동일하게 적용시켜야 합니다.)
	//document.domain = "http://localhost:8010/register/regitser.jsp";

	function goPopup() {
		// 호출된 페이지(jusoPopup.jsp)에서 실제 주소검색URL(https://www.juso.go.kr/addrlink/addrLinkUrl.do)를 호출하게 됩니다.
		var pop = window.open("jusoPopup.jsp", "pop",
				"width=570,height=420, scrollbars=yes, resizable=yes");

		// 모바일 웹인 경우, 호출된 페이지(jusoPopup.jsp)에서 실제 주소검색URL(https://www.juso.go.kr/addrlink/addrMobileLinkUrl.do)를 호출하게 됩니다.
		//var pop = window.open("/popup/jusoPopup.jsp","pop","scrollbars=yes, resizable=yes"); 
	}
	/** API 서비스 제공항목 확대 (2017.02) **/
	function jusoCallBack(roadFullAddr, roadAddrPart1, addrDetail,
			roadAddrPart2, engAddr, jibunAddr, zipNo, admCd, rnMgtSn, bdMgtSn,
			detBdNmList, bdNm, bdKdcd, siNm, sggNm, emdNm, liNm, rn, udrtYn,
			buldMnnm, buldSlno, mtYn, lnbrMnnm, lnbrSlno, emdNo) {
		// 팝업페이지에서 주소입력한 정보를 받아서, 현 페이지에 정보를 등록합니다.
		document.join.roadAddrPart1.value = roadAddrPart1;
		document.join.roadAddrPart2.value = roadAddrPart2;
		document.join.addrDetail.value = addrDetail;
		document.join.zipNo.value = zipNo;
	}
</script>
<title>회원가입 폼</title>

<style type="text/css">
#header .h_logo {
	width: 300px;
	height: 32px;
}
</style>
</head>
<link href="register.css" rel="stylesheet" />



<body>
	<div id="wrap">
		<div id="header">
			<!-- 회원가입 헤더 -->
			<a href="#"><h1 class="h_logo"></h1></a>
		</div>

		<!-- 회원 폼 -->
		<form id="join_form" method="post" name="join">
			<div id="container">
				<!-- 아이디, 비밀번호 -->
				<div class="row_group">
					<!-- 아이디 -->
					<div class="join_row">
						<h3 class="join_title">
							<label>아이디</label>
						</h3>
						<span class="box int_id"> <input type="text" id="id"
							class="int check" title="ID" maxlength="20">
						</span>
						<div id="idError" class="error_next_box"></div>
					</div>

					<!-- 비밀번호 -->
					<div class="join_row">
						<h3 class="join_title">
							<label>비밀번호</label>
						</h3>
						<span class="box int_id"> <input type="password" id="pw1"
							class="int check" title="비밀번호 입력" maxlength="20">
						</span>
						<div id="pw1Error" class="error_next_box"></div>

						<h3 class="join_title">
							<label>비밀번호 재확인</label>
						</h3>
						<span class="box int_id"> <input type="password" id="pw2"
							class="int check" title="비밀번호 재확인 입력" maxlength="20">
						</span>
						<div id="pw2Error" class="error_next_box"></div>
					</div>
				</div>


				<!-- 이름, 생년월일, 성별, 본인확인 이메일 -->
				<div class="row_group">
					<!-- 이름 -->
					<div class="join_row">
						<h3 class="join_title">
							<label>이름</label>
						</h3>
						<span class="box int_id"> <input type="text" id="name"
							class="int check" title="이름" maxlength="40">
						</span>
						<div id="nameError" class="error_next_box"></div>
					</div>

					<!-- 성별 -->
					<div class="join_row join_sex">
						<h3 class="join_title">
							<label>성별</label>
						</h3>
						<div class="ps_box gender_code">
							<select id="gender" name="gender" class="sel check">
								<option value="" selected>성별</option>
								<option value="M">남자</option>
								<option value="F">여자</option>
								<option value="U">선택 안함</option>
							</select>
						</div>
						<div id="mfError" class="error_next_box"></div>
					</div>

					<!-- 이메일 -->
					<div class="join_row join_email">
						<h3 class="join_title">이메일</h3>
						<span class="box" id="emailBox"> <input type="text"
							id="email" maxlength="20" class="check"> <span> @
						</span> <!-- 이메일 택일 --> <select id="mail_Select">
								<option>이메일 선택</option>
								<option>naver.com</option>
								<option>gmail.com</option>
								<option>daum.net</option>
								<option>hanmail.net</option>
								<option>nate.com</option>
								<option>yahoo.co.kr</option>
						</select>
						</span>
						<div id="emailError" class="error_next_box"></div>
					</div>

					<!-- 전화번호 입력 -->
					<div class="join_row">
						<h3 class="join_title">전화번호(-제외)</h3>
						<span class="box int_id"><input type="text" id="phoneNum"
							class="int check" maxlength="11"></span>
						<div id="phoneNumError" class="error_next_box"></div>
					</div>
				</div>


				<!-- 도로명주소 -->
				<div class="row_group">
					<!--우편번호 openapi사용-->
					<div class="join_row">
						<h3 class="join_title">주소</h3>
						<table>
							<colgroup>
								<col style="width: 20%">
								<col>
							</colgroup>
							<tbody>
								<tr>
									<th>우편번호</th>
									<td><input type="hidden" id="confmKey" name="confmKey"
										value=""> <input type="text" id="zipNo" name="zipNo" class="check"
										readonly style="width: 100px"> <input type="button"
										value="주소검색" onclick="goPopup();"></td>
								</tr>
								<tr>
									<th>도로명주소</th>
									<td><input type="text" id="roadAddrPart1"
										style="width: 85%" readonly></td>
								</tr>
								<tr>
									<th>상세주소</th>
									<td><input type="text" id="addrDetail" style="width: 40%"
										value=""> <input type="text" id="roadAddrPart2"
										style="width: 40%" value="" readonly></td>
								</tr>
							</tbody>
						</table>
						<div id="addNumError" class="error_next_box"></div>
					</div>

					<div class="btn_area">
						<input type="submit" value="가입하기" id="btnJoin"
							class="btn_type btn_primary check">
					</div>
				</div>

			</div>
		</form>
	</div>
	<script src="register.js"></script>

</body>
</html>

 

1. 모든 input태그에 클래스명으로 check를 부여하여 모든 항목을 선택할 수 있도록 한다.

2. 각각의 항목 밑에 id="~Error"를 부여해 유효성 검사를 즉각 반영하여 멘트가 나올 수 있게 하는 공간을 부여하였다.


[register.css]

더보기
body, button, dd, dl, dt, fieldset, form, h1, h2, h3, h3, h5, h6, input,
   legend, li, ol, p, select, table, td, textarea, th, ul {
   margin: 0;
   padding: 0;
}

#wrap {
	width: 100%;
	min-width: 760px;
}

#container {
	margin: 0 auto;
   max-width: 460px;
    width: auto;
}

#header .h_logo {
	display: block;
	margin: 0 auto;
	width: 240px;
	height: 100px;
	/*background-image: url(https://static.nid.naver.com/images/ui/join/m_naver_logo_20191126.png);*/
	background-image: url('null.png');
	background-repeat: no-repeat;
	background-position: 0 0;
	background-size: 240px auto; /*이미지 사이즈*/
}

.row_group {
	overflow: hidden;
	width: 100%;
}

.box {
	margin: 0px auto;
	display: block;
	position: relative;
	width: 100%;
	height: 51px;
	border: solid 1px #dadada;

	padding: 10px 110px 10px 14px;
	padding-top: 10px;
	padding-right: 14px;
	padding-bottom: 10px;
	box-sizing: border-box;
}
#email{
	outline: 0;
	border: none;
	font-size: 16px;
}
#mail_Select{
	width: 40%;
    font-size: 16px;
    border: 1px solid lightgray;
}

.join_title {
	display: inline-black;
	margin: 19px 0 8px;
	width: 60%;
	font-size: 18px;
	font-weight: 700;
}

.list h3 {
	display: inline-black;
}

.gender_code {
	display: block;
	width: 100%;
	padding-right: 7px;
	box-sizing: border-box;
}

.ps_box {
	display: block;
	position: relative;
	width: 100%;
	height: 51px;
	border: solid 1px #dadada;
	padding: 10px 110px 10px 14px;
	background: #fff;
	box-sizing: border-box;
	padding-right: 14px;
	box-sizing: border-box;
}

.error_next_box {
    display: block;
    margin: 5px 0 -2px;
    font-size: 12px;
    line-height: 14px;
    color: red;
}

.int {
	display: block;
	position: relative;
	width: 100%;
	height: 29px;
	padding-right: 25px;
	line-height: 29px;
	border: none;
	background: #fff;
	font-size: 18px;
	box-sizing: border-box;
	z-index: 10;
}

.sel {
	width: 100%;
	height: 29px;
	padding: 7px 8px 6px 7px\9;
	font-size: 18px;
	line-height: 18px;
	color: #000;
	border: none;
	border-radius: 0;
	height: auto;
	-webkit-appearance: none;
}

.d_form {
    font-size: 15px;
    padding: .5em;
    border: 1px solid #ccc;
    border-color: #dbdbdb #d2d2d2 #d0d0d0 #d2d2d3;
    vertical-align: middle;
    line-height: 1.25em;
    outline: 0;
    width: 100%;
    height : 50px;
    border:none;
   
    padding: 10px 110px 10px 14px;
    padding-top: 10px;
    padding-right: 110px;
    padding-bottom: 10px;
    padding-left: 14px;
    box-sizing: border-box;
}

.d_form.mini{
	width: 20%;
	border: solid 1px #dadada;
}
 
.btn{
	cursor: pointer;
}

.btn_area {
    margin: 30px 0 9px;
}

.btn_type {
    display: block;
    width: 100%;
    padding: 15px 0 15px;
    font-size: 16px;
    font-weight: 700;
    text-align: center;
    cursor: pointer;
    box-sizing: border-box;
}

[register.js]

js는 크게 사용자가 입력하는 그대로 유효성 검사를 진행하는 keyup이벤트와,

회원가입 버튼을 누른다면 진행하는 유효성검사로 나뉜다.

 

-keyup 이벤트 유효성-

더보기
		//==============로그인 유효성검사==============
		var regId = /^[a-zA-Z0-9-_]{5,15}$/;//id- 5~20자 (a~z, A~Z, 0~9, -, _만 입력가능)
		var regPw = /(?=.*\d{1,50})(?=.*[~`!@#$%\^&*()-+=]{1,50})(?=.*[a-zA-Z]{1,50}).{8,50}$/;//숫자, 특수문자, 영문 1개이상 사용하여 8자리 이상
		var regName = /^[가-힣]{2,15}$/; 
		var regEmail = /^[0-9a-zA-Z-_.]{5,15}$/; // 이메일 0~9, a~z, A~Z, -, _, .내에서만 입력가능
		var regPhone = /^01([0|1|6|7|8|9])-?([0-9]{3,4})-?([0-9]{4})$/;//전화번호 ->첫숫자는 01+(0,1,6,7,8,9)/-는 무시한다/숫자만 입력가능
		var data = document.querySelector("#id");
		var input = document.querySelectorAll('.check');
		console.log(input);
		function idCh() {//id유효성
			var err = document.querySelector('#idError');
			if (regId.test(input[0].value)) {
				console.log('id 잘나옴')
				err.innerText = "";
			} else {
				console.log('id오류')
				var data = document.querySelector('#idError');
				err.innerText = "5~15자 (a~z, A~Z, 0~9, -, _만 입력가능) ";
			}

		};

		function pw1Ch() {//패스워드 유효성
			var err = document.querySelector('#pw1Error');
			if (regPw.test(input[1].value)) {
				console.log('pw1 잘나옴');
				err.innerText = "";
			} else {
				console.log('pw1오류');
				err.innerText = "8자이상 (숫자, 특수문자, 영문 1개이상)";
			}
		};
		function pw2Ch() {//패스워드 확인 유효성
			var err = document.querySelector('#pw2Error');
			if (input[1].value == input[2].value) {
				console.log('pw2 잘나옴');
				err.innerText = "";
			} else {
				console.log('pw2오류');
				err.innerText = "비밀번호가 일치하지 않습니다.";
			}
		};

		function nameCh() {//이름유효성
			var err = document.querySelector('#nameError');
			
				if (regName.test(input[3].value)) {
					console.log('name 잘나옴')
					err.innerText = "";
				} else {
					console.log('name오류')
					err.innerText = "한글 2단어 이상 입력해 주세요.";
				}
			
		};
		
		function emailCh() {//이메일 유효성
			var err = document.querySelector('#emailError');
			
				if (regEmail.test(input[5].value)) {
					console.log('email 잘나옴')
					err.innerText = "";
				} else {
					console.log('email오류')
					err.innerText = "5~15글자 숫자, 영문자, -, _, .내에서만 입력가능";
					input[5].focus();
				}
			
		};
		
		function phoneCh() {//핸드폰 유효성
			var err = document.querySelector('#phoneNumError');
			
				if (regPhone.test(input[6].value)) {
					console.log('phone 잘나옴')
					err.innerText = "";
				} else {
					console.log('phone오류')
					err.innerText = "전화번호 형식에 맞지 않습니다.";
					input[6].focus();
				}
			
		};
		
		
		input[0].addEventListener('keyup', idCh);
		input[1].addEventListener('keyup', pw1Ch);
		input[2].addEventListener('keyup', pw2Ch);
		input[3].addEventListener('keyup', nameCh);
		input[5].addEventListener('keyup', emailCh);
		input[6].addEventListener('keyup', phoneCh);

1. 각 항목의 check클래스를 선택자로 저장하여 하나씩 불러 유효성 검사 함수를 만들어둔다.

2. 사용자가 입력할 때마다(keyup) 정규식과 비교하여 에러메시지(err.innerText)를 출력해주고

   유효성에 맞으면 ""처리한다. 

 

-회원가입 버튼 유효성-

더보기
window.onload = function() {
	document.join.onsubmit=function(){// 회원가입을 누른다면
		var errorStr = [ " 아이디를", " 비밀번호를", " 비밀번호 확인을", " 성함을","성별", "이메일을","전화번호", "주소를" ];
		
		var error=document.querySelectorAll('.error_next_box');
		console.log(input);
      	for (var i = 0; i < input.length-1; i++) { // -1 == submit제외 
        if (!input[i].value) { 	
             error[i].innerHTML = errorStr[i]+ " 입력해 주세요.";
             input[i].focus(); // 포커스 이동
             return false; // 종료 (포커스 이동유지를 위해 false 종료)
        	 }           
           	 error[i].innerHTML = "";
         }
         
		if (!regId.test(input[0].value)){//				
			var err = document.querySelector('#idError');
			err.innerText = "5~15자 (a~z, A~Z, 0~9, -, _만 입력가능) ";
			input[0].focus();
			return false;
		}
	
			
		if (!regPw.test(input[1].value)) {
			var err = document.querySelector('#pw1Error');
			err.innerText = "8자이상 (숫자, 특수문자, 영문 1개이상)";
			input[1].focus();
			return false;
			}
	
		if (input[1].value !== input[2].value) {
			var err = document.querySelector('#pw2Error');
			err.innerText = "비밀번호가 일치하지 않습니다.";
			input[2].focus();
			return false;
		}		
			
		if (!regName.test(input[3].value)) {
			var err = document.querySelector('#nameError');
			err.innerText = "한글 2단어 이상 입력해 주세요.";
			input[3].focus();
			return false;
		}				
			
		if (!regEmail.test(input[5].value)) {
			var err = document.querySelector('#emailError');	
			err.innerText = "5글자이상 숫자, 영문자, -, _, .내에서만 입력가능";
			input[5].focus();
			return false;
		}
			
		if (!regPhone.test(input[6].value)) {
			var err = document.querySelector('#phoneNumError');
			err.innerText = "전화번호 형식에 맞지 않습니다.";
			input[6].focus();
			return false;
		}

				 alert("회원가입이 완료되었습니다. this+조의 멤버가 되신 것을 환영합니다!! :D");
			}
		}

1. required 대신 직접 텍스트를 입력하기 위해 텍스트를 배열에 넣고, 모든 input에 대해 비어있다면 텍스트 출력

2.. 정규식에 대한 유효성이 맞지 않는다면 해당 input에 focus가 가도록 하고, 해당 유효성 텍스트 출력

 

 

 

*소감: 회원가입 요소가 추가되는 등에 대한 유지보수가 많이 어려운 코드 같다. 시간이 날 때 변수명을 통일하고, 동의 항목 등을 추가하여 디벨롭해봐야겠다.

댓글