-
localStorage 를 이용해서 로그인 / 회원가입 구현하기! (1) 회원가입 편으쌰으쌰 2023. 1. 20. 20:19
localStorage를 이용해서 간단한 로그인, 회원가입을 구현할 것이다.
나의 작은 도전 ~ 뭐든 남겨두면 나중에 꼭 까먹고 도움이 되어주기에 ... 최대한 세세하게 남겨본다!!!
만들려는 것
로그인, 회원가입 기능 구현
HTML -> JS -> CSS -> 갈무리 수정 및 추가 순서로 진행해볼까 한다.
왜?
어떤 웹페이지에 있어서 로그인, 회원가입 기능은 기본 같은 것이라고 생각했다. !!
다음에 만들고 싶은 웹페이지를 위한 준비운동(?) 겸!
localStorage를 직접 써볼 기회를 만들고, 이해도를 높이기 위하여.
바닐라JS 숙련도를 올리기 위해!
사용한 언어
HTML, CSS, javascript
만든 기간
총 3일. 2023년 1월 19일 ~ 2023년 1월 21일
✔︎ 로그인
1. 아이디와 비밀번호가 localStorage에 저장되어 있다면 로그인이 가능하다.
1-2. 저장되어 있지 않다면 로그인이 불가능하다.
2. 아이디가 저장되어 있지만, 비밀번호가 틀렸을 경우 비밀번호가 틀렸다고 alert 한다.
2-2. 아이디가 저장되어 있지 않을 경우, 없는 아이디라는 메세지를 alert 한다.
3. 로그인이 성공한 경우
✔︎ 회원가입
1. 아이디, 비밀번호, 닉네임, 생일을 입력받는다.
1-2. 아이디, 비밀번호, 닉네임은 필수 입력 정보이다. (입력하지 않으면 회원가입 불가능)
1-3. 생일은 선택.
2. 아이디 : 4자 이상, 10자 이하. 중복확인을 거쳐서 OK 일 경우에만 회원가입이 수락된다.
2-2. 비밀번호 : 6자 이상 10자. 사용가능하다.
2-3. 비밀번호 확인 : 2-2에 작성한 비밀번호와 일치할 경우 일치글자가 뜬다!!
2-4. 닉네임 : 8자 이하. / 생일 : 선택.
3. 중복확인->OK && 비밀번호확인 -> OK 를 거쳐야만 가입이 가능하다.
4. 가입이 성공할 경우 정보가 localStorage에 저장된다.
4-2. 로그인 창으로 이동한다.
로그인 html 뼈대
<body> <h1>로그인</h1> <!--local storage를 이용해서 로그인/회원가입 기능 구현하기--> <form action="" id="loginForm"> <input type="text" placeholder="아이디" id="idInput" /> <input type="text" placeholder="비밀번호" id="pwInput" /> <button id="loginBtn">로그인</button> </form> <span> <a href="signup.html">회원가입</a> </span> <!--js load--> <script type="text/javascript" src="js/login.js"></script> </body>
회원가입 html 뼈대
<body> <h1>회원가입</h1> <form action="" id="signUpForm"> <div class=""> <label for="idInput">아이디</label> <input type="text" id="idInput" placeholder="4자이상 10자이하" maxlength="10" minlength="4" required /> <input type="button" id="checkBtn" value="중복확인" /> <span id="idCheckSpan"></span> </div> <div class=""> <label for="pwInput">비밀번호</label> <input type="text" id="pwInput" placeholder="6자이상 10자이하" maxlength="10" minlength="6" required /> </div> <div class=""> <label for="pwCheckInput">비밀번호 확인</label> <input type="text" id="pwCheckInput" placeholder="비밀번호를 똑같이 입력하세요!" maxlength="10" minlength="6" required /> <span id="pwCheckSpan"></span> </div> <div class=""> <label for="nameInput">닉네임</label> <input type="text" id="nameInput" placeholder="8자이하" maxlength="8" required /> </div> <div class=""> <label for="birthinput">생일</label> <input type="date" id="birthInput" min="1920-01-01" /> </div> <input type="submit" value="가입" /> </form> <!--js load--> <script type="text/javascript" src="js/signup.js"></script> </body>
js 파일은 최대한 나누는 게 (나에게는) 덜 헷갈리기 때문에 로그인과 회원가입 기능을 따로따로 나눠 파일을 만들었다.
회원가입부터 시작~!
기능은 크게 세 가지로 나눴다.
1. 비밀번호 확인
2. 아이디 중복체크
3. 회원가입 정보 localStorage에 저장
순서로 진행했는데, 사실상 2와 3은 같이 진행한 것과 다름없었다.
회원가입 기능 구현
👇 전역변수 모음
const signUpForm = document.querySelector("#signUpForm"); // 회원가입form const idInput = document.querySelector("#idInput"); // id 정보 const idCheckBtn = document.querySelector("#checkBtn"); // id 중복확인 버튼 const idCheckSpan = document.querySelector("#idCheckSpan"); // 중복확인 문구 const pwInput = document.querySelector("#pwInput"); // pw 정보 const pwCheckInput = document.querySelector("#pwCheckInput"); // pw 확인 const pwCheckSpan = document.querySelector("#pwCheckSpan"); // 확인문구 const IDOK_KEY = "아이디를 사용하실 수 있습니다."; const PWOK_KEY = "비밀번호가 확인되었습니다!";
🍔 전역변수는 최대한 줄이자!! 를 목표로 작성했다.
💭 왜 전역변수를 최대한 줄이는 게 목표인가? 출처 : 모던 자바스크립트 DeepDive
1. 아무리 const를 사용해서 변수를 만들었다 한들, 모든 코드가 이 전역 변수들을 참조하고 변경할 수 있도록 허용하는 게 바로! 전역변수이기 때문이다.
2. 생명주기가 길다 -> 즉, 상태 변경을 통한 오류 발생 확률이 증가한다. 메모리도 지역변수보다 더 긴 기간동안 소비한다.
3. 전역 변수의 검색 속도가 가장 느리다.
4. 자바스크립트의 특징으로 파일이분리되어있다고 해도 하나의 전역 스코프를 공유하기 때문이다. 동일한 이름으로 명명된 전역 변수 혹은 전역 함수는 예상치 못한 결과를 가져올 수 있다.
즉!! 전역 변수는 지역 변수보다 개발자가 예상치 못한 결과를 가져올 확률이 더 높기 때문이다.🍔 변수의 이름은 무조건!! 이게 무슨 값을 갖고 있는지 알 수 있도록 설정하기
🍔 두 번 이상 사용하게 되는 문자열은 변수에 할당했다.
👇 비밀번호 확인 기능
function pwCheck(event) { if (pwInput.value === pwCheckInput.value) { pwCheckSpan.innerText = PWOK_KEY; } else pwCheckSpan.innerText = "비밀번호를 확인하세요"; } // Event Listner pwCheckInput.addEventListener("keyup", pwCheck);
🍔 회원가입 정보를 저장하는 기능에서 pwCheckSpan에 들어가는 값을 확인해야하므로 오타 등 오류를 줄이기 위해 변수에 할당했다.
🍔 여기서 주목할 건 !!! event listener 부분.
지금까지 혼자서 끄적끄적 써본 것들은 마우스 이벤트를 감지하는 게 대부분이었으나 이번에는 키보드 이벤트!! 를 사용했다.
이번에는 비밀번호 확인 input 에 한 글자 한 글자 작성할 때마다 감지하는 event를 만드는 게 목표였다. (왜냐면.. 버튼보다 간zi나니까..)
처음에는 더이상 사용하지 않는다는 걸 모르고 keypress 를 사용했지만 내가 원하는대로 움직이지 않았다.
(예: 비밀번호가 12345 라면 확인에서 12345를 눌러도 확인이라 나오지 않지만 그 다음에 아무 값이나 한 글자 추가하면 맞다고 떴다)
사용해서는 안 됩니다 (!!!) 대신 사용되고 있는 건 keydown 과 keyup 📌MDN-키보드이벤트
💭 keydown VS keyup
keydown 은 키가 눌렸을 때 발생한다.
keyup 은 키를 눌렀다가 손을 떼는 그 시점!! 바로 그 시점에 발생한다.멋지게 작동한다 ^________^ 기억하자 keyup 이벤트! ⚠️그런데 여기서 잠깐 ... 문제를 두 가지 발견했다.⚠️
1. 비밀번호의 조건은 6자 이상. 1234만 쳤는데도 된다는 건 문제가 있다.
6자 이하일 경우에는 비밀번호를 사용할 수 없다는 것을 알린다.
그런데 고민이 생겼다.
6자 이상 작성하지 않았을 때 어떻게 경고문구를 출력할 것인가?
1. 중복확인, 비밀번호 확인 문구처럼 옆에 나타난다. (6자 이상 입력하세요...)
2. 비밀번호 확인 창을 아예 작성하지 못하도록 만든다. ???
2-2. 6자 이상 작성했을 때 비밀번호 확인 input을 보여준다???
뭐가 더 사용자에게 있어서 친절하게 느껴질 지 고민이 됐다....
혼자 고민하다가 이럴 때 필요한 게 자료찾기(?)구나 하는 생각이 들어서 네이버 회원가입에 들어가봤다(ㅋㅋ)
네이버는 1번 방법으로 되어있고 몇 개의 페이지를 더 봐봤는데 ... 아마존 재팬도 똑같은 1번 방법!
나는 확인문구들이 너무 많으면 오히려 더러워보이지 않을까 했는데 ... css를 나중에 만져주면 되는 문제였다.
그래서 나도 1번 방법으로 해보기로 했다.
// 비밀번호 6자 이상인가욤? function pwLengthCheck() { if (pwInput.value.length < 6) { const pwLengthSpan = document.querySelector("#pwLengthSpan"); pwLengthSpan.innerText = "비밀번호는 6자 이상 입력해주세요."; } else pwLengthSpan.innerText = ""; }
keyup 이벤트를 알게된 나!! 쉽게 만들 수 있었다.
6자 이하일 때는 문구 출력, 그이상 썼다가도 다시 6자이하가 되면 문구가 출력된다 고민인 건 ... 함수가 점점 많아지는데 이렇게 해도 되는건가??
좀 합칠 수는 없을까 ㄱ- ... ?? 고민해보자. ...
2. 비밀번호를 변경할 경우 확인되었다는 문구가 사라지지 않는다.
이대로라면 비밀번호를 변경했음에도 확인 과정을 거치지 않고 바로 OK 조건이 달성되면서 가입이 되어버린다..
비밀번호를 변경할 경우 비밀번호 확인 input의 값이 초기화 되어야 한다. 물론 확인유무도!
function resetFunc() { pwCheckInput.value = ""; pwCheckSpan.innerText = ""; } // eventListener pwInput.addEventListener("keydown", resetFunc); // pw 수정시 비밀번호 확인, 확인문구 초기화
keydown 이벤트를 이용해서 비밀번호 input 에서 한글자라도!! 변경하고 손을 떼는 그 순간
비밀번호 확인 input value와 확인문구를 초기화 하는 function을 만들었다.
단 한글자라도 변경되면 리셋된다!
👇 아이디 중복 확인
// 아이디 중복체크 function idCheck() { const ID_KEY = idInput.value; const getId = localStorage.getItem(ID_KEY + ""); const obj = JSON.parse(getId); if (3 < ID_KEY.length && getId == null) { idCheckSpan.innerText = IDOK_KEY; } else if (4 > ID_KEY.length || obj.id === ID_KEY) { if (4 > ID_KEY.length) idCheckSpan.innerText = "아이디는 4글자 이상으로 정해주세요."; else if (obj.id === ID_KEY) idCheckSpan.innerText = "이미 있는 아이디예요"; idInput.value = ""; } } // Event Listner idCheckBtn.addEventListener("click", idCheck); // id중복확인
👇 회원가입 입력 정보 localStorage 저장
// 회원가입 정보 localStorage에 저장 function signUp(event) { event.preventDefault(); const nameInput = document.querySelector("#nameInput"); const birthInput = document.querySelector("#birthInput"); let obj = {}; if ( pwCheckSpan.innerText === PWOK_KEY && idCheckSpan.innerText === IDOK_KEY ) { obj.id = idInput.value; obj.pw = pwInput.value; obj.name = nameInput.value; obj.birth = birthInput.value; localStorage.setItem(idInput.value + "", JSON.stringify(obj)); alert("회원가입이 완료되었습니다!"); window.location.assign("login.html"); } } // eventListner signUpForm.addEventListener("submit", signUp);
완성! 같이 둬야 나중에 봐도 헷갈리지 않을 것 같아서 함께 적어둔다.
🍔 이 함수 안에서만 사용하는 변수들은 앞에서 말한 것처럼 전역변수가 아니라 지역변수로 사용했다. (최대한 그러려고 노력했다)
🍔 window.location.assign < 으로 회원가입 후 로그인창으로 이동하려고 했는데 요지부동! 인 문제 발생
그밖에도 location.href, location.replace .. 모두 요지부동이어서 컴퓨터를 붙잡고 왜이래~~~~!!! 했던 기억이 난다.
고친 방법은 놀랍게도 event.preventDefault(); 를 넣어준 것 뿐.
form 을 submit하면 창은 기능이 수행되면서 새로고침 된다. 이를 막아주는 게 preventDefault() 이다.
새로고침을 막아주고 location.assign이 잘 수행되도록 하는 것 !!! (이라고 이해했다 ...)
🍔 처음이라 그런지 많이 헤맸지만 그래도 만들어냈다는 게 뿌듯하다 !!! local storage에 저장되는 모습을 확인하면 느껴지는 고양감(?) 같은 게 있다 ㅎㅎ
🍔 위의 gif파일까지는 계속 나오던 자동완성기능(?)을 html 태그 속성을 이용해 없앴다. input 속성으로 autocomplete="off"
🍔 gif 파일은 한눈에 확인하기 위해 비밀번호 input type을 text로 해놓은 상태였는데, 지금은 password로 변경하여 비밀번호가 바로 보이지 않도록 바꿨다.
🍔 생일은 선택적으로 기입하는 정보이므로 생일 옆에 (선택) text를 추가했다!
🍔 같은 아이디일 경우 인풋창을 초기화하는 편이 낫지만, 아이디가 4글자 미만일 경우에는 한두글자 더 추가하면 되는데 굳이 초기화하지 않아도 될 것 같아 코드를 수정했다.
if (3 < ID_KEY.length && getId == null) { idCheckSpan.innerText = IDOK_KEY; } else if (4 > ID_KEY.length || obj.id === ID_KEY) { if (4 > ID_KEY.length) idCheckSpan.innerText = "아이디는 4글자 이상으로 정해주세요."; else if (obj.id === ID_KEY) { idCheckSpan.innerText = "이미 있는 아이디예요"; idInput.value = ""; } }
input date 의 max 속성 값을 '오늘'로 만들기 위해서 js 코드를 사용했다.
회원가입 js 파일에 작성한 게 아니라 html 파일 script 부분에 추가했는데 이유는 이렇다.
1. 다른 기능은 없고 오직 input 속성 값을 위해 작성한 코드이기 때문에.
2. 페이지가 로드되자마자 실행되어야 한다는 걸 좀 더 한눈에 ... 확인하기 쉽다고 생각해서.
라는 두 이유로 그렇게 배치했는데 사실 더 좋은 방법인지는 모르겠다 ^👅^);;
<script> const birth = document.querySelector("#birthInput"); const today = new Date(); const maxDay = `${today.getFullYear()}-${""+today.getMonth()+1}-${today.getDate()}`; birth.setAttribute("max", maxDay); </script>
아쉬운 점과 추가할 점
1. 보통 아이디는 영어와 숫자, 언더바 정도. 비밀번호는 특수문자를 꼭 섞어야 하는 곳이 많아지고 있다...
이러한 정보를 바탕으로 유효성 검사를 추가해야겠다!!
2. placeholder에 어떤 정보를 넣어야 사용자가 더 편하게 느끼고 이해가 쉬울지 고민해봐야겠다. 너무 길지 않게!!
3. 나는 나름 최선을 다한(?) 코드들이지만 언제나 더 좋은 코드는 뭘까 라는 생각이 든다... 다른 사람 코드도 많이 보고 생각을 게을리 하지 말아야겠다.
'으쌰으쌰' 카테고리의 다른 글
바닐라JS 로 만드는 북마크 웹앱 📓 (2) 게시물 편 (0) 2023.02.04 바닐라JS 로 만드는 북마크 웹앱 📓 (1) 회원가입, 로그인 편 (0) 2023.01.25 바닐라JS 로 만드는 북마크 웹앱 📓 (0) 계획 편 (0) 2023.01.24 localStorage 를 이용해서 로그인 / 회원가입 구현하기! (3) 수정, 추가 마지막 정리 편 (1) 2023.01.21 localStorage 를 이용해서 로그인 / 회원가입 구현하기! (2) 로그인 편 (0) 2023.01.20