본문 바로가기
TIL/JavaScript

2021.7.5 TIL : [JavaScript] 자바스크립트 기초-3

by yeon_zoo 2021. 7. 5.

오늘은 로그인 박스(폼)을 만드는데 자바스크립트를 이용해볼 것이다.

1. HTML 에서 로그인 폼 만들기

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <title>Momentum</title>
</head>
<body>
    <form id="login-form">
        <input required maxlength="15" type="text" placeholder="What is your name?">
        <button>Log In</button>
        <script src="app.js"></script>
    </form>
</body>
</html>

여기서 div 대신 form을 사용하는 이유는 input tag의 required 속성을 쓰려면 해당 Input이 form 내부에 위치해 있어야 하기 때문이다. 따라서 form 태그로 사용해주는 것이 좋다(해당 기능은 브라우저에서 자체 제공해준다. 15자 이상 입력하면 입력되지 않고, 비어있으면 역시 입력란을 작성하라는 안내 문구를 띄워준다). 이 때 form 태그의 특징은, input에 어떤 단어를 쓰고 엔터를 치거나 버튼을 누르면 페이지가 새로 고침된다는 것이다.

 

따라서 우리는 자바스크립트로 입력된 정보를 저장하고 페이지가 새로고침되는 것을 막는 과정을 진행해 볼 것이다.

 

2. 자바스크립트 활용

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

function LoginSubmit(event){
    event.preventDefault();
    console.log(loginInput.value);
}

loginForm.addEventListener("submit", LoginSubmit)

여기서 이해할 점은 함수에서 매개변수로 event(이벤트 객체)라는 것을 넘겨 받았다는 것이다. js 파일 내에서 EventListener로 LonginSubmit() 함수를 호출하면 어떤 유의미한 정보(사용자가 방금 행동한 이벤트에 대한 정보)를 넘겨 주게 되는데, 이를 우리가 쉽게 파악할 수 있도록 매개변수의 이름을 지정해준 것이다. 만약 지정해주지 않으면 아무것도 넘겨 받지 않게 된다. (이 매개변수 명은 보통 event 로 지정해 주는 것이 관행이라고 한다.) 

preventDefault() 함수는 어떤 event의 기본 행동이든지 발생하지 않도록 막는 것이다.  그리고 우리가 입력한 값은 loginInput.value (input 태그 내의 value) 내에 기록되니 그것을 console.log 해주면 콘솔창에서도 확인할 수 있다. 

 

event는 여러 종류가 있기 때문에 이번에는 다른 이벤트의 종류를 볼 것이다. 다음과 같은 html 코드를 추가해주자.

<a class="link" href="https://naver.com">Go to Naver</a>

그리고 자바스크립트에는 이런 코드를 추가한다.

const link = document.querySelector(".link");

function linked(event){
    console.log(event);
    alert("Link clicked!");
}

link.addEventListener("click", linked);

이렇게 추가하게 되면 콘솔 창에 다음과 같은 내용이 뜬다.

로그인 박스에 입력하고 버튼을 눌렀을 때는 SubmitEvent가 떴던 것과는 달리, MouseEvent가 뜨며 클릭한 마우스의 좌표가 적혀 있다. 이러한 event 정보를 통해 사용자의 마우스가 어딜 클릭했는지 파악할 수 있다. 

 

그러면 로그인 폼에서 사용자의 이름을 입력받고, 사용자에게 인사를 보내는 페이지를 만들어 보자. 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <title>Momentum</title>
</head>
<body>
    <form id="login-form">
        <input required maxlength="15" type="text" placeholder="What is your name?">
        <button>Log In</button><br>
    </form>
    <h1 id="greeting" class="hidden"></h1>
    <script src="app.js"></script>
</body>
</html>

 

body{
    background-color: beige;
}
.hidden{
    display: none;
}

위의 html과 css 코드를 먼저 작성해 준다. 그리고 app.js 파일에는 다음과 같이 해준다. 

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

function LoginSubmit(event){
    event.preventDefault();
    const username = loginInput.value;
    loginForm.classList.add("hidden");
    greeting.innerText = `Hello ${username}`;
    greeting.classList.remove("hidden");
    console.log(username);
}

loginForm.addEventListener("submit", LoginSubmit);

여기서는 css를 이용하여 페이지를 이동하지 않고, 사용자에게 인사를 보낼 수 있다. 즉, css에 hidden 클래스 속성으로 display:none;을 주면 더 이상 눈에 보이지 않게 된다. 이를 이용하면, submit 이벤트가 발생했을 때, 로그인 폼은 hidden을 해주고, 이미 hidden 되어 있던 h1 태그는 hidden 클래스를 제거 해주어 보여지도록 하면 된다. 여기서 새로운 문자열 포매팅 방식이 나오는데 당연히 "Hello " + username과 같은 식으로 해도 되지만, 다른 언어에서도 그랬듯이 확실히 따옴표와 플러스 기호를 이용하는 것보다 저런 기호를 이용하는 것이 더 편리하다. 주의할 점은 `Hello ${username}` 인 것! 양 끝의 기호가 따옴표나 쌍따옴표가 아닌 ` 이다. 

 

그런데 이렇게 일시적으로 저장된 username은 페이지를 새로고침하면 날아가고 새로 입력해야 한다. 보통 이렇게 일시적인 저장보다는 다시 페이지를 로딩했을 때도 저장되어 있기를 바란다. 예를 들면 유투브에서 음량을 조절했을 때, 다시 페이지를 로딩하더라도 내가 조절했던 대로 음량이 유지되는 것처럼 말이다. 어떻게 이것을 할 수 있을까?

 

3. 로컬 저장소에 저장해두기

기본적으로 브라우저에서 제공되는 API 중에 local storage가 있다. (JS에도 이미 존재하는 객체) 이건 브라우저에서 오른쪽 마우스 클릭 > Inspect(혹은 검사) > Application > Local Storage 에서 찾을 수 있다. 작은 DB같은 것으로 이해하면 된다. key 값과 value 값을 입력하여 key 값으로 value 값을 불러올 수 있다. 아래 코드를 LoginSubmit 함수 안에 입력하면 저장된다. 넘겨주는 매개변수 중에 앞에 것이 key, 뒤가 value 이다. local storage에는 getItem, setItem, deleteItem을 사용하여 데이터를 확인, 추가 및 삭제 해 줄 수 있다. 

localStorage.setItem("username", username);

위의 사진처럼 나오게 되면 성공! 하지만 여전히 페이지를 새로고침하면 로그인 폼이 나타난다. 그래서 로컬 저장소에 username이 있다면, 그대로 인사말이 등장하게 하고, 없다면 로그인 폼이 나타나도록 만들어야 한다.

 

4. Username 가져오기

저장된 username이 없으면 로그인 폼을 띄우고, 있다면 인사말을 띄우도록 하는 것은 저장소에 해당 정보가 있는지 확인해주면 쉽게 해결할 수 있다. 만약 저장된 것이 없는 상태에서 자바스크립트를 이용하여 검색하면 다음과 같은 결과(null)이 나온다.

따라서 이것을 이용하여 만들어 주면 된다. 이걸 좀 더 쉽게 하기 위해서는 로그인 폼과 인사말 모두에 hidden 클래스를 주고 시작하는 것이 좋다. 이렇게 했을 때, 로컬 스토리지에 있는지 없는지를 파악하여 로그인 폼을 보여주거나 인사말을 보여주는 과정을 선택할 수 있다. 그리고 나서 app.js를 다음과 같이 업데이트 해주면 된다.

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

const HIDDEN_CLASSNAME = "hidden";
const USERNAME_KEY = "username";

function LoginSubmit(event){
    event.preventDefault();
    const username = loginInput.value;
    loginForm.classList.add(HIDDEN_CLASSNAME);
    localStorage.setItem(USERNAME_KEY, username);
    greeting.innerText = `Hello ${username}`;
    greeting.classList.remove(HIDDEN_CLASSNAME);
    console.log(username);
}

const savedUsername = localStorage.getItem(USERNAME_KEY);

if (savedUsername === null){
    loginForm.classList.remove(HIDDEN_CLASSNAME);
    loginForm.addEventListener("submit", LoginSubmit);
} else{
    greeting.classList.remove(HIDDEN_CLASSNAME);
    greeting.innerText = `Hello ${savedUsername}`;
}

이렇게 해주면 된다. 이 때, HIDDEN_CLASSNAME이나 USERNAME_KEY와 같은 반복적인 문자열들은 변수를 지정해주는 것이 좋은데, "username"을 계속 사용하게 되면, 오타가 날 가능성이 높아지고 특히 이 문자열은 자바스크립트 내 변수가 아니기 때문에 오타가 나도 에러가 뜨지 않아서 어디서 틀렸는지 모른다. 대부분의 에러들이 오타에서 온다는 것을 기억해보면.. 변수명 지정이 귀찮기는 해도 꼭 해놔야 할 것 같다. 

 

위의 코드를 보면, hidden이라는 클래스를 지우는 코드가 두 번이나 들어가있다. (LoginSubmit 함수에서 한 번, if문에서도 한번) 이런 코드들이 중복되면, 새로운 함수로 지정해서 함수를 호출하는 방식으로 가는 것이 좋다.

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

const HIDDEN_CLASSNAME = "hidden";
const USERNAME_KEY = "username";

function showGreeting(username){
    greeting.innerText = `Hello ${username}`;
    greeting.classList.remove(HIDDEN_CLASSNAME);

}

function LoginSubmit(event){
    event.preventDefault();
    const username = loginInput.value;
    loginForm.classList.add(HIDDEN_CLASSNAME);
    localStorage.setItem(USERNAME_KEY, username);
    showGreeting(username);
}

const savedUsername = localStorage.getItem(USERNAME_KEY);

if (savedUsername === null){
    loginForm.classList.remove(HIDDEN_CLASSNAME);
    loginForm.addEventListener("submit", LoginSubmit);
} else{
    showGreeting(savedUsername);
    greeting.innerText = `Hello ${savedUsername}`;
}

 

댓글