localStorage 실습 앱 완전 정리
여행/먹거리 선택 저장, storage 이벤트 출력, 날짜 기반 일기 저장·보기를 localStorage 관점에서 정리합니다.
<script>
function store(key, obj) {
if (!window.localStorage) {
alert("지원하지 않습니다.");
return;
}
let value = obj.options[obj.selectedIndex].value;
localStorage.setItem(key, value);
}
window.addEventListener("storage", storageEventListener, false);
window.onload = show;
function storageEventListener(e) {
show();
}
function show() {
let obj = document.getElementById("msg");
obj.innerHTML = "";
for (let i = 0; i < localStorage.length; i++) {
let key = localStorage.key(i);
let val = localStorage.getItem(key);
obj.innerHTML += key + "=" + val + "<br>";
}
}
function printDate() {
let today = new Date();
date.innerHTML = today.getFullYear() + "." + (today.getMonth()+1) + "." + today.getDate();
}
</script>
96번 폴더는 localStorage를 사용한 두 가지 앱을 다룹니다. 첫 번째는 여행 도시와 먹거리를 선택해 저장하고 다른 페이지에서 보여 주는 앱, 두 번째는 오늘 날짜를 key로 일기를 저장하고 목록으로 출력하는 앱입니다.
- 여행 앱은 select onchange에서 store('city', this) 또는 store('food', this)를 호출합니다.
- 보기 페이지는 storage 이벤트와 window.onload에서 show 함수를 실행합니다.
- 일기 앱은 오늘 날짜를 span#date에 출력하고 메모를 localStorage에 저장합니다.
- 일기 보기 페이지는 localStorage 전체를 table로 출력합니다.
여행 앱의 store(key, obj)는 선택된 select 객체를 obj로 받고, obj.options[obj.selectedIndex].value로 현재 선택 값을 읽습니다. key는 city 또는 food처럼 호출할 때 정해집니다.
| 호출 | key | 저장 value |
|---|---|---|
| store('city', this) | city | 파리, 뉴욕, 런던 |
| store('food', this) | food | 햄버거, 에스프레소 커피, 치즈 케이크 |
| localStorage.setItem | 첫 번째 인수 | 두 번째 인수 |
| show() | key(i) | getItem(key) |
select의 onchange는 선택 항목이 바뀔 때 실행됩니다. 사용자가 도시를 선택하는 순간 localStorage에 저장되므로 별도 저장 버튼이 필요 없습니다.
- 사용자가 도시 또는 음식을 클릭합니다.
- select의 selectedIndex가 바뀝니다.
- onchange 속성의 store 함수가 호출됩니다.
- 선택된 option의 value가 localStorage에 저장됩니다.
show 함수는 localStorage의 모든 key/value를 읽어 msg 영역에 출력합니다. key 이름을 제한하지 않고 전체 저장소를 순회하므로, 같은 출처의 다른 예제 데이터도 함께 보일 수 있습니다.
for (let i = 0; i < localStorage.length; i++) {
let key = localStorage.key(i);
let val = localStorage.getItem(key);
obj.innerHTML += key + "=" + val + "<br>";
}
storage 이벤트는 같은 출처의 다른 창이나 탭에서 localStorage가 변경될 때 발생합니다. 여행 선택 페이지와 보기 페이지를 동시에 열어 두면 선택 변경을 보기 페이지가 감지해 show를 다시 실행할 수 있습니다.
| 상황 | 이벤트 | 처리 |
|---|---|---|
| 같은 페이지에서 setItem | 현재 문서에는 보통 발생하지 않음 | 필요하면 show를 직접 호출 |
| 다른 탭에서 setItem | 보기 페이지에 발생 | storageEventListener 호출 |
| 값 삭제 | 변경 이벤트 발생 가능 | show로 다시 렌더링 |
| 지원 안 됨 | 동작 불가 | alert 후 return |
일기 쓰기 페이지는 window.onload에서 printDate를 실행해 오늘 날짜를 span#date에 출력합니다. 저장할 때 이 날짜 문자열을 key로 사용합니다.
let today = new Date();
let str = today.getFullYear() + "." +
(today.getMonth() + 1) + "." +
today.getDate();
span.innerHTML = str;
일기 저장 함수는 date span의 innerHTML과 textarea의 value를 읽습니다. 날짜가 key, 일기 내용이 value가 됩니다. 같은 날짜에 다시 저장하면 이전 일기는 덮어써집니다.
- date는 화면에 표시된 오늘 날짜입니다.
- memo는 textarea에 입력된 일기 내용입니다.
- localStorage.setItem(date, memo)로 저장합니다.
- 같은 날짜 key는 하나만 존재하므로 최신 내용으로 바뀝니다.
일기 보기 페이지는 포스트잇 예제와 비슷하게 localStorage 전체를 table로 출력합니다. 각 행에는 번호, key, value가 들어갑니다.
| 열 | 출력 값 | 의미 |
|---|---|---|
| 번호 | i + 1 | 출력 순서 |
| key | localStorage.key(i) | 날짜 또는 다른 저장 key |
| value | localStorage.getItem(key) | 일기 내용 |
| table | document.write | HTML 문자열 출력 |
localStorage는 같은 출처의 모든 데이터가 섞입니다. 여행 앱의 city, food와 일기 앱의 날짜 key가 같은 저장소에 들어가므로 전체 순회 페이지에는 두 앱 데이터가 함께 나올 수 있습니다.
원문은 innerHTML과 document.write를 사용해 사용자 입력값을 화면에 출력합니다. 학습용으로 간단하지만, 실제 서비스에서는 HTML 삽입 위험을 줄이기 위해 textContent와 createElement를 사용하는 것이 안전합니다.
- innerHTML은 문자열을 HTML로 해석합니다.
- document.write는 문서 로딩 이후 호출 방식에 주의해야 합니다.
- textarea 입력값은 사용자가 자유롭게 작성할 수 있습니다.
- 안전한 출력에는 textContent가 적합합니다.
여행 앱은 div를 inline-block으로 배치해 도시와 음식 선택 박스를 나란히 보여 줍니다. 일기 앱은 textarea의 글자 크기를 키우고, 보기 페이지는 table 배경과 border로 목록을 구분합니다.
| CSS 대상 | 역할 |
|---|---|
| select | 왼쪽 여백으로 목록 위치 조정 |
| div | 선택 영역 박스 표시 |
| textarea | 일기 입력 글자 크기 조정 |
| table | 저장 목록 배경색 지정 |
| 개선 | 목표 |
|---|---|
| key 접두어 | travel:city, diary:date처럼 앱 데이터를 구분합니다. |
| 삭제 기능 | removeItem으로 특정 일기를 지웁니다. |
| 날짜 선택 | 오늘이 아닌 날짜에도 일기를 쓰게 합니다. |
| 자동 새로고침 | 현재 페이지에서도 저장 후 show를 직접 호출합니다. |
| DOM 렌더링 | document.write를 createElement로 대체합니다. |
- localStorage 지원 여부를 먼저 확인합니다.
- select의 value가 실제 저장하려는 문자열인지 확인합니다.
- storage 이벤트는 다른 탭 변경 감지용임을 이해합니다.
- 일기 날짜 key가 같은 날 덮어쓰기 되는지 확인합니다.
- localStorage 전체 순회 시 다른 예제 데이터가 섞일 수 있음을 확인합니다.
- 사용자 입력을 HTML로 출력할 때 보안 위험을 고려합니다.
| 실수 | 문제 | 해결 |
|---|---|---|
| storage 이벤트를 현재 페이지 저장 직후 기대 | 같은 문서에서는 기대대로 발생하지 않을 수 있습니다. | 저장 함수 안에서 show를 직접 호출하거나 다른 탭으로 테스트합니다. |
| 전체 localStorage를 앱 전용 저장소로 착각 | 다른 예제의 key/value도 함께 출력됩니다. | key 접두어로 앱 데이터를 구분합니다. |
| 같은 날짜 일기 덮어쓰기 미인지 | 이전 내용이 사라진 것처럼 보입니다. | 날짜+시간 key나 덮어쓰기 확인을 추가합니다. |
| innerHTML에 사용자 입력 그대로 출력 | HTML 삽입 위험이 있습니다. | textContent와 DOM API를 사용합니다. |
| selectedIndex 없이 value를 잘못 읽음 | 원하는 option 값이 저장되지 않습니다. | obj.options[obj.selectedIndex].value를 확인합니다. |
핵심 한 줄 요약
Tags
'php' 카테고리의 다른 글
| 부트스트랩 폼 완전 정리 (0) | 2026.07.17 |
|---|---|
| 부트스트랩 버튼 · 타이포그래피 완전 정리 (0) | 2026.07.17 |
| 웹 스토리지 실습 완전 정리 (0) | 2026.07.17 |
| 오디오 플레이리스트 완전 정리 (0) | 2026.07.17 |
| Canvas 그림판 완전 정리 (0) | 2026.07.16 |
왕진 블로그

댓글