회원가입 유효성 검사
회원가입 양식의 유효성 검사는 사용자가 올바른 정보를 제공하도록 보장하고, 데이터베이스 또는 사용자 정보를 처리하는 데 오류를 방지하기 위해 중요합니다.
회원가입 페이지
<script src="https://code.jquery.com/jquery-3.7.0.min.js" integrity="sha256-2Pmvv0kuTBOenSvLm6bvfBSSHrUJ+3A7x6P5Ebd07/g=" crossorigin="anonymous"></script>
<form id="signForm" action="signup.do" method="post">
<h3>회원가입</h3>
<div>
<div>
<label for="id">아이디<span id="spanId"> *</span></label>
<div>
<input type="text" id="inputId" name="memberId" placeholder="아이디를 입력하세요.">
</div>
</div>
<div>
<label for="name">이름<span id="spanName"> *</span></label>
<div>
<input type="text" id="inputName" name="memberName" placeholder="이름을 입력하세요.">
</div>
</div>
<div>
<label for="password">비밀번호<span id="spanPassword1"> *</span></label>
<div>
<input type="password" id="inputPassword1" name="memberPw" placeholder="비밀번호를 입력하세요.">
<button type="button" id="inputBtnPassword1"><i class="fa-solid fa-eye-slash"></i></button>
</div>
</div>
<div>
<label for="passwordre">비밀번호 확인<span id="spanPassword2" class="edit-red"> *</span></label>
<div>
<input type="password" id="inputPassword2" placeholder="비밀번호를 한번 더 입력하세요.">
<button type="button" id="inputBtnPassword2"><i class="fa-solid fa-eye-slash"></i></button>
</div>
</div>
<div>
<label for="phone">연락처<span id="spanPhone"> *</span></label>
<div>
<input type="text" id="inputPhone" name="memberPhone" placeholder="연락처를 입력해주세요.">
</div>
</div>
<div>
<label for="email">이메일<span id="spanEmail"> *</span></label>
<div>
<input type="text" id="inputEmail" name="memberEmail" placeholder="이메일을 입력해주세요.">
</div>
</div>
<div>
<label for="address">주소<span id="spanAddress"> *</span></label>
<div>
<input type="button" id="inputBtnAddress" onclick="daumPost()" value="우편번호 찾기"><br>
<input type="text" id="inputAddress" name="memberAddress" placeholder="주소를 입력해주세요." readonly>
</div>
</div>
<div>
<label for="addressDetail">상세주소<span id="spanAddressDetail"> *</span></label>
<div>
<input type="text" id="inputAddressDetail" placeholder="상세주소를 입력해주세요.">
</div>
</div>
</div>
<div>
<p><input id="inputSubmit" type="button" value="가입하기"></p>
</div>
</form>
signup.jsp
일반적인 회원가입 양식과 비슷하게 구현을 했고 유효성 검사는 jQuery 라이브러리를 이용하여 구현하기 때문에 상단에 jQuery CDN을 작성하였습니다.
아이디 유효성 검사
<div>
<label for="id">아이디<span id="spanId"> *</span></label>
<div>
<input type="text" id="inputId" name="memberId" placeholder="아이디를 입력하세요.">
</div>
</div>
<script type="text/javascript">
let inputId = null;
let flagId = false;
// 아이디 입력
$("#inputId").on("input", function(){ // #inputId 입력 이벤트 발생
checkInputId();
})
// 아이디 함수
function checkInputId() {
const regexId = /^[0-9a-zA-Z]{7,20}$/; // 7 ~ 20자의 숫자, 영문 대 소문자
inputId = $("#inputId").val();
if (!regexId.test(inputId)) { // 정규표현식 만족 X
if (inputId == '') { // inputId가 빈칸이면
$("#spanId").html(' <i class="fa-solid fa-x"></i> 필수 정보입니다.');
} else {
$("#spanId").html(' <i class="fa-solid fa-x"></i> 7 ~ 20자의 영문, 숫자만 사용 가능합니다.');
}
$("#spanId").css("color", "red");
flagId = false;
} else { // 정규표현식 만족 O
$.ajax({ // 아이디 중복검사 요청
url: "checkId.do",
data: {
memberId: inputId
},
type: "post",
success: function(result){
if (result == 1) { // 중복된 아이디가 있으면
$("#spanId").html(' <i class="fa-solid fa-x"></i> 중복된 아이디가 있습니다.');
$("#spanId").css("color", "red");
flagId = false;
} else { // 중복된 아이디가 없으면
$("#spanId").html(' <i class="fa-solid fa-check"></i>');
$("#spanId").css("color", "green");
flagId = true;
}
},
error: function(error){
console.log(error);
}
});
}
}
</script>
사용자가 입력한 아이디를 담을 inputId와 아이디의 유효성 상태인 flagId 변수를 선언합니다. id 속성이 inputId인 요소에 대한 이벤트 핸들러를 설정합니다. 사용자가 해당 input 태그에 입력하면 checkInputId 함수가 호출됩니다. checkInputId 함수는 정규 표현식 검사와 아이디 중복 검사를 확인하는 함수입니다.
먼저 정규 표현식을 사용하여 "7~20자의 영문 대 소문자, 숫자"인 조건을 작성하였습니다. 그 후 test 함수를 사용하여 id 속성이 inputId인 요소의 값이 정규 표현식에 만족하지 않으면 실패 안내 메세지를 업데이트하며 flagId를 false로 설정합니다. 만약 정규 표현식에 만족한다면 중복검사를 하기 위해 inputId를 checkId.do로 ajax 요청을 보냅니다.
package com.varchar.view.controller;
@Controller
public class MemberController {
@Autowired
private MemberService memberService;
@ResponseBody
@RequestMapping(value = "/checkId.do")
public String checkId(@RequestParam("memberId")String memberId, MemberVO memberVO) {
memberVO.setMemberSearch("아이디 중복검사");
memberVO.setMemberId(memberId);
if (memberService.selectOne(memberVO) == null) { // 중복된 아이디가 없으면
return String.valueOf(0);
}
return String.valueOf(1); // 중복된 아이디가 있으면
}
}
MemberController.java
요청 파라미터값을 @RequestParam 어노테이션의 해당 이름으로 바인딩해서 memberId를 String 변수에 저장합니다. 그 후 memverVO객체의 memberId 멤버 변수에 넣어줍니다.
@ResponseBody 어노테이션이 붙어 있기 때문에 반환 시 View 페이지를 반환하지 않고 값 자체를 그대로 반환하게 됩니다.
package com.varchar.biz.member;
@Repository("memberDAO")
public class MemberDAO {
@Autowired
private JdbcTemplate jdbcTemplate;
static final private String SQL_SELECTONE="SELECT MEMBER_ID, MEMBER_PW, MEMBER_NAME, MEMBER_ADDRESS, MEMBER_PHONE, MEMBER_EMAIL "
+ "FROM MEMBER "
+ "WHERE MEMBER_ID = ?";
public MemberVO selectOne(MemberVO memberVO){
try {
if (memberVO.getMemberSearch().equals("아이디 중복검사")) { // 아이디 중복검사
Object[] args = { memberVO.getMemberId() };
return jdbcTemplate.queryForObject(SQL_SELECTONE, args, new MemberSelectOneRowMapper());
} else {
Object[] args = { memberVO.getMemberId() };
return jdbcTemplate.queryForObject(SQL_SELECTONE, args, new MemberSelectOneRowMapper());
}
} catch (EmptyResultDataAccessException e) {
return null;
}
}
}
class MemberSelectOneRowMapper implements RowMapper<MemberVO> {
@Override
public MemberVO mapRow(ResultSet rs, int rowNum) throws SQLException {
MemberVO data=new MemberVO();
data.setMemberId(rs.getString("MEMBER_ID"));
data.setMemberPw(rs.getString("MEMBER_PW"));
data.setMemberName(rs.getString("MEMBER_NAME"));
data.setMemberAddress(rs.getString("MEMBER_ADDRESS"));
data.setMemberPhone(rs.getString("MEMBER_PHONE"));
data.setMemberEmail(rs.getString("MEMBER_EMAIL"));
return data;
}
}
MemberDAO.java
이후 memberSearch가 "아이디 중복검사"인 조건문으로 진입하여 단건 조회일 때 사용하는 queryForObject 메서드를 실행합니다. queryForObject의 첫 번째 인자로 실행할 쿼리문을 작성하고, 두 번째 인자로 쿼리문의 ? 안에 들어갈 값들을 선언합니다. 세 번째 인자로는 쿼리문의 결과를 반환받을 RowMapper객체를 생성합니다.
중복된 아이디가 있는 경우 실패 안내 메세지를 업데이트하며 flagId를 false로 설정합니다. 만약 중복된 아이디가 없다면 성공 안내 메세지를 업데이트하며 flagId를 true로 설정합니다.
비밀번호 유효성 검사
<div>
<label for="password">비밀번호<span id="spanPassword1"> *</span></label>
<div>
<input type="password" id="inputPassword1" name="memberPw" placeholder="비밀번호를 입력하세요.">
<button type="button" id="inputBtnPassword1"><i class="fa-solid fa-eye-slash"></i></button>
</div>
</div>
<div>
<label for="passwordre">비밀번호 확인<span id="spanPassword2"> *</span></label>
<div>
<input type="password" id="inputPassword2" placeholder="비밀번호를 한번 더 입력하세요.">
<button type="button" id="inputBtnPassword2"><i class="fa-solid fa-eye-slash"></i></button>
</div>
</div>
<script>
$("#inputBtnPassword1").on("click", function(){ // #inputBtnPassword1 클릭 이벤트 발생
$("#inputPassword1").toggleClass("eye"); // 요소에 eye라는 클래스가 있으면 삭제 / 없으면 생성
if ($("#inputPassword1").hasClass("eye")) { // 요소에 eye라는 클래스가 있으면
$(this).find("i").attr("class", "fa-solid fa-eye"); // 해당 버튼 하위 요소들 중 i태그의 클래스를 변경
$("#inputPassword1").attr("type", "text"); // #inputBtnPassword1의 타입 변경
} else { // 요소에 eye라는 클래스가 없으면
$(this).find("i").attr("class", "fa-solid fa-eye-slash"); // 해당 버튼 하위 요소들 중 i태그의 클래스를 변경
$("#inputPassword1").attr("type", "password"); // #inputBtnPassword1의 타입 변경
}
});
$("#inputBtnPassword2").on("click", function(){ // #inputBtnPassword2 클릭 이벤트 발생
$("#inputPassword2").toggleClass("eye");
if ($("#inputPassword2").hasClass("eye")) {
$(this).find("i").attr("class", "fa-solid fa-eye");
$("#inputPassword2").attr("type", "text");
} else {
$(this).find("i").attr("class", "fa-solid fa-eye-slash");
$("#inputPassword2").attr("type", "password");
}
});
</script>
사용자가 아이콘을 클릭하면 비밀번호 입력 시 가시성을 위해 toggleClass를 사용하여 비밀번호 태그 속성을 text와 password로 번갈아 가며 전환합니다.
<script>
let inputPassword1 = null;
let inputPassword2 = null;
let flagPassword1 = false;
let flagPassword2 = false;
// 비밀번호 입력
$("#inputPassword1").on("input", function(){ // #inputPassword1 입력 이벤트 발생
checkInputPassword1();
})
// 비밀번호 함수
function checkInputPassword1(){
// 8 ~ 20자중 적어도 하나 이상의 영문 대 소문자, 숫자, 특수문자가 각각 포함
const regexPassword = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,20}$/;
inputPassword1 = $("#inputPassword1").val();
inputPassword2 = $("#inputPassword2").val();
if (!regexPassword.test(inputPassword1)) { // 정규표현식 만족 X
if (inputPassword1 == '') { // inputPassword1가 빈칸이면
$("#spanPassword1").html(' <i class="fa-solid fa-x"></i> 필수 정보입니다.');
} else {
$("#spanPassword1").html(' <i class="fa-solid fa-x"></i> 8 ~ 20자의 영문 대 소문자, 숫자, 특수문자를 사용하세요.');
}
$("#spanPassword1").css("color", "red");
flagPassword1 = false;
} else { // 정규표현식 만족 O
$("#spanPassword1").html(' <i class="fa-solid fa-check"></i>');
$("#spanPassword1").css("color", "green");
flagPassword1 = true;
}
if (inputPassword1 != inputPassword2) { // inputPassword1와 inputPassword2가 같지 않으면
$("#spanPassword2").html(' <i class="fa-solid fa-x"></i> 비밀번호가 일치하지 않습니다.');
$("#spanPassword2").css("color", "red");
flagPassword2 = false;
} else {
$("#spanPassword2").html(' <i class="fa-solid fa-check"></i>');
$("#spanPassword2").css("color", "green");
flagPassword2 = true;
}
}
// 비밀번호 확인 입력
$("#inputPassword2").on("input", function(){ // #inputPassword2 입력 이벤트 발생
checkInputPassword2();
})
// 비밀번호 확인 함수
function checkInputPassword2(){
inputPassword1 = $("#inputPassword1").val();
inputPassword2 = $("#inputPassword2").val();
if (inputPassword1 != inputPassword2) {
$("#spanPassword2").html(' <i class="fa-solid fa-x"></i> 비밀번호가 일치하지 않습니다.');
$("#spanPassword2").css("color", "red");
flagPassword2 = false;
} else {
$("#spanPassword2").html(' <i class="fa-solid fa-check"></i>');
$("#spanPassword2").css("color", "green");
flagPassword2 = true;
}
}
</script>
사용자가 입력한 비밀번호, 비밀번호 확인을 담을 inputPassword1, 2와 비밀번호의 유효성 상태인 flagPassword1, 2 변수를 선언합니다. id 속성이 inputPassword1인 요소에 대한 이벤트 핸들러를 설정합니다. 사용자가 inputPassword1 태그에 입력을 하면 checkInputPassword1 함수가 호출됩니다. checkInputPassword1 함수는 정규 표현식 검사와 비밀번호 일치 여부를 확인합니다.
먼저 정규 표현식을 사용하여 "8~20자의 영문 대 소문자, 숫자, 특수문자를 무조건 하나씩 포함"한 조건을 작성하였습니다. 그 후 test 함수를 사용하여 id 속성이 inputPassword1인 요소의 값이 정규 표현식에 만족하지 않으면 실패 안내 메세지를 업데이트하며 flagPassword1를 false로 설정합니다. 만약 정규 표현식에 만족한다면 성공 안내 메세지를 업데이트하며 flagPassword1를 true로 설정합니다.
그 후 비밀번호 inputPassword1 요소와 inputPassword2 요소의 값이 일치하는지 확인하여 성공과 실패 안내 메세지를 업데이트한 후 flagPassword를 조건에 맞게 설정합니다.
두 번째로 사용자가 inputPassword2 태그에 입력하면 checkInputPassword2 함수가 호출됩니다. checkInputPassword2 함수는 비밀번호 일치 여부를 확인하여 위와 같이 실행됩니다.
주소 유효성 검사
<div>
<label for="address">주소<span id="spanAddress"> *</span></label>
<div>
<input type="button" id="inputBtnAddress" onclick="daumPost()" value="우편번호 찾기"><br>
<input type="text" id="inputAddress" name="memberAddress" placeholder="주소를 입력해주세요." readonly>
</div>
</div>
<div>
<label for="email">상세주소<span id="spanAddressDetail"> *</span></label>
<div>
<input type="text" id="inputAddressDetail" placeholder="상세주소를 입력해주세요.">
</div>
</div>
<script>
let flagAddress = false;
function daumPost() {
new daum.Postcode({
oncomplete: function(data) {
let fullAddr = '';
let extraAddr = '';
//도로명 주소를 선택했을 경우
if (data.userSelectedType === 'R') {
fullAddr = data.roadAddress;
//지번 주소를 선택했을 경우
} else {
fullAddr = data.jibunAddress;
}
//도로명일때 조합
if (data.userSelectedType === 'R') {
//법정동명 추가
if (data.bname !== '') {
extraAddr += data.bname;
}
//건물명 추가
if (data.buildingName !== '') {
extraAddr += (extraAddr !== '' ? ', ' + data.buildingName : data.buildingName);
}
//괄호 추가
fullAddr += (extraAddr !== '' ? ' (' + extraAddr + ')' : '');
}
$("#inputAddress").val(fullAddr); // #inputAddress의 값을 선택한 주소로 변경
$("#inputAddress").attr("readonly", false); // #inputAddress의 readonly속성을 해제
if ($("#inputAddress").val() == fullAddr) { // #inputAddress의 값과 선택한 주소가 같다면
$("#spanAddress").html(' <i class="fa-solid fa-check"></i>');
$("#spanAddress").css("color", "green");
flagAddress = true;
} else { // #inputAddress의 값과 선택한 주소가 다르다면
$("#spanAddress").html(' <i class="fa-solid fa-x"></i> 필수 정보입니다.');
$("#spanAddress").css("color", "red");
flagAddress = false;
}
$("#inputAddress").attr("readonly", true); // #inputAddress의 readonly속성을 설정
$("#inputAddressDetail").focus(); // #inputAddressDetail로 포커스 이동
}
}).open();
}
</script>
<script>
let inputAddress = null;
let inputAddressDetail = null;
let flagAddressDetail = false;
// 주소
inputAddress = $("inputAddress").val();
// 상세주소 입력
$("#inputAddressDetail").on("input", function(){ // #inputAddressDetail 입력 이벤트 발생
checkInputAddressDetail();
})
// 상세주소 함수
function checkInputAddressDetail(){
inputAddressDetail = $("#inputAddressDetail").val();
if (inputAddressDetail == '') { // inputAddressDetail이 빈칸이면
$("#spanAddressDetail").html(' <i class="fa-solid fa-x"></i> 필수 정보입니다.');
$("#spanAddressDetail").css("color", "red");
flagAddressDetail = false;
} else {
$("#spanAddressDetail").html(' <i class="fa-solid fa-check"></i>');
$("#spanAddressDetail").css("color", "green");
flagAddressDetail = true;
}
}
</script>
사용자가 주소 API를 사용하여 입력한 주소를 담을 inputAddress와 상세주소를 담을 inputAddressDetail, 주소 유효성 상태인 flagAddress, flagAddressDetail 변수를 선언합니다. id 속성이 inputAddressDetail 요소에 대한 이벤트 핸들러를 설정합니다. 사용자가 해당 input 태그에 입력하면 checkInputAddressDetail 함수가 호출됩니다. checkInputAddressDetail 함수는 주소 작성 여부를 확인하는 함수입니다.
id 속성이 inputAddressDetail인 요소의 값이 비어 있으면 실패 안내 메세지를 업데이트하며 flagAddressDetail을 false로 설정합니다. 만약 값이 비어있지 않다면 성공 안내 메세지를 업데이트하며 flagAddressDetail을 true로 설정합니다.
최종 유효성 검사
<div>
<input id="inputSubmit" type="button" value="가입하기">
</div>
<script>
$("#inputSubmit").on("click", function(){ // #inputSubmit 클릭 이벤트 발생
if (!flagId) {
checkInputId();
$("#inputId").focus();
} else if (!flagName) {
checkInputName();
$("#inputName").focus();
} else if (!flagPassword1) {
checkInputPassword1();
$("#inputPassword1").focus();
} else if (!flagPassword2) {
checkInputPassword2();
$("#inputPassword2").focus();
} else if (!flagEmail) {
checkInputEmail();
$("#inputEmail").focus();
} else if (!flagPhone) {
checkInputPhone();
$("#inputPhone").focus();
} else if (!flagAddress) {
$("#spanAddress").html(' <i class="fa-solid fa-x"></i> 필수 정보입니다.');
$("#spanAddress").css("color", "red");
$("#inputAddress").focus();
} else if (!flagAddressDetail) {
checkInputAddressDetail();
$("#inputAddressDetail").focus();
} else {
$("#signForm").submit();
}
});
</script>
회원가입 form인 signForm을 제출하기 위해 id 속성이 inputSubmit인 버튼을 눌렀을 때 모든 input 태그에 대한 유효성을 각각의 flag를 통해 검사하고, 유효성 검사가 모두 성공했을 때 form을 제출합니다. 어느 한 곳에서라도 유효성 검사가 실패했을 경우 submit 되지 않고 해당 input 태그로 포커스를 이동합니다.
이러한 유효성 검사를 통해서 사용자가 올바른 정보를 제공하도록 유도하고, 사용자에게 오류 메세지를 제공하여 어떤 문제가 발생했는지 이해하고 수정할 수 있도록 도움을 줄 수 있습니다.
유사 유효성 검사
이름 유효성 검사
<div>
<label for="name">이름<span id="spanName"> *</span></label>
<div>
<input type="text" id="inputName" name="memberName" placeholder="이름을 입력하세요.">
</div>
</div>
<script>
let inputName = null;
let flagName = false;
// 이름 입력
$("#inputName").on("input", function(){ // #inputName 입력 이벤트 발생
checkInputName();
})
// 이름 함수
function checkInputName(){
// 2 ~ 5자의 한글 문자 이거나 2 ~ 20자의 공백을 포함한 영문 대 소문자
const regexName = /(^[가-힣]{2,5}$)|(^[a-zA-Z]{2,20}(\s[a-zA-Z]{2,20})?$)/;
inputName = $("#inputName").val();
if (!regexName.test(inputName)) { // 정규표현식 만족 X
if (inputName == '') { // inputName이 빈칸이면
$("#spanName").html(' <i class="fa-solid fa-x"></i> 필수 정보입니다.');
} else {
$("#spanName").html(' <i class="fa-solid fa-x"></i> 한글과 영문 대 소문자를 사용하세요. 한글: 2~5자, 영문: 2~20자');
}
flagName = false;
$("#spanName").css("color", "red");
} else { // 정규표현식 만족 O
$("#spanName").html(' <i class="fa-solid fa-check"></i>');
$("#spanName").css("color", "green");
flagName = true;
}
}
</script>
사용자가 입력한 이름을 담을 inputName과 이름의 유효성 상태인 flagName 변수를 선언합니다. id 속성이 inputName인 요소에 대한 이벤트 핸들러를 설정합니다. 사용자가 inputName 태그에 입력하면 checkInputName 함수가 호출됩니다. checkInputName 함수는 정규 표현식 검사를 확인합니다.
먼저 정규 표현식을 사용하여 "2~5자의 한글 또는 2~20자의 영문 대 소문자"인 조건을 작성하였습니다. 그 후 test 함수를 사용하여 id 속성이 inputName인 요소의 값이 정규 표현식에 만족하지 않으면 실패 안내 메세지를 업데이트하며 flagName를 false로 설정합니다. 만약 정규 표현식에 만족한다면 성공 안내 메세지를 업데이트하며 flagName를 true로 설정합니다.
연락처 유효성 검사
<div>
<label for="phone">연락처<span id="spanPhone"> *</span></label>
<div>
<input type="text" id="inputPhone" name="memberPhone" placeholder="연락처를 입력해주세요.">
</div>
</div>
<script>
let inputPhone = null;
let flagPhone = false;
// 연락처 입력
$("#inputPhone").on("input", function(){ // #inputPhone 입력 이벤트 발생
checkInputPhone();
})
// 연락처 함수
function checkInputPhone(){
const regexPhone = /^010\d{8}$/; // 010으로 시작하는 11자리 숫자
inputPhone = $("#inputPhone").val();
if (!regexPhone.test(inputPhone)) { // 정규표현식 만족 X
if (inputPhone == '') { // inputPhone이 빈칸이면
$("#spanPhone").html(' <i class="fa-solid fa-x"></i> 필수 정보입니다.');
} else {
$("#spanPhone").html(' <i class="fa-solid fa-x"></i> 휴대전화 형식이 맞지 않습니다. ex)01012345678');
}
flagPhone = false;
$("#spanPhone").css("color", "red");
} else { // 정규표현식 만족 O
$.ajax({ // 연락처 중복검사 요청
url: "checkPhone.do",
data: {
memberPhone: inputPhone
},
type: "post",
success: function(result){
if (result == 1) { // 중복된 연락처가 있으면
$("#spanPhone").html(' <i class="fa-solid fa-x"></i> 중복된 휴대전화 번호가 있습니다.');
$("#spanPhone").css("color", "red");
flagPhone = false;
} else { // 중복된 연락처가 없으면
$("#spanPhone").html(' <i class="fa-solid fa-check"></i>');
$("#spanPhone").css("color", "green");
flagPhone = true;
}
},
error: function(error){
console.log(error);
}
})
}
}
</script>
사용자가 입력한 연락처를 담을 inputPhone과 연락처의 유효성 상태인 flagPhone 변수를 선언합니다. id 속성이 inputPhone인 요소에 대한 이벤트 핸들러를 설정합니다. 사용자가 해당 input 태그에 입력을 하면 checkInputPhone 함수가 호출됩니다. checkInputPhone 함수는 정규 표현식 검사와 연락처 중복 검사를 확인하는 함수입니다.
먼저 정규 표현식을 사용하여 "010으로 시작하는 11자리 숫자"인 조건을 작성하였습니다. 그 후 test 함수를 사용하여 id 속성이 inputPhone인 요소의 값이 정규 표현식에 만족하지 않으면 실패 안내 메세지를 업데이트 하며 flagPhone를 false로 설정합니다. 만약 정규 표현식에 만족한다면 중복검사를 하기 위해 inputPhone를 checkPhone.do로 ajax 요청을 보냅니다.
package com.varchar.view.controller;
@Controller
public class MemberController {
@Autowired
private MemberService memberService;
@ResponseBody
@RequestMapping(value = "/checkPhone.do")
public String checkPhone(@RequestParam("memberPhone")String memberPhone, MemberVO memberVO) {
memberVO.setMemberSearch("연락처 중복검사");
memberVO.setMemberPhone(memberPhone);
if (memberService.selectOne(memberVO) == null) { // 중복된 연락처가 없으면
return String.valueOf(0);
}
return String.valueOf(1); // 중복된 연락처가 있으면
}
}
MemberController.java
요청 파라미터값을 @RequestParam 어노테이션의 해당 이름으로 바인딩해서 memberPhone을 String 변수에 저장합니다. 그 후 memverVO객체의 memberPhone 멤버 변수에 넣어줍니다.
@ResponseBody 어노테이션이 붙어 있기 때문에 반환 시 View 페이지를 반환하지 않고 값 자체를 그대로 반환하게 됩니다.
package com.varchar.biz.member;
@Repository("memberDAO")
public class MemberDAO {
@Autowired
private JdbcTemplate jdbcTemplate;
static final private String SQL_SELECTONE_CKECKPHONE="SELECT MEMBER_ID, MEMBER_PW, MEMBER_NAME, MEMBER_ADDRESS, MEMBER_PHONE, MEMBER_EMAIL "
+ "FROM MEMBER "
+ "WHERE MEMBER_PHONE = ?";
public MemberVO selectOne(MemberVO memberVO){
try {
if (memberVO.getMemberSearch().equals("아이디 중복검사")) {
Object[] args = { memberVO.getMemberId() };
return jdbcTemplate.queryForObject(SQL_SELECTONE, args, new MemberSelectOneRowMapper());
} else if (memberVO.getMemberSearch().equals("연락처 중복검사")) { // 연락처 중복검사
Object[] args = { memberVO.getMemberPhone() };
return jdbcTemplate.queryForObject(SQL_SELECTONE_CKECKPHONE, args, new MemberSelectOneRowMapper());
} else {
Object[] args = { memberVO.getMemberId() };
return jdbcTemplate.queryForObject(SQL_SELECTONE, args, new MemberSelectOneRowMapper());
}
} catch (EmptyResultDataAccessException e) {
return null;
}
}
}
MemberDAO.java
이후 memberSearch가 "연락처 중복검사"인 조건문으로 진입하여 queryForObject 메서드를 실행합니다.
중복된 연락처가 있는 경우 실패 안내 메세지를 업데이트하며 flagPhone를 false로 설정합니다. 만약 중복된 연락처가 없다면 성공 안내 메세지를 업데이트하며 flagPhone를 true로 설정합니다.
이메일 유효성 검사
<div>
<label for="email">이메일<span id="spanEmail"> *</span></label>
<div>
<input type="text" id="inputEmail" name="memberEmail" placeholder="이메일을 입력해주세요.">
</div>
</div>
<script>
let inputEmail = null;
let flagEmail = false;
// 이메일 입력
$("#inputEmail").on("input", function(){ // #inputEmail 입력 이벤트 발생
checkInputEmail();
})
// 이메일 함수
function checkInputEmail(){
// 로컬 부분 : 영문 대 소문자, 숫자, 특수문자를 포함
// 도메인 부분 : 영문 대 소문자, 특수문자를 포함
// 최상위 도메인 부분 : 2 ~ 6자의 영문 대 소문자
const regexEmail = /^[A-Za-z0-9\.\-_]+@([a-z0-9\-]+\.)+[a-z]{2,6}$/;
inputEmail = $("#inputEmail").val();
if (!regexEmail.test(inputEmail)) { // 정규표현식 만족 X
if (inputEmail == '') { // inputEmail이 빈칸이면
$("#spanEmail").html(' <i class="fa-solid fa-x"></i> 필수 정보입니다.');
} else {
$("#spanEmail").html(' <i class="fa-solid fa-x"></i> 이메일 형식이 맞지 않습니다. ex)varchar1234@varchar.com');
}
flagEmail = false;
$("#spanEmail").css("color", "red");
} else { // 정규표현식 만족 O
$.ajax({ // 이메일 중복검사 요청
url: "checkEmail.do",
data: {
memberEmail:inputEmail
},
dataType: "json",
type: "post",
success: function(result){
if (result == 1) { // 중복된 이메일이 있으면
$("#spanEmail").html(' <i class="fa-solid fa-x"></i> 중복된 이메일이 있습니다.');
$("#spanEmail").css("color", "red");
flagEmail = false;
} else { // 중복된 이메일이 없으면
$("#spanEmail").html(' <i class="fa-solid fa-check"></i>');
$("#spanEmail").css("color", "green");
flagEmail = true;
}
},
error: function(error){
console.log(error);
}
})
}
}
</script>
사용자가 입력한 이메일을 담을 inputEmail과 이메일의 유효성 상태인 flagEmail 변수를 선언합니다. id 속성이 inputEmail인 요소에 대한 이벤트 핸들러를 설정합니다. 사용자가 해당 input 태그에 입력을 하면 checkInputEmail 함수가 호출됩니다. checkInputEmail 함수는 정규 표현식 검사와 이메일 중복 검사를 확인하는 함수입니다.
먼저 정규 표현식을 사용하여 일반적인 이메일 형식을 요구하는 조건을 작성하였습니다. 그 후 test 함수를 사용하여 id 속성이 inputEmail인 요소의 값이 정규 표현식에 만족하지 않으면 실패 안내 메세지를 업데이트 하며 flagEmail를 false로 설정합니다. 만약 정규 표현식에 만족한다면 중복검사를 하기 위해 inputEmail를 checkEmail.do로 ajax 요청을 보냅니다.
package com.varchar.view.controller;
@Controller
public class MemberController {
@Autowired
private MemberService memberService;
@ResponseBody
@RequestMapping(value = "/checkEmail.do")
public String checkEmail(@RequestParam("memberEmail")String memberEmail, MemberVO memberVO) {
memberVO.setMemberSearch("이메일 중복검사");
memberVO.setMemberEmail(memberEmail);
if (memberService.selectOne(memberVO) == null) { // 중복된 이메일이 없으면
return String.valueOf(0);
}
return String.valueOf(1); // 중복된 이메일이 있으면
}
}
MemberController.java
요청 파라미터값을 @RequestParam 어노테이션의 해당 이름으로 바인딩해서 memberEmail을 String 변수에 저장합니다. 그 후 memverVO객체의 memberEmail 멤버 변수에 넣어줍니다.
@ResponseBody 어노테이션이 붙어 있기 때문에 반환 시 View 페이지를 반환하지 않고 값 자체를 그대로 반환하게 됩니다.
package com.varchar.biz.member;
@Repository("memberDAO")
public class MemberDAO {
@Autowired
private JdbcTemplate jdbcTemplate;
static final private String SQL_SELECTONE_CKECKEMAIL="SELECT MEMBER_ID, MEMBER_PW, MEMBER_NAME, MEMBER_ADDRESS, MEMBER_PHONE, MEMBER_EMAIL "
+ "FROM MEMBER "
+ "WHERE MEMBER_EMAIL = ?";
public MemberVO selectOne(MemberVO memberVO){
try {
if (memberVO.getMemberSearch().equals("아이디 중복검사")) {
Object[] args = { memberVO.getMemberId() };
return jdbcTemplate.queryForObject(SQL_SELECTONE, args, new MemberSelectOneRowMapper());
} else if (memberVO.getMemberSearch().equals("연락처 중복검사")) {
Object[] args = { memberVO.getMemberPhone() };
return jdbcTemplate.queryForObject(SQL_SELECTONE_CKECKPHONE, args, new MemberSelectOneRowMapper());
} else if (memberVO.getMemberSearch().equals("이메일 중복검사")) { // 이메일 중복검사
Object[] args = { memberVO.getMemberEmail() };
return jdbcTemplate.queryForObject(SQL_SELECTONE_CKECKEMAIL, args, new MemberSelectOneRowMapper());
} else {
Object[] args = { memberVO.getMemberId() };
return jdbcTemplate.queryForObject(SQL_SELECTONE, args, new MemberSelectOneRowMapper());
}
} catch (EmptyResultDataAccessException e) {
return null;
}
}
}
MemberDAO.java
이후 memberSearch가 "이메일 중복검사"인 조건문으로 진입하여 queryForObject 메서드를 실행합니다.
중복된 이메일이 있는 경우 실패 안내 메세지를 업데이트하며 flagEmail를 false로 설정합니다. 만약 중복된 연락처가 없다면 성공 안내 메세지를 업데이트하며 flagEmail을 true로 설정합니다.