이제 회원가입을 만들어 볼 차례이다.
회원가입의 유효성 검사는 백엔드에서도 처리하였지만, 프론트에서도 동일하게 처리하였다. 그리고 unique하게 db에 저장되는 전화번호를 통해 인증할 수 있게 만들었다.
회원가입 페이지는 다음과 같이 구성하였다.
만약 유효성 검사와 중복검사에 통과하지 못한 텍스트가 input에 들어가 있을 경우 키 입력을 받을 때마다 체크하여 표시할 수 있게 만들어 보았다.
회원가입 버튼을 누를 때, input에 값을 입력할 때마다 유효성 검사를 통과하였는지 판단하기 위해 Javascript에서 각각의 boolean 변수를 생성하였다.
let isValidUsername = false; let isValidPassword = false; let isValidName = false; let isValidPhone = false; let checkNum = false;
아이디는 영문+숫자 4~10자리이고 중복된 아이디는 허용하지 않는다.
//[ Dup username ]*/ $("input[name='username']").on("propertychange change keyup paste input", function(){ let str = $("input[name='username']").val(); var regExp = /^[0-9a-zA-Z]{4,10}$/; if (!regExp.test(str)) { $("#dup-username").text("아이디는 영문+숫자 4~10자입니다").css("color", "red"); isValidUsername = false; return; } $.ajax({ url:`${path}/users/duplicated/0?str=${str}`, type:"GET", cache:false, success : function(data){ if (data.success) { $("#dup-username").text("사용 가능한 아이디입니다").css("color", "green"); isValidUsername = true; } else { $("#dup-username").text(data.msg).css("color", "red"); isValidUsername = false; } } }); })
비밀번호는 8~16자이고, 비밀번호 확인란과 똑같이 입력해야 한다.
//[ Dup pass ]*/ $("input[name='re-password']").on("propertychange change keyup paste input", function(){ let pass1 = $("input[name='password']").val(); let pass2 = $("input[name='re-password']").val(); let regExp = /^[a-zA-Z\d`~!@#$%^&*()-_=+]{8,16}$/; if (!regExp.test(pass1)) { $("#dup-password").text("비밀번호는 8~16자입니다").css("color", "red"); isValidPassword = false; return; } if (pass1 == pass2) { $("#dup-password").text(" 비밀번호와 일치합니다"); $("#dup-password").css("color", "green"); isValidPassword = true; } else { $("#dup-password").text(" 비밀번호와 다릅니다"); $("#dup-password").css("color", "red"); isValidPassword = false; } }) $("input[name='password']").on("propertychange change keyup paste input", function(){ let pass1 = $("input[name='password']").val(); let pass2 = $("input[name='re-password']").val(); let regExp = /^[a-zA-Z\d`~!@#$%^&*()-_=+]{8,16}$/; if (!regExp.test(pass1)) { $("#dup-password").text("비밀번호는 8~16자입니다").css("color", "red"); isValidPassword = false; return; } if (pass1 == pass2) { $("#dup-password").text(" 비밀번호와 일치합니다"); $("#dup-password").css("color", "green"); isValidPassword = true; } else { $("#dup-password").text(" 비밀번호와 다릅니다"); $("#dup-password").css("color", "red"); isValidPassword = false; } })
별명은 한글 2~8자이며, 중복을 허용하지 않는다.
//[ Dup name ]*/ $("input[name='name']").on("propertychange change keyup paste input", function(){ let str = $("input[name='name']").val(); var regExp = /^[가-힣]{2,8}$/; if (!regExp.test(str)) { $("#dup-name").text("별명은 한글 2~8자 입니다").css("color", "red"); isValidName = false; return; } $.ajax({ url:`${path}/users/duplicated/1?str=${str}`, type:"GET", cache:false, success : function(data){ if (data.success) { $("#dup-name").text("사용 가능한 별명입니다").css("color", "green"); isValidName = true; } else { $("#dup-name").text(data.msg).css("color", "red"); isValidName = false; } } }); })
전화번호는 전화번호 양식에 맞는 10~11자리 정수이고 중복을 허용하지 않는다.
//[ Dup phone ]*/ $("input[name='phone']").on("propertychange change keyup paste input", function(){ let str = $("input[name='phone']").val(); var regExp = /^01([0|1|6|7|8|9])([0-9]{3,4})([0-9]{4})$/; if (!regExp.test(str)) { $("#dup-phone").text("올바른 전화번호 11자리를 입력해 주세요").css("color", "red"); isValidPhone = false; return; } $.ajax({ url:`${path}/users/duplicated/2?str=${str}`, type:"GET", cache:false, success : function(data){ if (data.success) { $("#dup-phone").text("사용 가능한 번호입니다").css("color", "green"); isValidPhone = true; } else { $("#dup-phone").text(data.msg).css("color", "red"); isValidPhone = false; } } }); })
전화번호 인증을 위해 만든 백 서버 컨트롤러와 서비스, 자바스크립트이다.
이 기능을 사용하기 위해서는 백 서버의 build.gradle에 다음 dependency를 추가해야 하고 coolsms 계정이 필요하다. https://coolsms.co.kr/dependency
implementation group: 'net.nurigo', name: 'javaSDK', version: '2.2'
controller
@ResponseBody @GetMapping("/phoneCheck") // 휴대폰 인증번호 public String sendSMS(String phone) { // 휴대폰 문자보내기 //난수 생성 int randomNumber = (int)((Math.random()*(9999-1000+1)) + 1000); userService.certifiedPhoneNumber(phone,randomNumber); return Integer.toString(randomNumber); }
service
public void certifiedPhoneNumber(String userPhoneNumber, int randomNumber) { String api_key = "coolsms 앱키 입력"; String api_secret = "coolsms 앱 시크릿 입력"; Message coolsms = new Message(api_key, api_secret); // 4 params(to, from, type, text) must be filled HashMap<String, String> params = new HashMap<>(); // 수신전화번호 params.put("to", userPhoneNumber); // 발신전화번호. 테스트시에는 발신,수신 둘다 본인 번호로 하면 됨 params.put("from", "01055350934"); params.put("type", "SMS"); // 문자 내용 입력 params.put("text", "sekkison 인증번호는" + "[" + randomNumber + "]" + "입니다."); // application name and version params.put("app_version", "test app 1.2"); try { JSONObject obj = (JSONObject) coolsms.send(params); } catch (CoolsmsException e) { } }
javascript
//[ Phone Check Num ]*/ let code2 = ""; $("#phoneChk").click(function(){ if(!isValidPhone){ alert("휴대폰 번호가 올바르지 않습니다.") }else { alert("인증번호 발송이 완료되었습니다.\n휴대폰에서 인증번호 확인을 해주십시오."); var pn = $("#phone").val(); $.ajax({ type:"GET", url:`${path}/users/phoneCheck?phone=${pn}`, cache : false, success:function(data){ if(data == "error"){ alert("휴대폰 번호가 올바르지 않습니다."); }else{ $("#check").attr("disabled",false); $("#dup-check").text("인증번호를 입력한 뒤 본인인증을 눌러주십시오."); $("#dup-check").css("color","red"); $("#phone").attr("readonly",true); code2 = data; } } }); } }); $("#phoneChk2").click(function(){ if(code2.length <= 0 ){ $("#check").attr("disabled",false); //$("#phoneChk2").css("display","inline-block"); $("#dup-check").text("인증번호를 입력한 뒤 본인인증을 눌러주십시오."); $("#dup-check").css("color","red"); } else if( $("#check").val() == code2){ $("#dup-check").text("인증번호가 일치합니다."); $("#dup-check").css("color","green"); $("#check").attr("disabled",true); checkNum = true; }else{ $("#dup-check").text("인증번호가 일치하지 않습니다. 확인해주시기 바랍니다."); $("#dup-check").css("color","red"); $(this).attr("autofocus",true); checkNum = false; return; } });
성별은 input type="radio"를 통해 입력받는다. 값은 'M' 또는 'F' 둘 중 하나이다.
입력한 정보들로 회원가입을 시도하며, 유효성 검사를 통과하지 못한 것이 하나라도 있다면, 데이터를 전송하지조차 않는다.
//[ 회원가입 완료 ]*/ $("#submitBtn").click(function() { if (!isValidUsername) {alert("아이디를 확인해주세요");return;} if (!isValidPassword) {alert("비밀번호를 확인해주세요");return;} if ($("input[name='password']").val() != $("input[name='re-password']").val()) { alert("비밀번호 확인란이 틀립니다");return; } if (!isValidName) {alert("별명을 확인해주세요");return;} if (!isValidPhone) {alert("전화번호를 확인해주세요");return;} if (!checkNum) {alert("인증번호를 확인해주세요");return;} let data = { "username":$("#username").val(), "password":$("#password").val(), "name":$("#name").val(), "phone":$("#phone").val(), "gender":$("input[name='gender']:checked").val(), "content":"" }; $.ajax({ url:`${path}/users`, type:"POST", data:data, cache:false, success : function(data){ if (data.success) { alert("회원가입 성공"); location.href="../index.html"; } else { alert(data.msg); } } }); })
참고로 만드는 사이트는 구글, 카카오, 네이버 로그인을 통해 회원가입을 진행할 수도 있기 때문에 별도의 API회원가입 페이지도 비슷하게 만들었다.
API 로그인을 통한 회원가입은 아이디, 비밀번호와 관련한 로직을 빼고 진행한다.