localStorage는 web storage 중 하나로 서버에 데이터를 저장하는 방식이 아닌 웹 브라우저 상에서 데이터를 저장할 수 있는 방식이다. 키와 값으로 데이터가 이루어져 있으며 이런 형식으로 이루어져 있다.
localStorage.setItem("key", value); // > setItem
// > getItem, removeItem("key");
// > clear(); 클리어
로그인 화면에서 이름 데이터 값을 localStorage에 저장하고, 그 저장한 값을 불러들여 화면에 출력하는 방식을 사용하면 매커니즘 자체는 어렵지 않으나 후술할 문제 때문에 꽤 오랜 시간이 걸렸다.
코드 리뷰
<main class="main__user-interface hidden">
<div class="user-interface__weather window">
<div class="window__header">
<span><span class="header__window-username"></span> - Weather</span>
<img src="images/close-icon.png" alt="">
</div>
</div>
<div class="user-interface__status-bar">
<div class="status-bar__start"></div>
<div class="status-bar__clock"><span>00:00</span></div> <!-- TIME 추가될 곳 -->
</div>
</main>
const loginName = document.querySelector(".login__form input#name");
const windowUsername = document.querySelector(".header__window-username")
const greeting = document.querySelector(".main__greeting"); // login
const userInterface = document.querySelector(".main__user-interface"); // user-interface
const HIDDEN_CLASSNAME = "hidden"
const USERNAME_KEY = "username"
function onLoginSubmit(event) {
event.preventDefault();
greeting.classList.add(HIDDEN_CLASSNAME);
const username = loginName.value;
localStorage.setItem(USERNAME_KEY, username);
paintLogins(username);
}
function paintLogins(username) {
windowUsername.innerText = `${username}`;
userInterface.classList.remove(HIDDEN_CLASSNAME);
}
const savedUsername = localStorage.getItem(USERNAME_KEY);
if (savedUsername === null) {
greeting.classList.remove(HIDDEN_CLASSNAME);
loginForm.addEventListener("submit", onLoginSubmit);
} else {
paintLogins(savedUsername);
}
- submit를 제출하면 호출되는 함수 onLoginSubmit에 username의 변수를 선언하고 그 값을 submit될 때 받아오는 값, 즉 name input의 값으로 작성해준다. (loginName의 value = loginName.value)
- localStorage.setItem() 메서드에 "username"이라는 키와 username이라는 값을 추가한다. setItem은 키에 데이터를 씌우는 것이고, getItem과 removeItem은 키를 가져오거나 삭제하는 등 제어할 수 있다.
- "username"이라는 string이 too much 반복 되고 있기 때문에 (대문자로) USERNAME_KEY 라는 변수에 값을 저장해준다.
- windowUsername 은 웹에서 localStorage에 저장된 값이 출력되는 곳이다. innerText를 이용해 setItem 했던 username을 넣어주었다.
여기까진 단순하게 submit(로그인) 하고 → submit 하는 순간 name에 있는 값을 로컬 스토리지 값에 저장하고 → 그 저장된 값을 string으로 출력해주는 일련의 과정일 뿐이었다.
하지만 우리는 새로고침을 하거나 세션이 만료되지 않을 때에도 로그인을 유지하고 싶고 혹여나 세션이 만료된다면 (=로컬 스토리지의 값을 잃는다면) 다시 로그인 화면을 띄우고 싶다.
그럴 때 조건문을 사용해보는 거다. 컴퓨터야, 만약 내가 로컬 스토리지에 값이 없다면 로그인 화면을 띄울 거고, 그렇지 않다면 유저 화면을 보여줘. 마치 주문을 거는 것처럼.
- 앞서 말했던 getItem은 키를 가져올 수 있다. localStorage의 username key는 이제 savedUsername 변수의 값이 되었다.
- 만약(if) savedUsername의 데이터가 null 이라면(없는 정보를 받아옴), 즉 로컬 스토리지에 데이터가 없다면 로그인 화면의 hidden class를 지워 준다. 그리고 submit 이벤트 리스너를 넣어준다.
- 그렇지 않다면(else) 유저 화면의 hidden class를 제거하고 innerText를 통해 string 값이 수정된다. 이 과정은 onLoginSubmit 에서도, 조건문에서도 사용되기 때문에 재사용성을 위해 paintLogins 라는 함수를 만들어 묶어주었다.
- 함수 onLoginSubmit의 인자와 paintLogin의 인자가 다른 이유?
paintLogin(savedUsername) 은 하는 일이 화면에 출력되는 일 뿐이다. (유저 화면, 유저 화면 내 스트링) 또 유저정보가 savedUsername 이라는 로컬 스토리지에서 getItem 하고 있다.
onLoginSubmit(event)는 name이라는 id를 가진 input에서 오고 있다. (loginName.value)
- 함수 onLoginSubmit의 인자와 paintLogin의 인자가 다른 이유?
결과물
개 빡센 디버깅의 세계
로직은 정상적으로 짠 거 같은데 정상적으로 친 것 같은데 왜 동작이 안되는 거야?
성공적으로 로그인하고, localStorage에 데이터도 정상적으로 있는 거 확인. 음! 잘 굴러가는군? localStorage에 데이터가 있으면 유저 화면을 띄우고, 없다면 로그인 화면을 띄우는 실험을 위해 새.로.고.침!
어? 어디갔지?
...
위에서부터 하나하나 읽으면서 어떻게 동작하는 지 파악하고, 모든 변수를 콘솔로깅 해보고, 줄 위치도 바꿔보았다. 그러면서 useless한 문도 지우기도 하고... 한참을 멍하게 모니터만 바라보다가 미묘하게 거슬리는 한 줄이 있어 보니 오타..... 쌍욕을 박고 수정하니 정상적으로 동작하더라. 고작 30줄 남짓의 짧은 코딩에도 이런 문제가 생기는 데 나중에 현업에 투입됐을 때 코드들을 어떻게 처리해야 할지 조금 두려워 졌다. 코딩은 금방, 디버깅이 진짜라는 말이 틀린 말은 아닌 것 같다.
그리고 이름은 처음 지을 때 잘 짓자. 변수명을 고치고 이벤트명을 고치는 과정에서 사람이 개입하게 되면 실수가 생기니까. 하지만 아직까지 이름 짓는 건 잘 못하겠다...
마무리하며
함수로 묶을 수 있는 문과 아닌 문은 무엇인가? 함수 이름 옆에 붙어있는 얘 (☞゚ヮ゚)☞ (), return, 전역변수, 지역변수, 함수의 인자는 무엇이며 자바스크립트 내부에서 값은 어떻게 반환이 되고 있는가? 등등 프로그래밍의 기초라 할 수 있는 이런 기본 개념이 너무 부족한 것 같다. 코드를 봐도 왜 이렇게 되는지 정확한 대답을 못내려서 답답하다. 나의 지식이 너무 얕고 기초가 너무 부실해. deep dive를 하루에 30분은 읽도록 해야겠다.
'TIL LIST > JavaScript' 카테고리의 다른 글
[chrome app 코딩 챌린지] 5. 위치 정보 가져오기(API) (0) | 2022.06.26 |
---|---|
[chrome app 코딩 챌린지] 4. 시스템 시간 가져오기 (0) | 2022.06.21 |
[chrome app 코딩 챌린지] 2. 버튼 클릭 시 랜덤 이미지 출력 (0) | 2022.06.19 |
[chrome app 코딩 챌린지] 1. 로그인 화면 (0) | 2022.06.18 |
바닐라JS 강의 완강 (0) | 2022.06.15 |