WeniVooks

검색

JavaScript 베이스캠프

로컬스토리지

로컬스토리지 이해하기

로컬스토리지는 웹 브라우저에서 데이터를 영구적으로 저장할 수 있는 방법 중 하나입니다. 로컬스토리지에 저장된 데이터는 브라우저를 닫거나 컴퓨터를 재부팅해도 유지됩니다.

로컬스토리지는 개발자도구를 열어 확인할 수 있습니다. 개발자도구를 열고 Application 탭을 클릭하면 Storage 섹션에 Local Storage를 확인할 수 있습니다.

로컬스토리지에 있는 값은 클릭해서 삭제할 수도 있는데요. 자사 서비스인 스터디인에 로그인 한 후 이 로컬스토리지에 값들을 비워보세요. 그러면 로그아웃이 되는 것을 확인할 수 있습니다.

1. 로컬스토리지란?

로컬스토리지는 브라우저에서 제공하는 클라이언트 측 저장소입니다. 주요 특징은 다음과 같습니다.

  • 영구성: 데이터를 명시적으로 삭제하지 않는 한 유지됩니다.
  • 키-값 쌍: 데이터를 키-값 쌍으로 저장합니다.
  • 문자열 저장: 모든 데이터는 문자열 형식으로 저장됩니다.
2. 로컬스토리지 사용법

로컬스토리지의 주요 메서드는 다음과 같습니다.

  • setItem(key, value): 키-값 쌍 저장
  • getItem(key): 키에 해당하는 값 호출
  • removeItem(key): 키에 해당하는 값 삭제
  • clear(): 모든 데이터 삭제
  • key(index): 인덱스에 해당하는 키 호출
  • length: 저장된 항목의 개수
3. 기본 사용 법

아래 파일을 html 파일로 만들어서 브라우저에서 실행해보세요.

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <title>로컬스토리지 기본 사용</title>
  </head>
  <body>
    <script>
      // setItem: 데이터 저장
      localStorage.setItem('name', 'licat');
      localStorage.setItem('age', '10');
 
      // getItem: 데이터 호출
      console.log(localStorage.getItem('licat')); // licat
      console.log(localStorage.getItem('age')); // 10
 
      // removeItem: 데이터 삭제
      localStorage.removeItem('name');
 
      // clear: 모든 데이터 삭제
      localStorage.clear();
    </script>
  </body>
</html>
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <title>로컬스토리지 기본 사용</title>
  </head>
  <body>
    <script>
      // setItem: 데이터 저장
      localStorage.setItem('name', 'licat');
      localStorage.setItem('age', '10');
 
      // getItem: 데이터 호출
      console.log(localStorage.getItem('licat')); // licat
      console.log(localStorage.getItem('age')); // 10
 
      // removeItem: 데이터 삭제
      localStorage.removeItem('name');
 
      // clear: 모든 데이터 삭제
      localStorage.clear();
    </script>
  </body>
</html>

이번에는 일반 텍스트가 아니라 객체를 저장해보겠습니다. 로컬스토리지는 문자열 형식으로만 데이터를 저장할 수 있으므로, 객체나 배열을 저장하려면 JSON.stringify를 사용하여 문자열로 변환해야 합니다.

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>로컬스토리지 객체와 배열 저장</title>
  </head>
  <body>
    <script>
      const memoArray = ['메모1', '메모2'];
      localStorage.setItem('memos', JSON.stringify(memoArray));
 
      const memoObject = { one: '메모1', two: '메모2' };
      localStorage.setItem('memoObject', JSON.stringify(memoObject));
 
      console.log(JSON.parse(localStorage.getItem('memos'))); // ['메모1', '메모2']
      console.log(JSON.parse(localStorage.getItem('memoObject'))); // { one: '메모1', two: '메모2' }
    </script>
  </body>
</html>
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>로컬스토리지 객체와 배열 저장</title>
  </head>
  <body>
    <script>
      const memoArray = ['메모1', '메모2'];
      localStorage.setItem('memos', JSON.stringify(memoArray));
 
      const memoObject = { one: '메모1', two: '메모2' };
      localStorage.setItem('memoObject', JSON.stringify(memoObject));
 
      console.log(JSON.parse(localStorage.getItem('memos'))); // ['메모1', '메모2']
      console.log(JSON.parse(localStorage.getItem('memoObject'))); // { one: '메모1', two: '메모2' }
    </script>
  </body>
</html>
3. 메모장 예제

로컬스토리지를 사용하여 간단한 메모장 애플리케이션을 만들어보겠습니다. 사용자가 입력한 메모를 저장하고, 저장된 메모를 화면에 표시하며, 삭제할 수 있는 기능을 구현합니다. 아래 소스코드를 활용하여 메모장 예제를 완성해보세요.

<!DOCTYPE html>
<html lang="ko">
  <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" />
    <style>
      main {
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
      }
 
      input {
        display: block;
        width: 300px;
        height: 30px;
        margin-bottom: 10px;
      }
 
      textarea {
        display: block;
        width: 300px;
        height: 300px;
        margin-bottom: 10px;
      }
 
      button {
        display: block;
        width: 306px;
        height: 30px;
      }
    </style>
  </head>
  <body>
    <main>
      <section>
        <input type="text" name="" id="title" />
        <textarea name="" id="content" cols="30" rows="10"></textarea>
        <button onclick="saveNote()">메모</button>
      </section>
      <section id="display"></section>
    </main>
    <script>
      let allMemo = JSON.parse(localStorage.getItem('allMemo'));
      allMemo = allMemo ?? [];
      render();
 
      function saveNote() {
        const title = document.getElementById('title').value;
        const content = document.getElementById('content').value;
 
        allMemo.push({ title, content, len: allMemo.length });
 
        localStorage.setItem('allMemo', JSON.stringify(allMemo));
        render();
      }
 
      function render() {
        const display = document.getElementById('display');
        display.innerHTML = '';
 
        // // 최신 게시물이 위로 올라오도록
        // for (let i = allMemo.length; i > 0 ; i--) {
        //     // 아래와 유사 코드
        // }
 
        for (const item of allMemo) {
          const saveTitle = document.createElement('h2');
          const saveContent = document.createElement('p');
          const saveId = document.createElement('p');
          const deleteMemoBtn = document.createElement('button');
 
          saveTitle.textContent = item.title;
          saveContent.textContent = item.content;
          saveId.textContent = item.len + 1;
          deleteMemoBtn.textContent = '삭제';
          deleteMemoBtn.setAttribute('id', item.len);
          deleteMemoBtn.setAttribute('onclick', 'remove()');
 
          display.appendChild(saveId);
          display.appendChild(saveTitle);
          display.appendChild(saveContent);
          display.appendChild(deleteMemoBtn);
        }
      }
 
      function remove() {
        // console.log(event.srcElement.id);
        // console.log(allMemo);
        const idx = allMemo.find((item) => item.len == event.srcElement.id);
        if (idx) {
          allMemo.splice(
            allMemo.findIndex((item) => item.len == idx.len),
            1,
          );
        }
        localStorage.setItem('allMemo', JSON.stringify(allMemo));
        render();
      }
    </script>
  </body>
</html>
<!DOCTYPE html>
<html lang="ko">
  <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" />
    <style>
      main {
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
      }
 
      input {
        display: block;
        width: 300px;
        height: 30px;
        margin-bottom: 10px;
      }
 
      textarea {
        display: block;
        width: 300px;
        height: 300px;
        margin-bottom: 10px;
      }
 
      button {
        display: block;
        width: 306px;
        height: 30px;
      }
    </style>
  </head>
  <body>
    <main>
      <section>
        <input type="text" name="" id="title" />
        <textarea name="" id="content" cols="30" rows="10"></textarea>
        <button onclick="saveNote()">메모</button>
      </section>
      <section id="display"></section>
    </main>
    <script>
      let allMemo = JSON.parse(localStorage.getItem('allMemo'));
      allMemo = allMemo ?? [];
      render();
 
      function saveNote() {
        const title = document.getElementById('title').value;
        const content = document.getElementById('content').value;
 
        allMemo.push({ title, content, len: allMemo.length });
 
        localStorage.setItem('allMemo', JSON.stringify(allMemo));
        render();
      }
 
      function render() {
        const display = document.getElementById('display');
        display.innerHTML = '';
 
        // // 최신 게시물이 위로 올라오도록
        // for (let i = allMemo.length; i > 0 ; i--) {
        //     // 아래와 유사 코드
        // }
 
        for (const item of allMemo) {
          const saveTitle = document.createElement('h2');
          const saveContent = document.createElement('p');
          const saveId = document.createElement('p');
          const deleteMemoBtn = document.createElement('button');
 
          saveTitle.textContent = item.title;
          saveContent.textContent = item.content;
          saveId.textContent = item.len + 1;
          deleteMemoBtn.textContent = '삭제';
          deleteMemoBtn.setAttribute('id', item.len);
          deleteMemoBtn.setAttribute('onclick', 'remove()');
 
          display.appendChild(saveId);
          display.appendChild(saveTitle);
          display.appendChild(saveContent);
          display.appendChild(deleteMemoBtn);
        }
      }
 
      function remove() {
        // console.log(event.srcElement.id);
        // console.log(allMemo);
        const idx = allMemo.find((item) => item.len == event.srcElement.id);
        if (idx) {
          allMemo.splice(
            allMemo.findIndex((item) => item.len == idx.len),
            1,
          );
        }
        localStorage.setItem('allMemo', JSON.stringify(allMemo));
        render();
      }
    </script>
  </body>
</html>
11장 부록11.2 날짜와 시간