로컬 스토리지를 활용한 투두리스트(To-Do List) 실습을 시작해 보겠습니다.
이번 실습의 핵심은 "새로고침을 해도 내가 추가하거나 삭제한 할 일 목록이 그대로 유지되도록 만드는 것"입니다.
1. 프로젝트 구조 설계
HTML로 화면의 뼈대를 만들고, CSS로 간단한 스타일을 입힌 뒤, 자바스크립트로 로컬 스토리지 연동 로직을 구현하겠습니다.
이 프로젝트는 다음과 같은 데이터 흐름을 가집니다.
[입력창] ──(추가)──> [할 일 배열] ──(JSON.stringify)──> [로컬스토리지 저장]
│
└──(화면 렌더링)──> [<ul> 태그 내부에 표시]
2. 전체 실습 코드
하나의 HTML 파일에 모든 코드를 담았습니다. todolist.html 파일을 만들어 아래 코드를 붙여넣고 브라우저로 실행해 보세요.
HTML
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>로컬스토리지 투두리스트</title>
<style>
body {
font-family: 'Malgun Gothic', sans-serif;
background-color: #f5f6fa;
padding: 30px;
display: flex;
justify-content: center;
}
.todo-container {
background-color: white;
padding: 25px;
border-radius: 10px;
box-shadow: 0 4px 10px rgba(0,0,0,0.1);
width: 350px;
}
.input-box {
display: flex;
gap: 10px;
margin-bottom: 20px;
}
input {
flex: 1;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
}
button {
padding: 8px 12px;
background-color: #3498db;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover { background-color: #2980b9; }
ul { list-style: none; padding: 0; margin: 0; }
li {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
border-bottom: 1px solid #eee;
}
.delete-btn {
background-color: #e74c3c;
padding: 4px 8px;
font-size: 12px;
}
.delete-btn:hover { background-color: #c0392b; }
</style>
</head>
<body>
<div class="todo-container">
<h2>My To-Do List</h2>
<div class="input-box">
<input type="text" id="todo-input" placeholder="할 일을 입력하세요...">
<button id="add-btn">추가</button>
</div>
<ul id="todo-list"></ul>
</div>
<script>
// DOM 요소 선택
const todoInput = document.getElementById('todo-input');
const addBtn = document.getElementById('add-btn');
const todoList = document.getElementById('todo-list');
// 1. 로컬 스토리지에서 기존 데이터 불러오기 (없으면 빈 배열)
let todos = JSON.parse(localStorage.getItem('todos')) || [];
// 2. 화면에 할 일 목록을 그려주는 함수
function renderTodos() {
todoList.innerHTML = ''; // 기존 목록 초기화
todos.forEach((todo, index) => {
const li = document.createElement('li');
li.innerHTML = `
<span>${todo}</span>
<button class="delete-btn" onclick="deleteTodo(${index})">삭제</button>
`;
todoList.appendChild(li);
});
}
// 3. 새로운 할 일을 추가하는 함수
function addTodo() {
const text = todoInput.value.trim();
if (text === '') return; // 빈 값 입력 방지
todos.push(text); // 배열에 추가
saveTodos(); // 로컬 스토리지에 저장
renderTodos(); // 화면 갱신
todoInput.value = ''; // 입력창 비우기
}
// 4. 할 일을 삭제하는 함수
window.deleteTodo = function(index) {
todos.splice(index, 1); // 배열에서 해당 인덱스 요소 제거
saveTodos(); // 로컬 스토리지에 저장
renderTodos(); // 화면 갱신
};
// 5. 현재 배열 상태를 로컬 스토리지에 저장하는 함수 (핵심)
function saveTodos() {
localStorage.setItem('todos', JSON.stringify(todos));
}
// 이벤트 리스너 연결
addBtn.addEventListener('click', addTodo);
todoInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') addTodo();
});
// 앱 시작 시 최초 1회 화면 그리기
renderTodos();
</script>
</body>
</html>
3. 핵심 로직 해설
- 초기 데이터 로드 (|| []): 페이지를 처음 열었을 때는 로컬 스토리지에 아무것도 없습니다. localStorage.getItem('todos')가 null을 반환하더라도 에러가 나지 않고 빈 배열([])로 시작하도록 논리 연산자(||)를 사용했습니다.
- 배열 저장 시 JSON.stringify(): todos는 자바스크립트 배열 객체입니다. 이를 로컬 스토리지에 통째로 저장하기 위해 JSON.stringify(todos)를 거쳐 문자열 형태로 직렬화하여 저장했습니다.
- 데이터 복원 시 JSON.parse(): 반대로 로컬 스토리지에서 데이터를 꺼내올 때는 문자열 상태이므로, 자바스크립트 배열로 다시 사용하기 위해 JSON.parse()를 적용했습니다.
브라우저에서 할 일을 몇 개 등록해 보고, F5 키를 눌러 새로고침을 하거나 창을 닫았다가 다시 열어보세요. 내가 작성한 목록이 마법처럼 그대로 남아있는 것을 확인할 수 있습니다. 개발자 도구(F12)의 Application -> Local Storage 탭에서 데이터가 실시간으로 변하는 것을 눈으로 확인하면 더 재미있을 것입니다.
로컬 스토리지 실습을 멋지게 성공하셨습니다!

'JavaScript' 카테고리의 다른 글
| JavaScript BOM (0) | 2026.06.02 |
|---|---|
| JavaScript Built in object (0) | 2026.06.02 |
| JavaScript screen object method (0) | 2026.06.01 |
| JavaScript history object method (0) | 2026.06.01 |
| JavaScript location object method (0) | 2026.06.01 |