STUDY NOTE · 개념 정리
쿠키 vs 세션 vs 캐시 차이 정리 (+ 웹 스토리지, 토큰)
Network
쿠키와 세션은 "상태를 기억하기 위한 것", 캐시는 "같은 걸 다시 받지 않기 위한 것"이다. 셋을 가르는 기준은 저장 위치, 목적, 서버로의 전송 여부다.
1. 왜 필요한가: HTTP는 무상태(stateless)다
HTTP는 요청 하나하나가 독립적이다. 서버는 방금 요청한 사람이 1초 전에 로그인한 사람인지 모른다. 그래서 "이 사용자가 누구인지" 같은 상태를 이어 붙이기 위해 쿠키와 세션이 생겼다. 반면 캐시는 상태와 관계없이, 이미 받은 응답을 재사용해서 성능을 높이려는 장치다.
2. 한눈에 비교
| 구분 | 쿠키 (Cookie) | 세션 (Session) | 캐시 (Cache) |
| 목적 | 상태 유지 | 상태 유지 (민감 정보) | 성능 향상, 트래픽 절감 |
| 저장 위치 | 클라이언트 (브라우저) | 서버 (메모리, Redis, DB) | 브라우저, 프록시, CDN |
| 저장 대상 | 작은 키-값 문자열 | 사용자 상태 (로그인 정보 등) | HTTP 응답 (HTML, JS, 이미지 등) |
| 서버로 전송 | 조건이 맞으면 요청마다 자동 전송 | 세션 ID만 쿠키로 전송 | 전송하지 않음 (재검증 시 헤더만) |
| 만료 | Expires / Max-Age, 없으면 브라우저 종료 시 | 서버 타임아웃, 로그아웃 | Cache-Control max-age 등 |
| 용량 | 쿠키 하나당 약 4KB | 서버 자원 한도 내 | 브라우저 정책에 따름 |
| 보안 | 사용자가 보고 바꿀 수 있음 | 서버에 있어 상대적으로 안전 | 개인정보 응답은 저장 금지해야 함 |
| 누가 정하나 | 서버(Set-Cookie) 또는 JS | 서버 | 서버의 응답 헤더 |
3. 쿠키 (Cookie)
서버가 응답 헤더 Set-Cookie로 내려주면 브라우저가 저장하고, 이후 같은 도메인으로 요청할 때 Cookie 헤더에 자동으로 실어 보낸다.
| 속성 | 의미 |
| Expires / Max-Age | 만료 시점. 없으면 브라우저를 닫을 때 삭제되는 세션 쿠키 |
| Domain / Path | 어느 주소로 요청할 때 보낼지 |
| HttpOnly | JS(document.cookie)로 읽기 금지 → XSS로 탈취 방지 |
| Secure | HTTPS 요청에만 전송 |
| SameSite | 다른 사이트에서 시작된 요청에 보낼지 (Strict / Lax / None) → CSRF 방어 |
SameSite=Lax는 다른 사이트에서 링크를 눌러 이동하는 GET에는 보내고, 다른 사이트의 폼 POST나 이미지·iframe 요청에는 보내지 않는다. Chrome은 지정하지 않으면 Lax로 취급한다.SameSite=None은 항상 보내며, 반드시Secure와 함께 써야 한다.
4. 세션 (Session)
사용자 정보는 서버에 저장하고, 브라우저에는 그 정보를 찾을 수 있는 세션 ID만 쿠키로 준다.
- 로그인 성공 → 서버가 세션 저장소에
{세션ID: 사용자정보}저장 - 응답으로
Set-Cookie: JSESSIONID=abc123; HttpOnly - 이후 요청마다 브라우저가
Cookie: JSESSIONID=abc123전송 - 서버는 세션 ID로 저장소를 조회해 사용자를 식별
쿠키만 쓰면 userId=42를 사용자가 43으로 바꿔 보낼 수 있다. 세션은 의미 없는 난수 ID만 주고 진짜 정보는 서버에 있으니 변조할 수 없다. 대신 세션 ID 자체를 훔치면(세션 하이재킹) 그 사용자로 행세할 수 있어서 HttpOnly, Secure, 로그인 시 세션 ID 재발급(세션 고정 공격 방지)이 필요하다.
서버가 여러 대일 때의 문제: A 서버에서 만든 세션을 B 서버는 모른다.
| 방법 | 설명 | 단점 |
| Sticky Session | 로드밸런서가 같은 사용자를 같은 서버로 보냄 | 그 서버가 죽으면 세션 유실, 부하 쏠림 |
| Session Clustering | 서버끼리 세션을 복제 | 서버가 늘수록 복제 비용 증가 |
| 세션 저장소 분리 | Redis 같은 공용 저장소에 세션 저장 | 저장소가 단일 장애점이 되지 않게 구성 필요 |
실무에서는 보통 세 번째(Spring Session + Redis)를 쓴다.
5. 캐시 (HTTP Cache)
서버가 응답 헤더로 "이 응답을 얼마나, 어떻게 재사용해도 되는지" 알려준다.
| 헤더 값 | 의미 |
| max-age=초 | 이 시간 동안은 서버에 묻지 않고 캐시 사용 (fresh) |
| no-cache | 저장은 하되, 쓰기 전에 매번 서버에 재검증 |
| no-store | 아예 저장하지 않음 (개인정보, 결제 화면) |
| private | 브라우저에만 저장, 프록시·CDN은 저장 금지 |
| public | 공유 캐시(CDN)도 저장 가능 |
| immutable | 만료 전에는 재검증도 하지 않음 (해시 파일명 자산) |
재검증(조건부 요청): 캐시가 만료되면 다시 다 받는 게 아니라 "바뀌었니?"라고 묻는다.
- 첫 응답:
ETag: "v1"(또는Last-Modified) - 만료 후 요청:
If-None-Match: "v1" - 안 바뀌었으면
304 Not Modified(본문 없음) → 캐시 재사용 - 바뀌었으면
200 OK+ 새 본문
6. 함께 묻는 것: 웹 스토리지
| 구분 | 쿠키 | localStorage | sessionStorage |
| 서버 자동 전송 | O | X | X |
| 용량 | 약 4KB | 약 5MB | 약 5MB |
| 수명 | 만료 설정에 따름 | 직접 지울 때까지 | 탭을 닫을 때까지 |
| 공유 범위 | 도메인 단위 | 같은 출처의 모든 탭 | 해당 탭만 |
| JS 접근 | 가능 (HttpOnly면 불가) | 가능 | 가능 |
sessionStorage는 이름만 세션일 뿐 서버 세션과 아무 관계가 없다. 모두 JS로 읽을 수 있어 XSS에 노출되므로 토큰·개인정보보다 UI 설정 저장에 적합하다.
7. 함께 묻는 것: 세션 vs 토큰(JWT)
| 구분 | 세션 | 토큰 (JWT) |
| 상태 저장 | 서버가 저장 (stateful) | 토큰 자체에 정보 + 서명 (stateless) |
| 서버 확장 | 세션 공유 필요 | 서명만 검증하면 되어 쉬움 |
| 강제 로그아웃 | 세션 삭제로 즉시 가능 | 만료 전까지 무효화 어려움 |
| 크기 | 세션 ID만 오가서 작음 | 정보가 담겨 상대적으로 큼 |
| 보완책 | Redis 세션 저장소 | 짧은 Access Token + Refresh Token |
8. 실제로 어떻게 적용되나
- 로그인 유지: 세션 방식이면 세션 ID 쿠키에
HttpOnly; Secure; SameSite=Lax를 붙인다. 쿠키는 운반 수단, 세션은 실제 정보 저장소로 두 개념이 같이 쓰이는 대표 사례다. - "오늘 하루 보지 않기" 팝업: 서버가 알 필요 없는 UI 상태라 쿠키나 localStorage에 만료일과 함께 저장한다.
- 정적 파일 배포:
app.3f9a1c.js처럼 내용 해시가 붙은 파일은max-age=31536000, immutable, 그 파일을 가리키는 HTML은no-cache. 배포하면 HTML만 재검증되고 바뀐 JS는 파일명이 달라 새로 받는다. - 마이페이지 API 응답: 사용자별 데이터는
private또는no-store로 CDN에 저장되지 않게 한다. 안 그러면 다른 사람에게 내 정보가 캐시로 나갈 수 있다.
9. 자주 헷갈리는 포인트
no-cache는 "캐시 금지"가 아니라 "매번 확인 후 사용"이다. 금지는no-store.- 세션도 결국 쿠키를 쓴다. 차이는 쿠키에 정보 자체를 넣느냐, 정보를 찾을 키만 넣느냐다.
- 쿠키는 요청마다 따라가므로 많이 넣으면 모든 요청이 무거워진다.
10. 면접 질문으로 정리
- Q. 쿠키와 세션의 차이는? 쿠키는 클라이언트에 저장되어 요청마다 서버로 전송되는 데이터이고, 세션은 서버에 저장되는 사용자 상태다. 세션은 식별용 세션 ID만 쿠키로 주고받아 보안상 유리하지만 서버 자원을 쓰고, 서버가 여러 대면 세션 공유가 필요하다.
- Q. 캐시는 쿠키·세션과 무엇이 다른가? 쿠키·세션은 상태 유지가 목적이고, 캐시는 이미 받은 응답을 재사용해 응답 속도와 트래픽을 줄이는 게 목적이다. Cache-Control, ETag 같은 HTTP 헤더로 제어한다.
- Q. no-cache와 no-store의 차이는? no-cache는 저장하되 쓰기 전에 서버에 재검증하고, no-store는 아예 저장하지 않는다.
- Q. 쿠키를 안전하게 쓰려면? HttpOnly로 JS 접근을 막고, Secure로 HTTPS에서만 보내고, SameSite로 다른 사이트 요청에 실리지 않게 해 CSRF를 막는다.