HTTP는 상태가 없는(stateless) 프로토콜이라, 서버는 방금 요청을 보낸 사용자가 조금 전 로그인한 그 사용자인지 스스로 알 방법이 없습니다. 쿠키는 이 문제를 푸는 가장 오래된 표준 장치로, 서버가 작은 키·값 데이터를 브라우저에 저장시켜 두면 브라우저가 이후 같은 사이트로 가는 모든 요청에 자동으로 그 값을 실어 보냅니다. 그 결과 서버는 요청들을 하나의 '세션'으로 묶어 로그인 상태나 장바구니를 기억할 수 있습니다.
Set-Cookie와 Cookie
쿠키의 왕복은 두 개의 헤더로 이뤄집니다. 서버는 응답에 Set-Cookie 헤더로 저장할 쿠키를 지시하고, 브라우저는 이후 요청마다 Cookie 헤더에 저장된 값을 담아 보냅니다. Set-Cookie는 쿠키 하나당 한 줄씩 여러 번 보낼 수 있지만, 요청 쪽 Cookie는 모든 쿠키를 세미콜론으로 이어 한 줄에 담습니다.
HTTP/1.1 200 OK
Set-Cookie: session_id=a1b2c3d4; HttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=3600
Set-Cookie: theme=dark; Path=/; Max-Age=31536000
(이후 같은 사이트로 가는 요청)
GET /dashboard HTTP/1.1
Host: app.example.com
Cookie: session_id=a1b2c3d4; theme=dark
쿠키 속성
쿠키의 보안과 동작은 이름·값 뒤에 붙는 속성(attribute)들이 결정합니다. 이 속성들을 정확히 이해하는 것이 쿠키 사용의 핵심입니다.
HttpOnly: 자바스크립트의document.cookie로 읽을 수 없게 막습니다. XSS 공격이 세션 쿠키를 탈취하는 것을 방어하므로 인증 쿠키에는 사실상 필수입니다.Secure: HTTPS 연결에서만 전송합니다. 평문 HTTP로는 쿠키가 나가지 않아 스니핑을 막습니다.SameSite: 교차 사이트 요청에 쿠키를 붙일지 제어합니다.Strict(같은 사이트만),Lax(기본값, 최상위 내비게이션 GET은 허용),None(교차 사이트 허용, 단Secure필수).Domain: 쿠키가 유효한 도메인. 지정하지 않으면 정확히 발급 호스트에만,Domain=example.com으로 지정하면 서브도메인까지 포함됩니다.Path: 쿠키를 보낼 경로 접두사.Path=/admin이면/admin이하 요청에만 실립니다.Max-Age/Expires: 수명.Max-Age는 초 단위 상대 시간,Expires는 절대 시각. 둘 다 없으면 브라우저를 닫을 때 사라지는 세션 쿠키가 됩니다.
세션 인증 vs 토큰 인증
쿠키로 상태를 유지하는 방식은 크게 두 갈래입니다. 세션 인증은 서버가 세션 데이터를 서버 측(메모리·Redis·DB)에 저장하고 클라이언트에는 의미 없는 세션 ID만 쿠키로 내려주는 방식입니다. 서버가 상태를 쥐고 있어 즉시 로그아웃·무효화가 쉽지만, 여러 서버로 확장하려면 세션 저장소를 공유해야 합니다. 토큰 인증은 사용자 정보와 서명을 담은 JWT 같은 토큰 자체를 클라이언트가 지니는 방식으로, 서버가 세션을 저장하지 않아 확장성이 좋지만 만료 전 강제 무효화가 어렵습니다. 토큰을 HttpOnly 쿠키에 담으면 두 방식의 장점을 일부 결합할 수 있습니다.
CSRF: 쿠키의 자동 전송이 낳는 위험
브라우저가 쿠키를 자동으로 붙인다는 편리함이 곧 취약점이 됩니다. 사용자가 은행 사이트에 로그인한 상태에서 공격자가 만든 페이지를 방문하면, 그 페이지가 몰래 은행으로 요청을 보내도 브라우저는 세션 쿠키를 자동으로 실어 보냅니다. 이것이 CSRF(Cross-Site Request Forgery)입니다. 가장 효과적인 1차 방어는 인증 쿠키에 SameSite=Lax 또는 Strict를 걸어 교차 사이트 요청에는 쿠키가 붙지 않게 하는 것입니다. 여기에 상태 변경 요청마다 예측 불가능한 CSRF 토큰을 요구하는 이중 제출(double-submit) 패턴을 더하면 방어가 견고해집니다.
크기 제한과 서드파티 쿠키의 종말
쿠키는 작은 식별자를 위한 것이지 데이터 저장소가 아닙니다. 쿠키 하나는 대략 4KB로 제한되고, 도메인당 개수도 제한(브라우저마다 약 50~180개)됩니다. 매 요청에 함께 전송되므로 큰 쿠키는 모든 요청을 무겁게 만듭니다. 큰 클라이언트 상태는 localStorage나 IndexedDB에 두세요.
한편 광고·추적에 쓰이던 서드파티 쿠키(방문 중인 사이트가 아닌 다른 도메인이 설정한 쿠키)는 프라이버시 강화 흐름 속에서 퇴출되고 있습니다. Safari와 Firefox는 이미 기본 차단하며, 크로스 사이트 추적을 막기 위해 SameSite=None을 명시하지 않은 쿠키는 교차 컨텍스트에서 전송되지 않습니다. 자사(first-party) 로그인 세션에는 영향이 적지만, 여러 도메인에 걸친 임베드·SSO를 설계한다면 이 변화를 반드시 고려해야 합니다.