
localStorage, sessionStorage, cookie 차이와 실전 전략
웹 애플리케이션에서는 사용자 상태나 임시 데이터, 설정값 등을 클라이언트 측에 저장해야 할 일이 자주 발생합니다. 예를 들어, “테마 설정, 로그인 정보, 장바구니 상태 등은 사용자가 새로고침을 하거나, 브라우저를 닫았다가 다시 열었을 때도 유지되면 좋겠습니다.”라는 요구를 충족시키기 위해 브라우저는 몇 가지 저장소 API를 제공합니다. 대표적으로 localStorage, sessionStorage, 그리고 cookie가 있습니다.
이 세 가지 브라우저 저장소는 저장 위치도 다르고, 저장 방식, 전송 방식, 용량 제한, 보안 측면에서도 각각 큰 차이가 있습니다. 단순히 데이터를 저장할 수 있다는 이유로 아무 저장소나 사용하는 것은 종종 보안 문제나 유지보수의 어려움을 낳기도 합니다. 이번 글에서는 각 브라우저 저장소의 차이점과 사용 목적, 주의할 점, 그리고 실무에서의 안전한 사용 전략까지 알아보겠습니다.
웹 브라우저는 클라이언트 측 데이터를 저장할 수 있는 여러 메커니즘을 제공합니다. 그중 가장 흔히 사용되는 것은 localStorage, sessionStorage, 그리고 cookie입니다. 이들은 각각의 특성과 목적에 따라 적절히 선택하여 사용해야 합니다.
localStorage는 도메인 단위로 데이터를 영구적으로 저장할 수 있는 API입니다. 사용자가 브라우저를 닫고 다시 열어도 데이터는 유지되며, 페이지 새로고침이나 탭 변경에도 영향을 받지 않습니다. 따라서 테마, 언어 설정, 비로그인 상태의 장바구니 등 장기적으로 유지돼야 하는 데이터를 저장하는 데 적합합니다.
// 다크 모드 상태 저장
localStorage.setItem('theme', 'dark');
// 저장된 값 불러오기
const theme = localStorage.getItem('theme');
// 삭제
localStorage.removeItem('theme');
localStorage의 데이터는 문자(string)로 저장되기 때문에, 객체나 배열을 저장하려면 반드시 JSON.stringify와 JSON.parse를 사용해야 합니다. 예외적으로, 숫자나 불린 값도 자동으로 문자열로 변환됩니다.
또한 localStorage는 브라우저마다 약 5MB 정도의 용량 제한이 있습니다. 이는 쿠키(4KB 내외)에 비하면 매우 넉넉한 편입니다. 하지만 localStorage는 서버와 자동으로 연동되지 않으며, XSS 공격에 취약하기 때문에 민감한 정보를 저장하는 것은 금물입니다.
sessionStorage는 브라우저 탭 단위로 데이터를 저장합니다. 같은 도메인이라 하더라도 탭을 새로 열면 별도의 sessionStorage 공간이 생성되며, 기존 탭의 sessionStorage와는 공유되지 않습니다. 탭을 닫는 즉시 데이터가 사라지기 때문에 임시 데이터나 사용자 인터페이스 상태를 저장하는 데 적합합니다.
// 팝업 노출 여부 저장
sessionStorage.setItem('popupShown', 'true');
// 불러오기
const shown = sessionStorage.getItem('popupShown');
실무에서는 폼 입력 도중 탭을 닫는 것을 방지하거나, 안내 메시지를 한 번만 보여주는 데 자주 사용됩니다. 다만, 쿠키와 달리 서버로 자동 전송되지 않으며 localStorage처럼 5MB 정도의 용량 제한이 존재합니다.
cookie는 브라우저 저장소 중 유일하게 클라이언트와 서버 간의 요청에 자동으로 포함되는 방식입니다. 즉, 쿠키는 HTTP 요청 시마다 서버로 자동 전송되기 때문에 인증 정보나 세션 식별자 등을 저장하는 데 매우 유용합니다.
// 쿠키 설정 (자바스크립트)
document.cookie = 'token=abc123; path=/; max-age=3600; Secure; SameSite=Strict';
쿠키는 크기가 약 4KB 내외로 제한되며, 도메인과 경로(path)에 따라 전송 범위를 세밀하게 조절할 수 있습니다. 예를 들어, ‘path=/admin’으로 설정된 쿠키는 /admin 하위 경로에서만 접근 가능하게 할 수 있습니다. 또한 Secure 플래그를 사용하면 HTTPS에서만 전송되며, HttpOnly를 설정하면 자바스크립트로 접근이 불가능해 보안이 강화됩니다.
HttpOnly 쿠키는 XSS 공격에 강하지만, 클라이언트 측에서 직접 토큰 값을 읽을 수 없기 때문에 SPA 구조에서는 불편함이 생길 수 있습니다. 이런 경우 localStorage를 사용하는 대신, Refresh Token만 HttpOnly 쿠키에 저장하고 Access Token은 메모리에서 관리하는 방식을 혼합하여 사용하는 전략도 있습니다.
자바스크립트 프로젝트에서 저장소를 선택할 때는 단순한 기능만 볼 것이 아니라, 동작 방식, 보안, 생명주기, 전송 여부까지 고려해야 합니다.
많은 개발자들이 처음에는 localStorage에 JWT 토큰을 저장하는 실수를 합니다. 하지만 localStorage는 XSS 공격에 매우 취약합니다. 공격자가 스크립트를 삽입하여 localStorage 값을 탈취하면 사용자의 인증 정보가 노출될 수 있습니다.
반면, 쿠키는 HttpOnly 설정을 통해 자바스크립트로 접근할 수 없게 만들 수 있습니다. 이는 XSS로부터는 안전하지만, 쿠키는 모든 요청에 자동으로 포함되기 때문에 CSRF(Cross-Site Request Forgery) 공격에는 더 취약해질 수 있습니다. 이를 방지하기 위해 SameSite=Lax 또는 Strict 옵션을 반드시 설정해야 합니다.
실무에서는 Refresh Token은 HttpOnly 쿠키에 저장하고, Access Token은 메모리나 sessionStorage에 보관하는 방식이 많이 사용됩니다. 인증 요청을 보낼 때는 이 Access Token을 Authorization 헤더에 직접 실어 보내는 구조입니다.
fetch('/api/user', {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
이처럼 각 저장소의 장단점을 조합한 하이브리드 전략을 활용하면, 보안성과 사용자 경험을 모두 만족시키는 인증 시스템을 구축할 수 있습니다.
사용자의 인터페이스 상태나 설정값은 localStorage가 적합합니다. 브라우저를 닫았다 다시 열어도 유지되기 때문에, 테마나 언어 설정, 장바구니 목록 등을 저장하기 좋습니다. 반면, 일시적인 사용자 상태나 폼 입력 도중의 데이터는 sessiongStorage가 알맞습니다. 탭이 닫히면 삭제되므로, 탭 간의 독립성을 보장할 수 있습니다. 예를 들어, 설문조사를 진행하다가 새 탭을 열면 새로운 세션으로 취급할 수 있죠.
서버와 통신이 필요한 세션 상태 유지는 쿠키로 처리하는 것이 가장 적절합니다. 서버에서는 쿠키의 세션 ID를 바탕으로 사용자의 상태를 관리하게 됩니다.
브라우저 저장소를 사용할 때는 몇 가지 주의해야 할 기술적인 디테일이 있습니다. 단순히 API를 쓰는 것보다, 이 저장소들이 가진 특성과 한계점을 이해하고 적절히 보완하는 것이 중요합니다.
localStorage와 sessionStorage는 문자열만 저장할 수 있기 때문에, 객체나 배열은 반드시 JSON으로 변환하여 저장하고, 다시 사용할 때는 파싱해야 합니다.
const cart = [{ id: 1, name: '햄버거' }];
localStorage.setItem('cart', JSON.stringify(cart));
const storedCart = JSON.parse(localStorage.getItem('cart'));
이때 JSON.parse 과정에서 예외가 발생할 수 있기 때문에 try-catch로 감싸는 것이 안전합니다.
localStorage나 sessionStorage의 저장 용량이 초과되면 Quota Exceeded Error가 발생합니다. 사용자가 지나치게 많은 데이터를 저장하거나, 의도하지 않은 루프로 인해 저장이 반복될 경우 발생할 수 있습니다. 이때는 예외 처리를 통해 사용자에게 경고하거나 대체 동작을 유도해야 합니다.
localStorage와 sessionStorage는 저장된 데이터에 자동으로 만료 시간이 적용되지 않습니다. 만료 처리를 하고 싶다면 타임스탬프를 함께 저장하고, 데이터를 사용할 때 유효한지 검사해야 합니다.
const now = Date.now();
localStorage.setItem('token', JSON.stringify({ value: 'abc', expires: now + 3600 * 1000 }));
const raw = JSON.parse(localStorage.getItem('token'));
if (Date.now() > raw.expires) {
localStorage.removeItem('token');
}
4) 스토리지 동기화 이벤트 처리
localStorage는 탭 간 동기화를 지원합니다. 다른 탭에서 저장소가 변경되면 storage 이벤트가 발생하므로, 이를 활용하면 실시간 동기화가 가능합니다.
window.addEventListener('storage', (e) => {
if (e.key === 'theme') {
document.body.className = e.newValue;
}
});
반면, sessionStorage와 쿠키는 이런 실시간 동기화 이벤트를 지원하지 않기 때문에 동기화가 필요하다면 BroadcastChannel API 같은 별도 통신 수단을 고려해야 합니다.
브라우저 저장소는 웹 개발에 있어 매우 강력한 도구입니다. 그러나 각각의 저장소는 쓰임새와 보안 특성이 전혀 다르기 때문에, 단순히 데이터를 저장할 수 있다는 이유로 무분별하게 사용하는 것은 피해야 합니다. 용량 제한, 만료 정책, 보안 취약점, 접근 범위 등을 정확히 이해하고 사용하는 것이 무엇보다 중요합니다.
localStorage는 장기 상태를 저장하는 데 유용하지만, 민감 정보는 저장하지 말아야 하며, sessionStorage는 탭 단위의 임시 저장소로 활용 가치가 높습니다. 쿠키는 서버와 연동된 인증에 적합하지만, 보안 옵션을 반드시 설정해야 안전합니다. 결국 가장 중요한 것은 각 저장소의 특성과 한계를 이해하고, 그에 맞는 전략을 수립하는 것입니다. 저장소 선택 하나가 보안과 사용자 경험을 좌우할 수 있다는 사실을 꼭 기억해 두시면 좋겠습니다.
©️요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.