확인한 환경과 범위

Chromium 156.0.8078.74. 본문의 HTML·CSS·JavaScript를 실제 브라우저로 렌더링하고 현재 화면을 캡처했습니다. 모든 조작·레이아웃·접근성을 검증한 것은 아닙니다.

이 글의 순서 2개 단락
직접 고쳐서 실행해보기이 글의 예제로 바로 실습해요.실습 열기
넓은 화면에서 열기 ↗
새로고침하면 사라지는 할 일 목록: localStorage에서 배열 복원하기코드 실행기 ↗
입력값 input() · prompt()에 한 줄씩 전달
실행 결과실행 전
코드를 바꾸면, 결과도 달라져요.

실행하기를 눌러 확인해보세요.

코드는 이 브라우저에 자동 저장돼요.설치 없이 브라우저에서 실행해요.

브라우저 JavaScript 할 일 목록 코스에서 입력값을 배열에 넣고 화면에 그리는 방법을 익혔다면, 이 노트에서 새로고침 후에도 목록을 복원하는 방법을 이어서 살펴보세요. 앞 강의의 파일이 없어도 아래 예제 하나로 실행할 수 있습니다.

새로고침하면 JavaScript가 처음부터 다시 실행됩니다. 이때 let tasks = []로 시작하고 저장된 값을 읽어 오지 않으면, 저장소에 데이터가 남아 있더라도 화면에는 빈 배열이 그려집니다. 반대로 배열을 복원해도 추가나 삭제 후 다시 저장하지 않으면 다음 새로고침에 이전 목록이 나타날 수 있습니다.

시작할 때 읽고, 변경할 때 저장하기

이 예제는 문자열 배열을 사용합니다. localStorage에는 문자열을 저장하므로 JSON.stringify(tasks)로 배열을 JSON 문자열로 바꾸고, 읽을 때는 JSON.parse()로 다시 배열로 바꿉니다. 저장된 키가 없으면 getItem()은 null을 반환하므로 빈 배열로 시작합니다. JSON 문법이 잘못됐거나 결과가 문자열 배열이 아니면 안내 메시지를 표시하고 빈 목록으로 시작합니다.

아래 전체 코드를 index.html로 저장해 실행하세요. 페이지의 스크립트가 목록 요소를 찾을 수 있도록 <script>를 화면 요소 뒤에 두었습니다. 시작 시 loadTasks()로 복원한 다음 renderTasks()로 첫 화면을 그립니다. 추가와 삭제 뒤에는 배열을 저장하고 다시 그립니다.

<!doctype html>
<html lang="ko">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>할 일 목록 저장하기</title>
</head>
<body>
  <main>
    <h1>할 일 목록</h1>
    <form id="task-form">
      <label for="task-input">할 일</label>
      <input id="task-input" autocomplete="off" required>
      <button type="submit">추가</button>
    </form>
    <p id="message" role="status" aria-live="polite"></p>
    <ul id="task-list"></ul>
  </main>
  <script>
    const STORAGE_KEY = 'task-list-example-v1';
    const form = document.querySelector('#task-form');
    const input = document.querySelector('#task-input');
    const list = document.querySelector('#task-list');
    const message = document.querySelector('#message');

    function loadTasks() {
      let saved;
      try {
        saved = localStorage.getItem(STORAGE_KEY);
      } catch (error) {
        message.textContent = '저장소를 읽을 수 없어 빈 목록으로 시작합니다.';
        return [];
      }

      if (saved === null) return [];

      try {
        const parsed = JSON.parse(saved);
        if (!Array.isArray(parsed) || !parsed.every(item => typeof item === 'string')) {
          throw new Error('문자열 배열이 아닙니다.');
        }
        return parsed;
      } catch (error) {
        message.textContent = '저장된 목록을 읽을 수 없어 빈 목록으로 시작합니다. 항목을 변경하면 기존 저장값을 덮어씁니다.';
        return [];
      }
    }

    function saveTasks() {
      try {
        localStorage.setItem(STORAGE_KEY, JSON.stringify(tasks));
        message.textContent = '';
      } catch (error) {
        message.textContent = '저장하지 못했습니다. 현재 화면의 변경 사항은 새로고침 후 사라질 수 있습니다.';
      }
    }

    function renderTasks() {
      list.replaceChildren();
      tasks.forEach((task, index) => {
        const item = document.createElement('li');
        const label = document.createElement('span');
        const button = document.createElement('button');
        label.textContent = task;
        button.type = 'button';
        button.textContent = '삭제';
        button.setAttribute('aria-label', `${task} 삭제`);
        button.addEventListener('click', () => {
          tasks.splice(index, 1);
          saveTasks();
          renderTasks();
        });
        item.append(label, ' ', button);
        list.append(item);
      });
    }

    let tasks = loadTasks();
    renderTasks();

    form.addEventListener('submit', event => {
      event.preventDefault();
      const task = input.value.trim();
      if (!task) return;
      tasks.push(task);
      saveTasks();
      renderTasks();
      input.value = '';
      input.focus();
    });
  </script>
</body>
</html>

새로고침하면 사라지는 할 일 목록: localStorage에서 배열 복원하기 — 첫 예제의 실제 실행 결과

renderTasks()는 현재 배열만 화면에 반영합니다. 저장은 saveTasks()가 담당하며, 삭제 버튼은 해당 항목을 배열에서 제거한 뒤 저장하고 목록을 다시 그립니다. 입력한 글은 textContent로 넣기 때문에 HTML 태그로 해석되지 않습니다.

직접 확인하기

다음은 코드가 의도한 동작입니다. 이 글에서는 브라우저에서 실제 클릭과 새로고침을 실행해 확인하지 않았습니다.

  1. 할 일을 두 개 추가하고 새로고침합니다. 저장소를 사용할 수 있다면 두 항목이 다시 나타납니다.
  2. 한 항목을 삭제하고 새로고침합니다. 남은 항목만 다시 나타납니다.
  3. 빈 저장소에서는 오류 없이 빈 목록으로 시작합니다. 손상된 JSON이나 문자열 배열이 아닌 값이 저장돼 있으면 안내를 표시하고 빈 목록으로 시작합니다. 이때 원래 값은 바로 지우지 않지만, 새 항목을 추가하는 등 저장에 성공하면 새 배열로 덮어씁니다.

브라우저 개발자 도구의 저장소 화면에서 task-list-example-v1 키를 살펴보면 저장된 JSON 문자열을 확인할 수 있습니다. 테스트를 마친 뒤에는 그 키만 삭제할 수 있습니다.

localStorage는 출처별로 구분되므로 주소의 프로토콜, 호스트 또는 포트가 달라지면 다른 저장소를 볼 수 있습니다. 브라우저 설정이나 실행 환경에 따라 접근 또는 저장이 제한될 수도 있습니다. 파일을 직접 여는 file: 주소의 저장 동작은 브라우저마다 다를 수 있으므로, 복원이 불안정하면 같은 로컬 웹 서버 주소에서 다시 확인하세요. 저장에 실패한 경우에는 현재 화면을 계속 사용할 수 있지만 변경 내용이 유지된다고 보장할 수 없습니다.

참고: MDN — Storage.setItem(), MDN — localStorage, MDN — JSON 파싱 오류.

함께 찾아볼 코드 사전

CHECK THE SOURCE

참고한 공식 문서

기능 설명은 위 문서를 참고했으며, 예제의 입력·결과와 한계는 본문에 따로 기록했습니다.

한 줄씩 이해하고, 차곡차곡 기록합니다.이 글의 오류 제보하기 ↗