개요
웹 개발을 하면서 Cookie 와 Session 이라는 개념을 자주 마주했지만,
막상 설명하려 하면 명확하게 정리되어 있지 않다는 느낌이 들었다.
이 글에서는 두 개념을 복습하고 정리해보고자 한다.
HTTP 는 Stateless
Cookie 와 Session 을 이해하기 전에 먼저 HTTP 의 특성을 알아볼 필요가 있다.
RFC 9110 에서는 HTTP 를 다음과 같이 정의한다.
RFC (Request for Comments): 인터넷 표준을 정의하는 공식 문서
"The Hypertext Transfer Protocol (HTTP) is a stateless application-level protocol for distributed, collaborative, hypertext information systems."
출처: RFC 9110 – HTTP Semantics
HTTP 는 분산되고 협업적인 하이퍼텍스트 정보 시스템을 위한 무상태(stateless) 애플리케이션 계층 프로토콜이다.
여기서 Stateless 란 무엇일까?
Stateless
HTTP 는 다음과 같은 요청-응답 구조를 가진다.
sequenceDiagram
participant C as Client
participant S as Server
C->>S: Request
S-->>C: Response
- Client(브라우저)가 Server 에 요청을 보낸다.
- Server 는 요청을 처리하고 응답을 보낸다.
- 그 요청-응답 사이클은 종료된다.
다음 요청이 오면, Server 는 그것을 완전히 새로운 요청으로 취급한다.
즉, Server 는 이전에 어떤 요청이 왔었는지 기억하지 않는다. 이것이 Stateless 이다.
Stateless 의 한계
하지만 실제 서비스에서는 이전 요청의 맥락이 유지되어야 하는 경우가 많다.
- 사용자가 로그인되어 있는가?
- 장바구니에 어떤 상품이 담겨 있는가?
- 사용자의 권한은 무엇인가?
예를 들어, 사용자가 로그인한 뒤 마이페이지로 이동한다고 가정해보자.
이 두 행동은 별도의 HTTP 요청이기 때문에, Server 입장에서 로그인 요청과 마이페이지 요청은 서로 독립적인 요청이다.
즉, 로그인했다는 사실이 다음 요청에 자동으로 이어지지 않는 것이다.
장바구니도 마찬가지다. 상품을 담는 요청과 결제 페이지를 여는 요청은 서로 독립적이기 때문에,
별도의 수단이 없다면 Server 는 "이 사용자가 무엇을 담았는지" 알 수 없다.
이처럼, 서비스 관점에서는 요청 간에 맥락이 유지되어야 하지만 HTTP 자체는 이를 제공하지 않는다.
이 간극을 메우기 위해 등장한 것이 Cookie 와 Session 라고 할 수 있다.
그냥 요청에 정보를 담으면 되지 않나?
여기서 한 가지 의문이 들었다.
장바구니에 물건을 담을 때 사용자 아이디를 함께 보내고,
장바구니 조회 요청에도 사용자 아이디를 포함하면 맥락이 유지되는 것 아닌가?
하지만 이 방식에는 근본적인 문제가 있다.
단순히 요청에 사용자 아이디를 포함한다고 해서, 그 요청을 보낸 사람이 실제로 그 사용자라는 것을 보장할 수 없다.
예를 들어, 본인만 볼 수 있어야 하는 마이페이지를 다음과 같이 구현했다고 하자.
GET /mypage?userId=user999이 경우, userId 값만 바꾸면 누구든 다른 사람의 마이페이지에 접근할 수 있게 된다.
요청에 아이디를 담는 것만으로는 "이 요청을 보낸 사람이 정말 그 사용자인가" 를 검증할 수 없는 것이다.
장바구니도 마찬가지다.
POST /cart/add?userId=user999&itemId=42다른 사람이 userId=user999 를 넣어 요청을 보내면, user999 의 장바구니에 원치 않는 상품이 담기게 된다.
즉, 필요한 것은 단순히 정보를 전달하는 수단이 아니라,
Server 가 신뢰할 수 있는 방식으로 사용자를 식별하는 수단이다.
이를 위해서는 두 가지가 필요하다.
- 식별 정보를 저장하고, 요청마다 자동으로 전달하는 수단
- 그 수단에 담길, 신뢰할 수 있는 식별 값
Cookie 와 Session 은 각각 이 역할을 담당한다.
Cookie
앞서 말한 첫 번째 역할, 즉 식별 정보를 저장하고 자동으로 전달하는 수단에 해당하는 것이 Cookie 이다.
Cookie 는 Server 가 응답을 통해 Client 에게 저장을 지시하는 작은 데이터 조각이며,
Client 는 이후 요청마다 이 데이터를 자동으로 함께 전송한다.
Cookie 의 동작 흐름
예를 들어, 사용자가 로그인에 성공했다고 하자.
Server 는 응답 헤더에 Set-Cookie 를 포함하여, Client 에게 특정 값을 저장하도록 지시한다.
HTTP/1.1 200 OK
Set-Cookie: id=user001
Client(Browser)는 이 값을 Browser 의 쿠키 저장소에 저장한다.
이것은 localStorage 나 메모리와는 별도의 영역으로, Browser 가 쿠키 전용으로 관리하는 저장소이다.
이 쿠키 저장소는 Browser 개발자 도구의 Application 탭 Cookies 항목에서 직접 확인할 수 있다.
![]()
이후 Client 가 같은 Server 에 요청을 보낼 때, Browser 는 저장된 쿠키를 자동으로 요청 헤더에 포함한다.
GET /mypage
Cookie: id=user001sequenceDiagram
participant C as Client
participant S as Server
C->>S: POST /login (아이디, 비밀번호)
S-->>C: 200 OK + Set-Cookie: id=user001
C->>S: GET /mypage + Cookie: id=user001
S-->>C: 200 OK (마이페이지 데이터)
개발자가 매 요청마다 수동으로 값을 붙이는 것이 아니라,
Browser 가 Set-Cookie 로 받은 값을 자동으로 관리하고 전송한다는 점이 핵심이다.
이로써 값을 저장하고 자동으로 전달하는 수단은 마련되었다.
그렇다면 이제 남은 질문은, Cookie 에 어떤 값을 담아야 하는가 이다.
Cookie 에 담기는 값
위 예시에서는 Cookie 에 id=user001 을 담았다.
하지만 이 값은 사용자 아이디 그 자체이기 때문에,
앞서 GET /mypage?userId=user001 로 살펴보았던 문제와 본질적으로 다르지 않다.
Cookie 의 값을 id=user999 로 조작하면, 여전히 다른 사용자인 것처럼 요청을 보낼 수 있다.
전달 수단은 마련되었지만, 그 안에 담기는 식별 값 자체가 신뢰할 수 없다면
Cookie 를 쓰는 의미가 없어진다.
그렇다면 Cookie 에 담기는 식별 값은 다음 조건을 만족해야 한다.
- 추측하기 어려운 값이어야 한다 (사용자 아이디처럼 공개된 정보가 아니라)
- Server 만이 발급하고 검증할 수 있어야 한다
이런 조건을 충족하는 식별 값을 만들고 관리하는 구조가 바로 Session 이다.
Session
Session 은 Server 가 각 사용자의 상태를 저장하고 관리하는 구조이며,
Client 에게는 이 Session 을 가리키는 식별자(Session ID) 만 전달된다.
Session 의 동작 흐름
사용자가 로그인에 성공하면, Server 는 해당 사용자의 정보를 Session 에 저장하고,
이 Session 을 가리키는 고유한 식별자인 Session ID 를 생성한다.
HTTP/1.1 200 OK
Set-Cookie: sessionId=abc123xyz
Cookie 에 담기는 값은 user001 같은 사용자 아이디가 아니라,
Server 가 발급한, 추측할 수 없는 값인 abc123xyz 이다.
이후 Client 가 요청을 보내면, Browser 는 이 Session ID 를 Cookie 에 담아 자동으로 전송한다.
GET /mypage
Cookie: sessionId=abc123xyz
Server 는 전달받은 Session ID 로 자신이 보관하고 있는 Session 을 조회하고,
그 안에 저장된 사용자 정보(예: userId=user001)를 확인하여 요청을 처리한다.
sequenceDiagram
participant C as Client
participant S as Server
C->>S: POST /login (아이디, 비밀번호)
Note right of S: Session 생성 및 사용자 정보 저장
S-->>C: 200 OK + Set-Cookie: sessionId=abc123xyz
C->>S: GET /mypage + Cookie: sessionId=abc123xyz
Note right of S: Session 조회 → userId=user001 확인
S-->>C: 200 OK (마이페이지 데이터)
Cookie 만 사용했을 때와의 차이
핵심적인 차이는, 사용자의 실제 정보가 Client 에 노출되지 않는다는 점이다.
| Cookie 에 userId 저장 | Cookie 에 Session ID 저장 | |
|---|---|---|
| Cookie 값 | id=user001 |
sessionId=abc123xyz |
| 사용자 정보 위치 | Client (Cookie) | Server (Session) |
| 조작 가능성 | 값을 바꾸면 다른 사용자로 위장 가능 | 유효한 Session ID 를 추측하기 어려움 |
Client 는 Session ID 만 알 뿐, 그것이 어떤 사용자와 연결되어 있는지는 알 수 없다.
Session 의 실제 데이터는 Server 에만 존재하기 때문에, Client 가 이를 직접 변경할 수도 없다.
Session 의 만료
웹사이트를 사용하다 보면 "세션이 만료되었습니다" 라는 문구를 종종 접한다.
Session 은 왜 만료되어야 할까?
우리는 보안상의 이유로 Cookie 에 userId 대신 sessionId 를 담기로 했다.
sessionId는 추측하기 어려운 무작위 값이므로,userId를 사용하는 것보다 안전하다.
하지만 sessionId 자체가 탈취된다면, 공격자는 그 값을 그대로 사용하여 해당 사용자인 것처럼 요청을 보낼 수 있다.
이것이 sessionId 가 영구적이면 안 되는 이유이다.
userId 는 한 번 정해지면 바꾸기 어렵지만, sessionId 는 Server 가 언제든 새로 발급할 수 있다.
따라서 Session 에 만료 시간을 두고, 일정 시간이 지나면 해당 Session 을 무효화한다.
만료된 sessionId 로 요청이 들어오면 Server 는 이를 거부하고,
사용자에게 다시 로그인하도록 요구하여 새로운 Session 을 생성한다.
Session 이 오래 유지될수록 탈취된 sessionId 가 악용될 수 있는 시간도 길어지기 때문에,
적절한 만료 시간을 설정하는 것이 보안 유지에 꼭 필요하다.
정리
정리하면 다음과 같다.
HTTP 는 무상태 프로토콜이므로 상태를 유지하려면 매 요청마다 식별 정보를 전달해야 하며,
Cookie 는 그 식별 정보를 자동으로 전달하는 수단이고,
Session 은 그 식별자를 통해 서버가 사용자 상태를 안전하게 관리하는 방식이다.
관련 포스팅
'Computer Science > Network' 카테고리의 다른 글
| [Network] Cookie 옵션 (HttpOnly, Secure, SameSite) - 실습으로 이해하기 (0) | 2026.02.24 |
|---|