로컬 스토리지와 세션 스토리지
지난 장에서는 웹 애플리케이션이 Fetch API
를 통해 서버와 비동기적으로 통신하여 데이터를 주고받는 방법을 학습했습니다. 서버로부터 데이터를 가져와 웹 페이지에 동적으로 표시하는 것은 매우 중요하지만, 때로는 서버를 거치지 않고 클라이언트(브라우저) 자체에 데이터를 저장하고 관리해야 할 필요가 있습니다. 예를 들어, 사용자의 로그인 상태 유지, 설정 정보 저장, 장바구니 정보 임시 저장, 오프라인 지원 등을 위해서 말이죠.
이러한 클라이언트 측 데이터 저장을 위해 과거에는 주로 쿠키(Cookie)가 사용되었지만, 쿠키는 용량 제한(약 4KB), 모든 HTTP 요청에 자동 전송되어 발생하는 네트워크 오버헤드, 복잡한 API 등의 단점이 있었습니다. ES5부터 도입된 웹 스토리지(Web Storage) API는 이러한 쿠키의 단점을 보완하며, 더 큰 용량과 간편한 API를 제공하여 클라이언트 측 데이터 저장의 표준이 되었습니다.
웹 스토리지 API는 크게 두 가지 유형을 제공합니다: 로컬 스토리지(Local Storage) 와 세션 스토리지(Session Storage).
이번 장에서는 이 두 가지 스토리지의 특징, 사용법, 그리고 각각의 적절한 활용 시나리오를 깊이 있게 알아보겠습니다.
웹 스토리지 (Web Storage) 개요
웹 스토리지는 클라이언트 측에서 key-value
형태로 데이터를 저장할 수 있도록 해주는 웹 API입니다. 동일 출원(Same Origin) 정책을 따르며, 각 출원(도메인, 프로토콜, 포트)마다 별도의 저장 공간을 가집니다. 즉, example.com
에서 저장한 데이터는 another.com
에서 접근할 수 없습니다.
두 가지 주요 웹 스토리지 객체는 전역 Window
객체의 프로퍼티로 제공됩니다.
window.localStorage
window.sessionStorage
이 두 객체는 동일한 메서드와 프로퍼티를 제공하지만, 데이터의 지속성(persistence)
에서 차이가 있습니다.
로컬 스토리지 (Local Storage)
로컬 스토리지는 브라우저를 닫았다가 다시 열어도 데이터가 유지되는 영구적인 저장소입니다. 사용자가 명시적으로 데이터를 삭제하거나, 브라우저 캐시를 지우지 않는 한 데이터가 지속적으로 보존됩니다.
- 지속성: 영구적 (브라우저 종료 후에도 유지)
- 만료 기간: 없음 (수동 삭제 필요)
- 용량: 출원당 약 5MB ~ 10MB (브라우저마다 다름)
- 접근성: 동일 출원의 모든 탭/창에서 접근 가능
- 데이터 형식: 문자열(
string
)만 저장 가능
로컬 스토리지 사용법
localStorage
객체는 setItem()
, getItem()
, removeItem()
, clear()
, key()
등의 메서드를 제공합니다.
데이터 저장: localStorage.setItem(key, value)
key
: 데이터를 식별할 키 (문자열)value
: 저장할 값 (문자열)value
는 항상 문자열로 변환되어 저장됩니다. 객체나 배열을 저장하려면JSON.stringify()
를 사용하여 문자열로 변환해야 합니다.
// 문자열 저장
localStorage.setItem('username', 'Alice');
localStorage.setItem('theme', 'dark');
// 객체 저장 (JSON.stringify 사용)
const userSettings = {
notifications: true,
language: 'ko'
};
localStorage.setItem('settings', JSON.stringify(userSettings));
console.log("로컬 스토리지에 데이터 저장됨.");
데이터 조회: localStorage.getItem(key)
key
: 조회할 데이터의 키- 저장된 문자열 값을 반환합니다. 값이 없으면
null
을 반환합니다. - 저장했던 객체나 배열은
JSON.parse()
를 사용하여 다시 객체나 배열로 변환해야 합니다.
const storedUsername = localStorage.getItem('username');
console.log("저장된 사용자 이름:", storedUsername); // 결과: Alice
const storedTheme = localStorage.getItem('theme');
console.log("저장된 테마:", storedTheme); // 결과: dark
// 객체 조회 (JSON.parse 사용)
const storedSettings = localStorage.getItem('settings');
if (storedSettings) {
const parsedSettings = JSON.parse(storedSettings);
console.log("저장된 설정:", parsedSettings); // 결과: {notifications: true, language: 'ko'}
}
데이터 삭제: localStorage.removeItem(key)
key
: 삭제할 데이터의 키
localStorage.removeItem('theme');
console.log("테마 데이터 삭제됨.");
console.log("남은 사용자 이름:", localStorage.getItem('username')); // 결과: Alice
console.log("삭제된 테마:", localStorage.getItem('theme')); // 결과: null
모든 데이터 삭제: localStorage.clear()
- 해당 출원에 저장된 모든 로컬 스토리지 데이터를 삭제합니다.
localStorage.clear();
console.log("모든 로컬 스토리지 데이터 삭제됨.");
console.log("사용자 이름:", localStorage.getItem('username')); // 결과: null
키 순회: localStorage.key(index)
또는 for...in
localStorage.length
로 저장된 항목의 개수를 알 수 있습니다.
localStorage.setItem('fruit', 'apple');
localStorage.setItem('drink', 'water');
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
const value = localStorage.getItem(key);
console.log(`${key}: ${value}`);
}
/*
결과 예시:
fruit: apple
drink: water
*/
// 또는 for...in 루프 (비권장: 프로토타입 체인의 속성도 포함될 수 있음)
// for (let key in localStorage) {
// if (localStorage.hasOwnProperty(key)) {
// console.log(`${key}: ${localStorage.getItem(key)}`);
// }
// }
로컬 스토리지 활용 시나리오
- 사용자 설정 저장: 테마(다크 모드/라이트 모드), 언어 설정, 알림 설정 등
- 로그인 정보(JWT 토큰 등): 로그인 상태를 유지하기 위한 토큰 저장
- 장바구니 정보(오프라인 유지): 사용자가 브라우저를 닫아도 장바구니 내용 유지
- 캐싱 데이터: 자주 사용되는 데이터를 클라이언트에 저장하여 서버 요청 감소 (API 응답 캐싱)
세션 스토리지 (Session Storage)
세션 스토리지는 로컬 스토리지와 동일한 API를 제공하지만, 데이터가 현재 브라우저 세션 동안만 유지됩니다. 즉, 사용자가 탭이나 브라우저 창을 닫으면 해당 세션 스토리지의 데이터는 자동으로 삭제됩니다.
- 지속성: 세션 동안만 유지 (탭/창 닫으면 삭제)
- 만료 기간: 세션 종료 시 (만료 기간 설정 불가)
- 용량: 출원당 약 5MB ~ 10MB (브라우저마다 다름)
- 접근성: 동일한 탭/창 내에서만 접근 가능 (다른 탭/창에서는 접근 불가, 새로고침은 유지)
- 데이터 형식: 문자열(
string
)만 저장 가능
세션 스토리지 사용법
로컬 스토리지와 동일한 메서드를 사용합니다. localStorage
대신 sessionStorage
객체를 사용하면 됩니다.
// 데이터 저장
sessionStorage.setItem('tempMessage', '이 메시지는 현재 세션 동안만 유지됩니다.');
sessionStorage.setItem('lastVisitedPage', '/products/detail/123');
// 데이터 조회
const message = sessionStorage.getItem('tempMessage');
console.log("세션 저장 메시지:", message);
// 데이터 삭제
sessionStorage.removeItem('lastVisitedPage');
sessionStorage.clear(); // 현재 세션의 모든 데이터 삭제
세션 스토리지 활용 시나리오
- 단일 세션 내 임시 데이터: 폼 입력값 임시 저장 (페이지 이동 후 다시 돌아왔을 때), 일회성 알림 메시지
- 단계별 마법사(Wizard) 형식의 데이터: 여러 단계로 이루어진 회원가입 폼에서 각 단계의 입력 데이터를 다음 단계로 넘기기 전까지 임시 저장
- 세션별 사용자 액션 추적: 특정 세션에서만 필요한 사용자 행동 로그
쿠키 (Cookie)와 웹 스토리지 비교 (간략)
특징 | 쿠키 (Cookie) | 로컬 스토리지 (Local Storage) | 세션 스토리지 (Session Storage) |
---|---|---|---|
지속성 | 만료일 지정 가능 (영구적/세션) | 영구적 (브라우저 종료 후에도 유지) | 세션 동안만 유지 (탭/창 닫으면 삭제) |
용량 | 약 4KB | 5~10MB | 5~10MB |
서버 전송 | 모든 HTTP 요청 시 자동으로 서버로 전송 | 클라이언트에서만 접근 가능 (서버로 자동 전송 안됨) | 클라이언트에서만 접근 가능 (서버로 자동 전송 안됨) |
접근성 | 동일 출원의 모든 탭/창, 서버에서 접근 가능 | 동일 출원의 모든 탭/창에서 접근 가능 | 동일 출원의 동일 탭/창에서만 접근 가능 |
API | 복잡 (document.cookie 문자열 파싱) | 간단 (setItem, getItem 등) | 간단 (setItem, getItem 등) |
주요 용도 | 사용자 인증 (세션 ID), 추적 | 사용자 설정, 캐시, 로그인 토큰, 오프라인 데이터 | 폼 데이터, 임시 상태, 일회성 메시지 |
결론: 대부분의 클라이언트 측 데이터 저장에는 웹 스토리지를 사용하는 것이 쿠키보다 유리합니다. 쿠키는 주로 서버에서 읽고 써야 하는 사용자 인증(세션 ID)이나 트래킹 정보 등에 제한적으로 사용됩니다.
마무리하며
이번 장에서는 웹 애플리케이션의 클라이언트 측에서 데이터를 효율적으로 저장하고 관리할 수 있는 로컬 스토리지(Local Storage) 와 세션 스토리지(Session Storage) 에 대해 심도 있게 학습했습니다.
여러분은 로컬 스토리지가 브라우저를 닫아도 데이터가 영구적으로 보존되는 특성과, 세션 스토리지가 현재 브라우저 세션 동안만 데이터가 유지되는 특성을 명확히 이해했습니다. 또한, 두 스토리지 모두 setItem()
, getItem()
, removeItem()
, clear()
등의 동일하고 간결한 API를 제공하며, 문자열 형태의 데이터만 저장할 수 있다는 중요한 제약 사항도 확인했습니다. 객체나 배열을 저장하기 위해서는 JSON.stringify()
와 JSON.parse()
를 사용해야 한다는 점도 기억해야 합니다.
쿠키와 비교했을 때 웹 스토리지는 더 큰 용량과 간편한 API, 그리고 HTTP 요청에 불필요한 데이터를 전송하지 않는다는 장점으로 인해 현대 웹 개발에서 클라이언트 측 저장의 표준으로 자리 잡았습니다. 사용자 설정 저장, 장바구니 정보 유지, 임시 폼 데이터 관리 등 다양한 시나리오에서 이 웹 스토리지 API들을 적절히 활용하여 사용자 경험을 향상시키고 애플리케이션의 성능을 최적화할 수 있을 것입니다. 다음 장에서는 DOM 조작과 이벤트 핸들링에 대해 자세히 다루겠습니다.