Post

[인증/인가] Cookie, 왜 보안 옵션이 필수일까?

이전 글에서 살펴봤듯이, HTTP는 기본적으로 Stateless(무상태)한 프로토콜이다.

즉 서버는 요청이 끝나면 사용자를 기억하지 않는다.
하지만 현실의 웹 서비스는 그렇지 않다.

  • 페이지를 이동해도 로그인 상태가 유지되고
  • 하루 전에 닫았던 사이트를 다시 열어도 설정이 남아있다.
  • “오늘 하루 그만 보기”를 누른 팝업은 다시 뜨지 않는다.

이런 동작들은 어떻게 가능한 걸까?
이 문제를 해결하기 위해 등장한 개념이 바로 Cookie(쿠키)다.


🍪 Cookie란?

쿠키는 클라이언트와 서버의 연결이 끊어지더라도, 필요한 정보를 기억하기 위해 사용되는 작은 데이터 조각이다.

서버가 데이터를 key=value 형태로 묶어
클라이언트(브라우저)에 저장해 두는 작은 텍스트 파일이라고 보면 된다.

쿠키는 서버가 만들어 주지만, 실제로 보관하는 곳은 클라이언트(브라우저)다.

쿠키는 언제, 왜 사용될까?

쿠키는 생각보다 우리 일상 속에서 아주 많이 사용되고 있다.
대표적인 사용 목적은 다음과 같다.

1. 로그인 상태 유지

로그인에 성공하면 서버는 쿠키를 하나 발급한다.
이 쿠키에는 사용자를 직접 식별하는 정보가 아니라,
사용자를 가리키는 식별자(session id 등)가 담긴다.

이후 클라이언트는 요청을 보낼 때마다 쿠키를 함께 전달하고,
서버는 해당 식별자를 기준으로 “아, 이 사용자구나”하고 판단한다.

2. 사용자 추적 및 분석

우리가 한 번 검색한 상품이 다른 사이트에서도 계속 광고로 보이는 이유가 바로 여기에 있다.

  • 광고 추천
  • 방문 기록 분석
  • 사용자 행동 기반 통계 수집

cookie_agree

3. 사용자 설정 저장

  • 언어 설정
  • 다크 모드 / 라이트 모드
  • 팝업 “오늘 하루 그만 보기”

이런 정보들도 대부분 쿠키를 통해 저장된다.


쿠키의 특징

쿠키를 이해할 때 꼭 기억해야 할 포인트들이 있다.

  • 쿠키는 클라이언트가 데이터를 가지고 있다.
  • 브라우저 단위로 관리된다.
    • 같은 사이트라도 크롬과 사파리는 서로 다른 쿠키를 가진다.
  • 기본적으로 쿠키는 현재 응답을 보낸 도메인에서만 설정할 수 있다.
    다른 도메인의 쿠키를 임의로 생성하거나 수정하는 것은 불가능하다.
  • 쿠키는 만료 시간까지 상태 정보를 유지한다.
  • 브라우저 구현에 따라 차이는 있지만, 쿠키에는 저장 용량과 개수에 제한이 있다.
    • 하나의 쿠키는 약 4KB
    • 도메인당 약 20개 내외
    • 브라우저는 제한을 초과하면 오래된 쿠키를 삭제하는 방식으로 관리한다.

이 때문에 쿠키는 아주 가벼운 정보를 저장하는 데에 적합하다.


쿠키의 동작 방식

쿠키는 다음과 같은 흐름으로 동작한다.

1
2
3
4
5
6
1. 클라이언트가 서버에 요청을 보낸다.
2. 서버가 쿠키를 생성한다.
3. HTTP 응답 헤더(Set-Cookie)에 쿠키를 담아 응답한다.
4. 브라우저는 쿠키를 저장한다.
5. 이후 같은 사이트로 요청할 때마다, 브라우저는 HTTP 요청 헤더에 쿠키를 함께 전송한다.
6. 서버는 쿠키를 읽어 사용자 상태를 판단하거나, 필요하다면 쿠키를 갱신해 다시 응답한다.

cookie_auth_logic


쿠키는 어떻게 설정될까?

쿠키는 HTTP 응답 헤더의 Set-Cookie를 통해 설정된다.

1
Set-Cookie: session_id=123abc; Expires=Mon, 09 Feb 2026 07:06:00 GMT; Secure; HttpOnly

이 헤더를 받은 브라우저는
“이 쿠키를 언제까지, 어떤 조건에서 저장하고 전송해야 하는지”를 알게 된다.


쿠키의 종류

쿠키는 만료 시점을 기준으로 두 가지로 나뉜다.

브라우저가 열려 있는 동안만 유지되는 쿠키다.
브라우저를 닫으면 자동으로 삭제된다.

  • 저장 위치: 브라우저 메모리 (일부 구현에서는 임시 저장소)
  • 용도: 로그인 세션 유지, 일시적인 상태 관리
  • Expires, Max-Age 속성을 명시하지 않음
  • ex) Set-Cookie: session_id=abc123; Path=/; HttpOnly

정해진 만료 시점까지 디스크에 저장되는 쿠키이다.
브라우저를 종료해도 유지된다.

  • 저장 위치: 디스크
  • 용도: 자동 로그인, 사용자 설정, 방문 기록
  • ex) Set-Cookie: user_id=abc123; Expires=Mon, 09 Feb 2026 07:06:00 GMT; Secure

쿠키의 주요 속성

각 속성은 쿠키의 동작 방식을 결정한다.

속성설명
Key=Value쿠키의 이름(name)과 값(value)
Expires쿠키 만료 시점 (절대 시간)
Max-Age쿠키 유효 기간 (초 단위)
Domain쿠키 적용 도메인 범위
Path쿠키가 전송될 URL 경로
SecureHTTPS에서만 전송
HttpOnlyJavaScript 접근 차단 (XSS 방지)
SameSiteCSRF 방어 옵션, Strict / Lax / None 中 선택

Expires와 Max-Age 둘 중 하나만 있어도 동작하지만, Max-Age를 우선시한다.


쿠키 보안 옵션은 왜 필요할까?

쿠키는 편리하지만, 한 가지 치명적인 특징을 가지고 있다.

쿠키는 매 요청 마다 서버로 자동 전송된다.

이 특성 덕분에 로그인 상태를 유지할 수 있지만,
반대로 말하면 공격자 입장에서도 노리기 쉬운 대상이라는 뜻이기도 하다.

쿠키는 다음과 같은 공격에 취약할 수 있다.

  • XSS (Cross-Site Scripting)
  • CSRF (Cross-Site Request Forgery)

(쿠키 자체가 취약한 기술이라기보다는, 보안 옵션 없이 사용될 경우 XSS, CSRF 공격의 주요 타깃이 된다.)

이런 공격을 완화하기 위해
브라우저와 서버는 쿠키에 여러 보안 옵션을 제공한다.

그 중에서도 가장 중요한 옵션이 HttpOnlySameSite이다.
이 옵션에 대해 자세히 알아보자.


HttpOnly - “자바스크립트 접근 차단”

HttpOnly 옵션은 JavaScript를 통해 쿠키에 접근하는 것을 막아주는 설정이다.

1
Set-Cookie: session_id=abc123; HttpOnly

이 옵션이 설정된 쿠키는
document.cookie를 통해 읽거나 수정할 수 없다.

왜 필요한 걸까?
XSS 공격을 떠올려보자.

공격자가 웹 페이지에 악성 JavaScript 코드를 삽입하였고,
사용자가 해당 페이지에 접속했다면?

1
2
// 공격자가 삽입한 악성 스크립트
alert(document.cookie);

만약 쿠키에 로그인 정보나 세션 ID가 들어 있고, HttpOnly가 설정되어 있지 않다면?
⟹ 공격자는 쿠키 값을 그대로 탈취할 수 있다.

하지만 HttpOnly가 설정된 쿠키라면 브라우저가 JavaScript 접근 자체를 차단하며,
쿠키는 HTTP 요청을 통해서만 서버로 전송한다.

즉 XSS로부터 쿠키 탈취를 방어할 수 있다.
따라서 세션 ID나 인증 관련 내용, 사용자 권한과 직접 연결되는 정보 등 민감한 쿠키에는 거의 필수 옵션이라고 봐도 된다.


SameSite - “다른 사이트에서 온 요청은 제한”

SameSite는 다른 사이트에서 발생한 요청에 쿠키 전송을 제어하는 옵션이다.
이 옵션은 CSRF 공격을 방어하는 데 핵심적인 역할을 한다.

1
Set-Cookie: session_id=abc123; SameSite=Lax

🤔 CSRF는 어떻게 발생할까?
CSRF 공격의 핵심은 이거다.

사용자는 로그인되어 있고,
브라우저는 자동으로 쿠키를 전송한다.

예를 들어 이런 상황이다.

1
2
3
4
5
6
7
1. 사용자는 은행 사이트에 로그인 되어있다.
2. 공격자는 악성 사이트를 만들어 두었다.
3. 사용자가 그 사이트를 방문한다.
4. 그 사이트에서 은행 서버로 요청을 보낸다.
5. 브라우저는 자동으로 쿠키를 포함해 요청한다.

➔ 서버는 "정상 사용자 요청이구나"하고 처리해버린다.

SameSite 옵션은 바로 이 자동 전송을 제어해준다.

SameSite 옵션 종류 (3가지)

1. SameSite = Strict

1
Set-Cookie: session_id=abc123; SameSite=Strict
  • 완전 차단
  • 다른 사이트에서 시작된 요청에는 쿠키를 절대 전송하지 않는다.
  • 보안은 강력하지만, UX가 불편해질 수 있다.
  • 예시: 외부 링크 클릭 ➔ 로그인 풀려버림
  • 보안 최우선 서비스에 적합하다.

2. SameSite = Lax (기본값)

1
Set-Cookie: session_id=abc123; SameSite=Lax
  • 기본적으로 크로스 사이트 요청 차단
  • 일부 안전한 요청 (GET 기반의 top-level navigation 등)은 허용
  • POST, PUT 같은 위험한 요청에는 쿠키 미전송
  • 보안과 UX의 균형이 좋다.

3. SameSite = None

1
Set-Cookie: session_id=abc123; SameSite=None; Secure
  • 크로스 사이트 요청에도 쿠키 전송 허용
  • 반드시 Secure 옵션과 함께 사용해야 한다.
  • 주로 OAuth, 외부 로그인 연동에서 사용


Secure - “HTTPS 에서만 전송”

Secure 옵션은 HTTPS 연결에서만 쿠키를 전송하도록 제한한다.

  • HTTP(평문) 요청에서는 쿠키가 전송되지 않는다.
  • 네트워크 스니핑 공격을 방지할 수 있다.
  • 인증 관련 쿠키에는 거의 필수이다.

지금까지 쿠키를 개념적으로만 살펴봤다.
그렇다면 실제 브라우저에서는 쿠키가 어떤 형태로 저장되고 있을까?

크롬 개발자 도구를 통해,
내 깃허브 블로그 사이트에 저장된 쿠키를 직접 확인해보았다.

saved_cookie

브라우저 개발자 도구(Application 탭)에서 저장된 쿠키 정보를 확인한 화면이다.

쿠키명(Name), 값(Value), 도메인(Domain), Path, 만료 정보(Expires/Max-Age), 그리고 HttpOnly, Secure 같은 보안 옵션들이 각 쿠키마다 어떻게 설정되어 있는지 확인할 수 있다.


쿠키의 장・단점

장점

  • 대부분의 브라우저에서 기본적으로 지원한다.
  • 만료 기간을 설정할 수 있어 상태 관리가 가능하다.
  • HttpOnly 옵션을 설정하면 XSS 공격을 통한 쿠키 탈취를 완화할 수 있다.

단점

  • 저장 용량이 매우 작다. (약 4KB)
  • 모든 요청에 자동으로 포함되어 전송되므로 탈취 위험이 존재한다.
  • 별도의 방어 장치가 없다면 CSRF 공격에 노출될 수 있다.

CSRF(Cross-Site Request Forgery)란?

공격자가 사용자의 인증 상태를 악용해
사용자의 의지와 상관없는 요청을 서버로 보내는 공격을 의미한다.

쿠키가 탈취되면 해당 쿠키를 가진 것만으로도 사용자를 가장할 수 있다는 점이 가장 큰 문제점이다.

그래서 쿠키만으로 인증 상태를 관리하는 것은 위험하다.⚠️

아무리 보안 옵션을 잘 설정하더라도,
쿠키는 결국 클라이언트에 저장되는 데이터이기 때문이다.

이러한 한계 때문에 민감한 정보를 쿠키에 직접 저장하는 방식은 실제 서비스에서 거의 사용되지 않는다.

대신, 대부분의 웹 서비스는 쿠키와 세션을 함께 사용하는 구조를 선택한다.

  • 쿠키에는 의미 없는 Session ID만 저장하고
  • 실제 사용자 정보는 서버의 세션 스토어에 보관한다.
  • 서버는 쿠키에 담긴 Session ID를 기준으로 사용자를 식별한다.

이 구조를 사용하면 쿠키가 탈취되더라도 직접적인 사용자 정보 노출을 막을 수 있다.


마무리

쿠키는 HTTP의 무상태성을 보완하기 위해 등장한 가장 기본적인 상태 관리 방식이다.

하지만 보안과 확장성 측면에서는 분명한 한계를 가지고 있다.
이 한계를 보완하기 위해 등장한 개념이 바로 Session이다.

다음 글에서는 Session은 무엇이고, 왜 쿠키와 함께 사용되는지 살펴보자.

© sihyun. Some rights reserved.