본문 바로가기
Java/Servlet & JSP

JSP) 회원가입 아이디 중복 검사

by 박채니 2022. 6. 25.

안녕하세요, 코린이의 코딩 학습기 채니 입니다.

 

개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다.


회원가입 아이디 중복 검사

 

memberEnroll.jsp

<tr>
    <th>아이디<sup>*</sup></th>
    <td>
        <input type="text" placeholder="4글자이상" name="memberId" id="_memberId" required>
        <input type="button" value="중복검사" onclick="checkIdDuplicate();"/>
        <input type="hidden" id="idValid" value="0" />	<%-- 중복검사 전 0, 중복검사(유효한아이디) 후 1 --%>
    </td>
</tr>
...
... 이하 코드 생략

<form action="<%=request.getContextPath()%>/member/checkIdDuplicate" name="checkIdDuplicateFrm">
	<input type="hidden" name="memberId" />
</form>

중복검사 버튼을 생성하고 input:hidden을 생성하여 중복 검사 여부에 대해 체크 해주려고 합니다.

중복 검사를 진행했다면 value값은 1로 변경, 진행하지 않았다면 value값은 0으로 변경됩니다.

 

서버에 동일 아이디가 있는 지 확인 요청을 보내는 것이기 때문에 적어도 페이지 이동이 이뤄질 것입니다.

이를 방지하기 위해 중복검사는 팝업창을 이용하여 기존 회원가입 폼에는 그대로 머물고 중복 검사를 해보도록 하겠습니다.

 

script 코드

/**
 * 사용자가 입력한 id값 중복 검사
 * - 폼에서 팝업을 제출
 */
const checkIdDuplicate = () => {
	const memberId = document.querySelector("#_memberId");
	if(!/^[a-zA-Z0-9]{4,}$/.test(memberId.value)) {
		alert("유효한 아이디를 입력해주세요.");
		memberId.select();
		return;
	}
	
	// popup 제어
	const title = "checkIdDuplicatePopup";
	const spec = "width=300px, height=300px";
	const popup = open("", title, spec);	// url, title, spec
	
	// 폼 제어
	const frm = document.checkIdDuplicateFrm;
	frm.target = title;	// 폼의 제출 대상이 현재 윈도우가 아닌 팝업으로 지정
	frm.memberId.value = memberId.value;	// checkIdDuplicateFrm의 memberId에 memberEnrollFrm의 memberId 대입
	frm.submit();
};

open()메소드에는 url, title, spec을 매개인자로 넘겨주게 되는데 이 때, url은 폼을 팝업에 제출할 것이기 때문에 그 때 해결되므로 생략!

팝업에 폼을 연결하기 위하여 폼의 target 속성을 popup으로 지정해주었으며, 입력된 memberId값을 그대로 가져오기 위해 checkIdDuplicateFrm폼 - hidden속성의 memberId에 입력했던 value값을 대입해주었고, 폼을 제출해줍니다.

 

controller

CheckIdDuplicateServlet

@WebServlet("/member/checkIdDuplicate")
public class CheckIdDuplicateServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private MemberService memberService = new MemberService();
	
	/**
	 * member 객체 반환 -> 사용 불가
	 * null 반환 -> 사용 가능
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		
		String memberId = request.getParameter("memberId");
		Member member = memberService.findById(memberId);
		
		boolean available = member == null;
		request.setAttribute("available", available);
		
		request.getRequestDispatcher("/WEB-INF/views/member/checkIdDuplicate.jsp").forward(request, response);
	}
}

 

checkIdDuplicate.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	boolean available = (boolean) request.getAttribute("available");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>아이디중복검사</title>
<style>
div#checkId-container{text-align:center; padding-top:50px;}
span#duplicated{color:red; font-weight:bold;}
</style>
</head>
<body>
	<div id="checkId-container">
	<% if(available) { %>
		<%-- 아이디 사용 가능한 경우 --%>
		<p>
			<span><%= request.getParameter("memberId") %></span>는 사용 가능합니다.
		</p>
		<button type="button" onclick="closePopup();">닫기</button>
	<% } else { %>
		<%-- 아이디 사용 불가한 경우 --%>
		<p>
			<span id="duplicated"><%= request.getParameter("memberId") %></span>는 이미 사용 중입니다.
		</p>
		<form action="<%=request.getContextPath()%>/member/checkIdDuplicate" name="checkIdDuplicateFrm">
			<input type="text" name="memberId" placeholder="아이디를 입력하세요."/>
			<input type="submit" value="중복검사" />
		</form>
		
		<script>
		document.checkIdDuplicateFrm.onsubmit = (e) => {
			const frm = e.target;

	 		if(!/^[a-zA-Z0-9]{4,}$/.test(frm.memberId.value)) {
				alert("유효한 아이디를 입력해주세요.");
				frm.memberId.select();
				return false;
			}
		};
		</script>
	<% } %>
	</div>
	
	<script>
	const closePopup = () => {
		// opener : 부모 윈도우 객체
		const parentFrm = opener.document.memberEnrollFrm;
		parentFrm.idValid.value = 1;	// 중복검사했다고 표시!
		parentFrm.memberId.value = "<%=request.getParameter("memberId")%>";
		
		self.close(); // 현재 창 닫기
	}
	</script>
</body>
</html>

request의 속성으로 등록한 available을 가지고 분기처리를 진행하였습니다.

만일, 중복된 아이디값을 입력하게 된다면 해당 페이지에서 form을 제출하여 다시 중복검사를 진행하였습니다.

사용 가능한 아이디를 입력했다면, 부모 윈도우 객체(opener)의 memberEnrollFrm에 idValid값을 1로 변경해주어 중복 검사를 진행했다는 표시를 하도록 하였고, (잘 반영되어있음!) 닫기 버튼을 생성해주어 팝업을 닫을 수 있도록 하였습니다.

 

하지만, 중복 검사를 통해 올바른 아이디를 입력하고 해당 팝업을 닫았을 때 아이디에 올바르게 입력한 아이디 값이 들어가야 하는데 그대로 'honggd'가 들어가있는 것을 확인할 수 있습니다.

 

팝업을 닫은 후 올바른 아이디값 입력처리

<script>
const closePopup = () => {
    // opener : 부모 윈도우 객체
    const parentFrm = opener.document.memberEnrollFrm;
    parentFrm.idValid.value = 1;	// 중복검사했다고 표시!
    parentFrm.memberId.value = "<%=request.getParameter("memberId")%>";

    self.close();	// 현재 창 닫기
}
</script>

부모 윈도우 객체 opener를 이용하여 값 대입을 해주었습니다.

 

중복검사를 한 후, 아이디를 변경할 가능성도 있으므로 memberId의 change속성이 발생하면, idValid를 0으로 변경하였습니다.

memberEnroll.jsp

document.querySelector("#_memberId").onchange = () => {
	document.querySelector("#idValid").value = 0;
};

중복검사 후 아이디 변경한 경우