쿠키 vs 로컬 스토리지 vs 세션 스토리지 — 언제, 왜 써야 할까?
웹 개발을 하다 보면 브라우저 저장소를 자주 쓰게 됩니다.
쿠키 / 로컬 스토리지 / 세션 스토리지 는 다 브라우저가 제공하는 “클라이언트 저장소”지만, 각 저장소마다 가지고 있는 특징 / 용량 / 보안성이 달라서 목적에 맞게 올바르게 선택해야 합니다.
1️⃣ 로컬 스토리지 (localStorage)
특징:
데이터가 영구적으로 저장됩니다.
사용자가 직접 지우지 않는 이상, 컴퓨터를 껐다 켜도 그대로 남아있습니다.
용량: 도메인당 약 5MB 정도.
자바스크립트로 접근 가능 (
localStorage.getItem).
사용 예시:
다크 모드 여부, 사용자 언어 설정
최근 본 상품, 검색어 기록 등 캐시
새로고침/재접속 후에도 남아야 하는 상태
2️⃣ 세션 스토리지 (sessionStorage)
특징:
브라우저 탭 단위로 유지됩니다.
탭을 닫으면 저장된 정보는 사라집니다.
새로운 탭을 열 때 마다 모든 탭 각각에 새로운
sessionStorage공간이 생깁니다.용량은 localStorage와 비슷, 약 5MB 정도.
사용 예시:
다단계 회원가입 폼의 입력값 유지
페이지 이동 시 필요한 임시 데이터
뒤로 가기 했을 때 직전 상태 복원
⚠️ 각 스토리지들은 JS로 접근 가능해서 XSS 공격에 그대로 노출되기 때문에, 탈취됐을 때 문제가 생길만한 민감한 인증 토큰(JWT 등)을 넣는 건 권장되지 않습니다.
3️⃣ 쿠키 (Cookie)
쿠키는 대부분 서버에 의해 관리됩니다.
쿠키란 브라우저가 서버에서 내려받아 자동으로 요청에 포함시켜주는 작은 데이터 조각
브라우저는 서버로부터 Set-Cookie 헤더를 받으면 내부 저장소에 기록해두고,
이후 요청마다 자동으로 Cookie 헤더에 포함해 서버로 다시 전송합니다.
Set-Cookie: session=abc123; Path=/; HttpOnly; Secure; SameSite=Strict
보시다시피 쿠키에는 몇 가지 속성들을 가지고 있는데, 주요 속성들에 대해 하나하나 알아봅시다.
HttpOnly: 속성은 브라우저에게 쿠키를 클라이언트 코드에서 접근할 수 없게 하라는 명령입니다. 이 속성을 붙여주면 클라이언트 코드로 해당 쿠키에 접근이 불가능해지기 때문에 XSS에 대해 안전을 확보할 수 있습니다.Secure: 속성은 연결이 HTTPS인 경우에만 해당 쿠키를 사용하라는 명령입니다. 일반 HTTP 요청시 해당 속성을 가진 쿠키는 전달되지 않습니다.SameSite: 어떤 상황에서 쿠키를 자동으로 전송할지 제어 (CSRF 완화)
4️⃣ SameSite가 중요한 이유
웹 초창기 쿠키는 그냥 “자동 전송”만 있었습니다.
사용자가 로그인하면 서버가 세션 쿠키(예:
session=abc123)를 내려줍니다.브라우저는 이후 요청마다 이 쿠키를 자동으로 서버에 붙여 보내요 → 서버는 “아 이 사람 로그인한 그 사용자네” 하고 인식합니다.
그런데 문제는 외부 사이트 보낸 외부 요청에도 무조건 쿠키가 따라갔습니다.
그런데 이 특성이 CSRF 공격(다른 사이트에서 몰래 요청 보내서 내 쿠키 사용)이 핵심 취약점이었죠.
이를 막기 위해 도입된 게 SameSite 입니다. “외부 요청일 때는 쿠키를 제한하자” 라는 아이디어가 나오게 된 것이죠.
| 상황/옵션 | Strict | Lax | None |
| 같은 사이트 내 요청 | 쿠키 전송 ✅ | 쿠키 전송 ✅ | 쿠키 전송 ✅ |
| 외부 사이트에서 시작된 GET (링크 클릭, 주소창 입력 등) | 전송 ❌ | 전송 ✅ | 전송 ✅ |
| 외부에서 시작된 POST/PUT/DELETE/AJAX | 전송 ❌ | 전송 ❌ | 전송 ✅ |
CSRF와 SameSite의 관계
CSRF: 해커 사이트가 내 브라우저의 로그인 쿠키를 ‘몰래’ 이용해 타 사이트에 요청시키는 공격.
Strict: 외부에서 시작된 요청에는 쿠키를 절대 안 붙임 → CSRF 사실상 원천 차단.
Lax: 외부 GET은 허용하지만, 외부 POST 등은 쿠키 차단 → 대부분의 CSRF 시나리오 완화.
None: 제약 없음 → 반드시 CSRF 토큰 등 다른 방어가 필요.
👉 브라우저는 요청의 출발지(site)를 기준으로 같은 사이트인지 판단합니다.
내가
google.com에서shop.com링크를 클릭 → 외부 사이트에서 시작된 요청내가
shop.com내부에서 페이지 이동 → 같은 사이트 요청
5️⃣ 무엇을 선택할까?
B2C(쇼핑몰, 커뮤니티 등)
외부 유입(검색/SNS/광고) 많음
사용자는 링크 눌러 들어와도 로그인 유지되길 기대
추천:
SameSite=Lax+ CSRF 토큰 +HttpOnly+Secure- 이유: 외부 링크 GET에는 쿠키가 붙어 로그인 유지(UX), 외부 POST는 막혀 CSRF 완화
B2B(내부 시스템: PMS/ERP/CRM 등)
외부 유입 거의 없음, 보안 우선
추천:
SameSite=Strict+HttpOnly+Secure(+ 필요 시 MFA/2FA)이유: 외부에서 시작된 모든 요청 차단 → CSRF 강력 봉쇄
링크로 들어와 로그인 풀리는 UX 이슈? 내부 시스템에선 영향 작음
외부 파트너사도 접근하는 B2B 포털처럼 외부 링크 접근이 꽤 있는 경우엔
Lax + CSRF 토큰 조합이 현실적입니다.
참고: SameSite는 2016년 Chrome 51에서 처음 도입되었고, 2020년부터는 기본값이 Lax 로 바뀌었습니다. 즉, 명시하지 않아도 기본적으로 Lax 동작을 하지만, 예전 브라우저는 기본값이 None처럼 동작할 수 있습니다. 또한 서비스 정책을 명확히 하기 위해 현업에서는 SameSite 를 항상 명시적으로 설정하는 것이 권장됩니다.
6️⃣ 함께 쓰는 보안 옵션
HttpOnly: 자바스크립트로 쿠키 접근 불가 → XSS로 쿠키 탈취 어렵게Secure: HTTPS에서만 전송 → 중간자 공격 완화CSRF 토큰: 폼/비동기 요청에 서버가 발급한 토큰을 함께 제출하도록 강제
Origin/Referer 검사: 요청의 출발지 헤더로 2차 확인
짧은 세션 수명 + 재발급(회전), 로그아웃 시 서버 세션 폐기
기억하기: SameSite는 CSRF의 “자동 쿠키 전송”을 줄여주는 1차 안전장치이고,
CSRF 토큰/Origin 체크는 서버에서 최종적으로 검증하는 2차 안전장치입니다.
정리
localStorage / sessionStorage
장점: CSRF와는 무관 (자동 전송 안 되니까)
단점: JS에서 접근 가능 → XSS 뚫리면 토큰 그대로 털림
현실적으로 XSS는 “사람이 실수하기 쉬운 부분”이라 더 위험
쿠키 (HttpOnly + Secure + SameSite 설정)
장점:
HttpOnly덕분에 JS에서 접근 불가 → XSS에 훨씬 안전단점: 자동 전송 특성 때문에 CSRF 위험, 하지만
HttpOnly + Secure + SameSite설정으로 방어 가능
CSRF는 브라우저/서버 설정 몇 가지로 방어선 구축 가능
XSS는 코드 전반에서 조심해야하고, 한번 뚫리면 localStorage/sessionStorage에 있는 토큰은 그대로 털림따라서 보안 민감 서비스(은행, 결제, 기업 내부 시스템)에서는 XSS에 강한 HttpOnly 쿠키가 더 안전하다고 보는 거예요
👉 그래서 실무에서는 보안 민감 서비스(은행, 결제, 기업 내부 시스템) → 쿠키 세션
👉 API 서버와 SPA 같은 구조 → JWT + 로컬 스토리지를 많이 쓰지만, 요즘은 JWT도 쿠키(HttpOnly)로 관리하는 흐름이 늘어나는 중이에요.