Front-End/JavaScript

[노마드코더 / 바닐라JS] momentum 클론 코딩(2)_Login

Olivia Kim 2023. 3. 23. 03:59
반응형

 

📚 노마드코더의 '바닐라 JS로 크롬 앱 만들기'를 수강하며 배우거나 추가적으로 찾아본 것들을 정리한 내용입니다.

 

Input Values

이름을 입력받을 input과 버튼을 만든 후, 버튼 클릭을 감지해서 input의 입력값을 console.log에 찍어본다.

// HTML
<body>
  <div id="login-form">
    <input type="text" placeholder="Whai is your name?" />
    <button>Log In</button>
  </div>

  <!-- html보다 js가 먼저 로드될 경우 js에서 지정한 요소를 못찾을 수 있어, body의 맨 마지막에 작성한다. -->
  <script src="app.js"></script>
</body>
// JavaScript

/*
const loginForm = document.querySelector('#login-form');
const loginInput = loginForm.querySelector('input');
const loginButton = loginForm.querySelector('button');
*/

// * 위의 코드를 더 짧게 바꿔보기
// 이와 같이 document 또는 하나의 element를 통해서 검색이 가능하다.
const loginInput = document.querySelector('#login-form input');
const loginButton = document.querySelector('#login-form button');

// 사용자가 버튼을 클릭했을 때를 감지해서 console.log에 찍는 이벤트 만들어보기
function onLoginBtnClick() {
  console.log(loginInput.value);
}

loginButton.addEventListener('click', onLoginBtnClick);

 

 


Form Submisson

username의 유효성 검사를 진행한다.

  • username이 비어있으면 안된다.
  • username이 너무 길면 안된다.

user가 입력한 값의 유효성을 검증하는 것은 좋은 습관이다. user를 믿으면 안된다!

 

 

조건에 따라 유효성 검사를 하기 위해 다음과 같이 JS를 작성할 수 있다.

  if(username === '') {
    alert('Please write your name.');
  } else if(username.length > 15) {
    alert('Your name is too long.');
  }

 

 

위와 같이 JS로 유효성 검사를 하는 것도 좋지만, 이미 가지고 있는 기능을 사용하는 것이 좋다. 바로 input에 maxlength와 requred를 추가하는 것!

 

 

단, input의 유효성 검사를 작동시키기 위해서는 input이 <form></form> 태그 안에 있어야 한다. 이 안에 input이 위치하지 않는다면 maxlength와 required는 작동하지 않는다.

// HTML
<body>
  <form id="login-form">
    <input type="text" maxlength="15" placeholder="Whai is your name?" required />
    <button>Log In</button>
  </form>

  <script src="app.js"></script>
</body>

 

 

위와 같이 유효성 검사를 HTML로 세팅한 뒤 로그인 버튼을 클릭하면, 페이지가 '새로고침'되는 문제가 발생한다. 새로고침하게 되면 input에 작성한 값이 사라져버린다. 이 이유는, form이 submit되고 있기 때문이다.

 

  1. input 안에 있는 button을 누르거나 type이 submit인 input을 클릭하면 form은 submit된다.
  2. form 안에서 enter를 눌렀을 때 input이 더 존재하지 않는다면 해당 form은 submit된다.

 

우리가 원하는 것은 브라우저가 새로고침을 하지 않고 user 정보를 저장하는 것이다. 어떻게 할 수 있을까?

 

 


Events

위의 코드에서 발생했던 문제상황인 submit event가 발생하는 것을 아예 막거나, 중간에 개입해 submit event가 발생했다는 것을 파악하고자 한다.

 

 

해결책을 찾아보기 위해, 브라우저가 우리가 작성한 코드를 어떻게 불러오고 전달해주는지 먼저 알아보자.

loginForm.addEventListener('submit', onLoginSubmit);

 

위의 코드는 다음의 순서로 진행된다.

 

  1. submit 이벤트를 감지한 브라우저는 지정된 onLoginSubmit을 호출한다.
  2. 이때, 브라우저는 해당 함수를 호출하면서 어떤 argument(인수, 전달인자 : 메서드가 호출될 때 전달되는 실제 값)를 가지고 호출한다. 즉, onLoginSubmit이 onLoginSubmit() 처럼 비어있는 채로 호출되지 않고 () 안에 추가적인 정보를 담아서 호출한다는 것!
  3. 이 정보의 정체는 바로, '발생한 일에 대해 내가 필요로 할만한 정보들'을 전달해주는 것이다. 모든 EventListen function의 첫번째 argument는 항상 '지금 막 벌어진 일들에 대한 정보'이다.

 

 

따라서 우리는 매개변수 부분에 정보를 읽을 수 있는 공간만 제공하면 얼마든지 읽어올 수 있다. 다음과 같이 코드를 작성해 어떤 정보를 전달해주는지 확인해보자. onLoginSubmit() 안의 첫 번째 매개변수 명은 아무 단어나 입력해도 확인할 수 있다.

function onLoginSubmit(olivia) {
    // 새로고침을 막는다.
    olivia.preventDefault();
    console.log(olivia);
}

loginForm.addEventListener('submit', onLoginSubmit);

 

위 코드의 출력값

 

우리가 하고자 했던 새로고침을 막아주는 코드도 argument로 받아와 콘솔에 찍어본 내역 중 defaultPrevented로 확인할 수 있다. preventDefault의 역할은 어떤 event의 기본 행동(어떤 function에 대해 브라우저가 기본적으로 수행하는 동작)이든지 발생되지 '않도록' 막는 것이다. 따라서 form을 submit하면 기본 행동은 새로고침이므로, 해당 코드를 작성하여 새로고침을 막을 수 있다.

 

 


Getting Username

이제 user가 이름을 제출하면, form(input, button) 자체를 없애는 것(=== HTML 요소를 화면에 안보이도록 없애는 것)을 구현해본다.

// HTML
<body>
  <form id="login-form">
    <input type="text" maxlength="15" placeholder="Whai is your name?" required />
    <button>Log In</button>
  </form>
  <h1 class="hidden" id="greeting"></h1>

  <script src="app.js"></script>
</body>
// CSS
.hidden {
  display: none;
}
const loginForm = document.querySelector('#login-form');
const loginInput = document.querySelector('#login-form input');
const greeting = document.querySelector('#greeting');

// 'hidden'을 두 번 사용하고 있으니 아예 변수로 선언해서 오류 발생의 위험을 줄인다.
// string만 포함된 변수는 대문자로 표기하고 string을 저장하고 싶을 때 사용한다.
const HIDDEN_CLASSNAME = 'hidden';

function onLoginSubmit(event) {
  event.preventDefault();

  // 1. username을 입력했을 때, className 'hidden'을 부여해 화면에서 보이지 않게 한다.
  const username = loginInput.value;
  loginForm.classList.add(HIDDEN_CLASSNAME);

  // 2. 화면에 숨겨뒀다가 username이 입력되면 화면에 보여주는 HTML 요소를 추가한다.
  greeting.innerText = `Hello, ${username}!`;
  greeting.classList.remove(HIDDEN_CLASSNAME);
}

loginForm.addEventListener('submit', onLoginSubmit);

 

 


Setting Username

사용자가 입력한 username을 매번 입력하지 않아도 되도록 저장해보자. 저장은 local storage를 이용한다.

 

local storage는 우리가 브라우저에 무언가를 저장할 수 있게 해준다. 그래서 나중에 가져다 쓸 수 있다. 저장된 내역은 개발자도구를 연 후 Application > Local Storage에서 확인 가능하다.

 

 

Local Storage에 무언가를 저장하기
✨ localStorage.setItem('key', 'value');

 

 

Local Storage에 저장된 데이터를 가져오기
localStorage.getItem('key', 'value');

 

 

Local Storage에 저장된 데이터를 삭제하기
✨ localStorage.setItem('key', 'value');

 

 

위의 내용을 이용해 코드를 작성해보자.

const loginForm = document.querySelector('#login-form');
const loginInput = document.querySelector('#login-form input');
const greeting = document.querySelector('#greeting');

// 'hidden'을 두 번 사용하고 있으니 아예 변수로 선언해서 오류 발생의 위험을 줄인다.
// string만 포함된 변수는 대문자로 표기하고 string을 저장하고 싶을 때 사용한다.
const HIDDEN_CLASSNAME = 'hidden';

function onLoginSubmit(event) {
  event.preventDefault();
  const username = loginInput.value;
  // localStorage에 사용자가 입력한 username 저장해두기
  localStorage.setItem('username', username);
  loginForm.classList.add(HIDDEN_CLASSNAME);
  greeting.innerText = `Hello, ${username}!`;
  greeting.classList.remove(HIDDEN_CLASSNAME);
}

loginForm.addEventListener('submit', onLoginSubmit);

 

 


Loading Username

local storage에 username이 존재하는지 확인하고, 존재한다면 form을 화면에서 보이지 않도록 한 뒤 h1이 표시되도록 한다.

// HTML
<body>
  <form class="hidden" id="login-form">
    <input type="text" maxlength="15" placeholder="Whai is your name?" required />
    <button>Log In</button>
  </form>
  <h1 class="hidden" id="greeting"></h1>

  <script src="app.js"></script>
</body>
// JavaScript

const loginForm = document.querySelector('#login-form');
const loginInput = document.querySelector('#login-form input');
const greeting = document.querySelector('#greeting');

// 본인이 생성한 string을 반복하게 사용하게 될 경우에는
// 반복되는 string들을 대문자 변수에 저장해놓는 것이 좋다.
// 추후 오타가 났다면 js가 감지해서 오류 알림을 띄워주기 때문이다.
const HIDDEN_CLASSNAME = 'hidden';
const USERNAME_KEY = 'username';

function onLoginSubmit(event) {
  event.preventDefault();
  const username = loginInput.value;
  // localStorage에 사용자가 입력한 username 저장해두기
  localStorage.setItem(USERNAME_KEY, username);
  loginForm.classList.add(HIDDEN_CLASSNAME);
  paintGreetings(username);
}

// h1을 보여주기
function paintGreetings(username) {
  greeting.innerText = `Hello, ${username}!`;
  greeting.classList.remove(HIDDEN_CLASSNAME);
}


// localStorage에 username값이 있는지 확인하기
const savedUsername = localStorage.getItem(USERNAME_KEY);
if(savedUsername === null) {
  // form을 보여주기
  loginForm.classList.remove(HIDDEN_CLASSNAME);
  loginForm.addEventListener('submit', onLoginSubmit);
} else {
  paintGreetings(savedUsername);
}

 

 


[관련 글 함께 보기]

 

 


[참고 자료]

https://nomadcoders.co/javascript-for-beginners

 

바닐라 JS로 크롬 앱 만들기 – 노마드 코더 Nomad Coders

Javascript for Beginners

nomadcoders.co

 

 

반응형