Html&Dom/Local Storage

Local Storage(2)_회원가입/로그인으로 응용하기

김Boolean 2022. 10. 21. 17:55

이번엔 저번에 만들었던 게시판 방식을 응용하여 회원가입을 하고 로그인 시 해당 닉네임을 매칭하여 환영 인사를 보여주는 페이지를 제작해보자.

 

원래 Local Storage로 회원가입, 로그인을 구현하면 안 되지만 연습용으로만 한번 제작해보자.

 

1. 구조 잡기

<!DOCTYPE html>
<html lang="ko">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  <title> Local Storage 회원가입</title>
  <link href="./css/reset.css" rel="stylesheet" />
  <link href="./css/style.css" rel="stylesheet" />
</head>

<body>
  <div class="wrap">
      <h1>Local Storage 회원가입</h1>
      <div class="signup_container">
        <form action="#" class="signup__form" id="signup-form">
          <label id="signup_email-label"><span>이메일 주소</span>
            <div><input type="email" id="signup_email" name="signup_email" value=""></div>
          </label>
          <label id="signup_nickname-label"><span>닉네임</span>
            <div><input type="text" id="signup_nickname" name="signup_nickname" value=""></div>
          </label>
          <label id="signup_password-label"><span>비밀번호</span>
            <div><input type="password" id="signup_password" name="signup_password" value=""></div>
          </label>
          <label id="signup_password-check-label"><span>비밀번호 확인</span>
            <div><input type="password" id="signup_password-check" name="signup_password-check" value=""></div>
            <div class="error_signup_password">비밀번호가 일치하지 않습니다.</div>
            <div class="error_signup_nickname">닉네임을 입력해주세요.</div>
            <div class="signup_complete">회원가입이 완료되었습니다! 로그인해주세요.</div>
          </label>
          </label><button class="submit_button" type="submit">회원가입</button>
        </form>
        <p >이미 회원이신가요?&nbsp;<a href="/login">로그인 하러가기</a></p>
      </div>

    <div class="login_container">
      <form action="#" class="login__form" id="login-form">
        <label id="login_email-label"><span>이메일 주소</span>
          <div><input type="email" id="login_email" name="login_email" value=""></div>
        </label>
        <label id="login_password-label"><span>비밀번호</span>
          <div><input type="password" id="login_password" name="login_password" value=""></div>
        </label>
        </label><button class="login_button" type="submit">로그인</button>
      </form>
      <p >아직 회원이 아니신가요?&nbsp;<a href="/login">회원가입 하러가기</a></p>
    </div>

    <div class="welcome_container">
      <p>
        <span class="welcome_nickname"></span>님 환영합니다!
      </p>
    </div>
  </div>
  </div>
  <script src="./js/jquery-3.6.0.min.js"></script>
  <script src="./js/script.js"></script>
</body>

</html>

 

우선 구조를 짜보자.

signup_container - 회원가입을 진행하는 화면

login_container -  로그인을 진행하는 화면

welcome_container - 로그인 성공 시 보여지는 화면

 

페이지 접속 시 뜨는 화면이다. (=signup_container)

이번에도 동일하게 css보단 script가 중요하여 css는 첨부하지 않겠다.

 


 

2. 회원가입

(1) 변수 선언

이전과 동일하게 input값과 submit 상태를 확인할 form, localstorage에 전달해줄 key, value값을 선언해준다.

// 이메일, 닉네임, 비밀번호, 비밀번호 확인을 입력하는 signup-form
const signupForm = document.querySelector('#signup-form');
const signup_emailInput = document.querySelector('#signup_email');
const signup_nicknameInput = document.querySelector('#signup_nickname');
const signup_passwordInput = document.querySelector('#signup_password');
const signup_passwordCheckInput = document.querySelector('#signup_password-check');

let signup_email = '';
let signup_nickname = '';
let signup_password = '';
let signup_passwordCheck = '';

// key값
const InfoList = 'InfoLists';
// value값
const InfoListsObj = [];

 

(2) 회원가입 진행

회원가입 버튼 클릭 시 실행되는 함수이다.

 

현재 각 input에 입력된 값을 받아와 변수에 대입해준다.

그 후, InfoList에 들어있는 데이터 값을 lists에 대입해주고 해당 lists의 값이 없을 경우(회원가입이 한번도 이루어지지 않은 경우) 임의의 배열 변수를 생성하여 현재 입력된 값들을 넣어준다.

 

처음이 아니라면 기존 lists에 배열을 추가한 뒤 해당 lists를 value값으로 InfoList에 넣어준다.

// 회원가입 버튼 클릭 시 실행
function onSignupSubmit(e) {
  // 이벤트 방지
  e.preventDefault();

  // signup_emailInput에 입력된 값을 찾아와 signup_email에 대입
  signup_email = signup_emailInput.value;
  // signup_nicknameInput에 입력된 값을 찾아와 signup_nickname에 대입
  signup_nickname = signup_nicknameInput.value;
  // signup_passwordInput에 입력된 값을 찾아와 signup_password에 대입
  signup_password = signup_passwordInput.value;
  // signup_passwordCheckInput에 입력된 값을 찾아와 signup_passwordCheck에 대입
  signup_passwordCheck = signup_passwordCheckInput.value;

  // 로컬스토리지 InfoList에 저장되어있는 값을 불러와 json형태로 변형 후 lists에 대입
  const lists = JSON.parse(localStorage.getItem(InfoList));
  // 만약 lists가 false면(=비어있다면)
  if (!lists) {
    // objArr라는 빈 배열을 생성하여
    const objArr = [];
    // 값 대입
    objArr.push({
      // 이메일
      signup_email: `${signup_email}`,
      // 닉네임
      signup_nickname: `${signup_nickname}`,
      // 비밀번호
      signup_password: `${signup_password}`,
    });

    // 생성된 배열의 내용을 InfoList(key)에 json 형태의 데이터로 저장
    localStorage.setItem(InfoList, JSON.stringify(objArr));
    // 한번 lists가 생성되어 데이터가 저장된 후
  } else {
    // lists에 입력된 값들 대입
    lists.push({
      // 이메일
      signup_email: `${signup_email}`,
      // 닉네임
      signup_nickname: `${signup_nickname}`,
      // 비밀번호
      signup_password: `${signup_password}`,
    });

    // 생성된 배열의 내용을 InfoList(key)에 json 형태의 데이터로 저장
    localStorage.setItem(InfoList, JSON.stringify(lists));
  }

  if(!$('.error_signup_nickname').hasClass('off') && !$('.error_signup_password').hasClass('off')) {
    // input값 초기화
    signup_emailInput.value = '';
    signup_nicknameInput.value = '';
    signup_passwordInput.value = '';
    signup_passwordCheckInput.value = '';
    
    document.querySelector('.signup_complete').classList.add('on');
    document.querySelector('.signup_container').classList.add('off');
    document.querySelector('.login_container').classList.add('on');
  }
}

여기서 중요한 조건값이 들어간다.

우리는 회원가입 진행 시 닉네임 기입과 비밀번호 일치 여부를 확인할텐데 이를 해당 에러 메세지의 class 여부로 판별할 것이다.

 

조건이 참일 때에만 다음 단계인 로그인창이 뜨게 된다.

 

(3) 닉네임 기입, 비밀번호 일치 여부 확인

닉네임 입력창을 누를 때 실행되는데 그저 간단하게 닉네임칸이 비어있지 않을 경우에 에러창을 off시키는 것이다.

 

비밀번호 일치 여부는 비밀번호와 비밀번호 확인창에 무엇인가 입력할 때 실행되는데 누를 때마다 비밀번호값과 비밀번호 확인값을 갱신하고 마찬가지로 이 두 값이 일치할 때에만 에러창을 off시킨다.

// 닉네임을 누를 때 실행
signup_nicknameInput.addEventListener('keyup', function () {
  // signup_nicknameInput에 입력된 값을 찾아와 signup_nickname에 대입
  signup_nickname = signup_nicknameInput.value;
  // 닉네임칸이 비어있지 않을 경우 에러창 off
  if(signup_nickname !== '') {
    document.querySelector('.error_signup_nickname').classList.add('off');
  } else {
    document.querySelector('.error_signup_nickname').classList.remove('off');
  }
});

// 비밀번호 일치 여부 확인 함수
function signup_passwordCheckFn() {
  if (signup_password !== signup_passwordCheck) {
    document.querySelector('.error_signup_password').classList.remove('off');
  } else {
    document.querySelector('.error_signup_password').classList.add('off');
  }
}

// 비밀번호를 누를 때 실행
signup_passwordInput.addEventListener('keyup', function () {
  // signup_passwordInput에 입력된 값을 찾아와 signup_password에 대입
  signup_password = signup_passwordInput.value;
  // signup_passwordCheckInput에 입력된 값을 찾아와 signup_passwordCheck에 대입
  signup_passwordCheck = signup_passwordCheckInput.value;

  signup_passwordCheckFn();
});

// 비밀번호 확인을 누를 때 실행
signup_passwordCheckInput.addEventListener('keyup', function () {
  // signup_passwordInput에 입력된 값을 찾아와 signup_password에 대입
  signup_password = signup_passwordInput.value;
  // signup_passwordCheckInput에 입력된 값을 찾아와 signup_passwordCheck에 대입
  signup_passwordCheck = signup_passwordCheckInput.value;

  signup_passwordCheckFn();
});

 


 

3. 로그인

(1) 변수 선언

로그인 시에는 이메일과 비밀번호값을 통해서만 진행되고 emailIndex와 index는 로그인 진행 시 입력한 이메일과 비밀번호가 일치하는지 대조하기 위해 선언하는 변수이다.

// 로그인=======================================================================================================
// 이메일, 비밀번호를 입력하는 login-form
const loginForm = document.querySelector('#login-form');
const login_emailInput = document.querySelector('#login_email');
const login_passwordInput = document.querySelector('#login_password');

let emailIndex = 0;
let index = 0;

 

(2) 로그인 진행

로그인 버튼 클릭 시 진행되는데 이메일과 비밀번호 input에 입력된 값을 받아온 뒤 InfoList 데이터를 받아와 반복문을 돌려준다.

 

InfoList에 있는 데이터의 길이만큼 반복해주는데 입력한 이메일값과 InfoList의 데이터에 있는 이메일값이 일치할 경우 해당 index를 emailIndex 변수에 대입해주고

입력한 비밀번호와 emailIndex에 해당하는 InfoList의 비밀번호가 일치한다면 이를 해당 회원의 index로 지정하고 환영 인사 페이지에서 회원의 닉네임을 대입해주는 것이다.

// 로그인 버튼 클릭 시 실행
function onLoginSubmit(e) {
  // 이벤트 방지
  e.preventDefault();

  // login_emailInput에 입력된 값을 찾아와 login_email에 대입
  login_email = login_emailInput.value;
  // login_passwordInput에 입력된 값을 찾아와 login_password에 대입
  login_password = login_passwordInput.value;

    // input값 초기화
    signup_emailInput.value = '';
    signup_nicknameInput.value = '';

  // 로컬스토리지 InfoList에 저장되어있는 값을 불러와 json형태로 변형 후 lists에 대입
  const lists = JSON.parse(localStorage.getItem(InfoList));
  // lists의 길이만큼 반복문을 돌림
  for(var i = 0; i <= lists.length; i++) {
    if(login_email === lists[i].signup_email) {
      // 해당 index 저장
      emailIndex = i;
      if(login_password === lists[emailIndex].signup_password) {
        index = emailIndex;

        document.querySelector('.login_container').classList.remove('on');
        // 환영 인사 페이지 on
        document.querySelector('.welcome_container').classList.add('on');
        document.querySelector('.welcome_container p .welcome_nickname').textContent = lists[emailIndex].signup_nickname;
      }
    }
  }
}

loginForm.addEventListener('submit', onLoginSubmit);

 

그럼 히원가입 후 해당 이메일과 비밀번호로 로그인 시 아래와 같이 우리가 입력했던 닉네임으로 환영인사가 나오는 것을 확인할 수 있다.

 

사실 여기에서 보충되어야 할 기능이 많다.

중복 회원가입 불가라든가 닉네임 중복 불가라든가...

 

하지만 우선 Local Storage로 회원가입/로그인 기능을 구현하는 것 자체가 바람직하지 않기에 우선 이만큼만 구현을 해보고 더욱 정확한 기능은 firebase를 통해 진행해보자.