쿠키(Cookie)의 개념과 실전 예제

FastAPI로 알아보는 쿠키(Cookie)의 개념과 동작 원리

written by tiaz0128

HTTP의 무상태(Stateless) 특성

HTTP 프로토콜은 기본적으로 무상태(Stateless)입니다. 이는 각 요청이 독립적이며, 서버가 이전 요청에 대한 정보를 기억하지 않는다는 의미입니다. 이런 특성은 다음과 같은 문제가 있었습니다.

쿠키는 이러한 무상태 특성에서 상태를 유지할 수 있게 해주는 핵심 메커니즘입니다.

쿠키(Cookie)

쿠키(Cookie)는 웹 서버가 사용자의 브라우저에 저장하는 작은 텍스트 데이터입니다. 이 데이터는 서버와 클라이언트 간의 상태 정보를 유지하는 데 중요한 역할을 합니다.

쿠키(Cookie) 용어의 유래

1994년 넷스케이프 커뮤니케이션즈(Netscape Communications)의 프로그래머 루 몬튤리(Lou Montulli)가 웹 브라우저와 서버 간에 정보를 저장하고 유지하는 메커니즘이 필요했고, 쿠키라는 개념을 처음 도입했습니다.

“쿠키(Cookie)”라는 이름은 ‘포춘 쿠키’ 안에 메시지가 들어있듯이, 쿠키도 정보를 담고 있는 작은 데이터 조각이라는 유사성에서 명칭이 유래됐습니다.

Lou Montulli

> Lou Montull – the inventor of the browser cookie

쿠키의 역할

쿠키는 웹사이트가 사용자의 활동을 기억하기 위해 사용하는 소량의 데이터로, 사용자 브라우저에 저장됩니다. 주요 역할은 다음과 같습니다.

쿠키의 동작 원리

쿠키는 다음과 같이 동작합니다.

  1. 서버는 HTTP 응답 헤더의 Set-Cookie 필드를 통해 쿠키를 설정합니다.
  2. 브라우저는 이 쿠키를 저장합니다.
  3. 이후 같은 서버로 요청을 보낼 때마다 브라우저는 HTTP 요청 헤더의 Cookie 필드에 이 값을 포함시킵니다.

서버 응답(Response) 헤더 예시

HTTP/1.1 200 OK
Set-Cookie: user_id=12345; Max-Age=3600; Path=/

클라이언트 요청(Request) 헤더 예시

GET /profile HTTP/1.1
Host: example.com
Cookie: user_id=12345

실습 방법

Chrome 웹 브라우저를 기반으로 설명하겠습니다.

웹 브라우저의 개발자 도구(Dev Tools)를 이용해 아래의 정보를 확인하면서 쿠키의 설정값을 확인하고 수정, 삭제할 수 있습니다. 키보드 F12를 통해 개발도구 창을 열어줍니다.

개발자 도구: Network 탭

Network 탭에서 서버 응답(Response) 헤더와 클라이언트 요청(Request) 헤더를 확인할 수 있습니다. 각 헤더에서 아래의 값이 어떻게 오고 가는지 관찰해봅시다.

Chrome Network 탭

> Chrome Network 탭에서 헤더를 확인하자

개발자 도구: Application 탭

쿠키는 Application 탭에서 확인 및 값을 변경 및 삭제 가능합니다. 다양한 쿠키의 속성값에 따른 쿠키의 변화를 관찰해봅시다.

Chrome Application 탭

> Chrome Application 탭에서 쿠키를 확인하자

실전 예제

파이썬 3.13 버전을 사용했습니다.

여기에서는 FastAPI 그리고 웹 브라우저의 개발자 도구(Dev Tools)를 통해 쿠키를 확인하고 테스트 해보겠습니다. 우선은 아래의 명령으로 필요한 패키지를 설치합니다.

패키지 설치

$ pip install fastapi "uvicorn[standard]"

소스코드

FastAPI는 쿠키를 설정할 때 Response.set_cookie() 메서드를 사용하며, 이 메서드로 쿠키의 다양한 옵션을 설정할 수 있습니다.

main.py
from datetime import datetime, UTC
from fastapi import FastAPI, Response, Request
from fastapi.responses import HTMLResponse

app = FastAPI()

# 쿠키 설정 엔드포인트
@app.get("/set_cookie")
async def set_cookie(response: Response):
    response.set_cookie(
        key="user_id",
        value="tiaz",
    )
    return {"message": "쿠키가 설정되었습니다!"}

# 쿠키 확인 엔드포인트
@app.get("/get_cookie")
async def get_cookie(request: Request):
    user_id = request.cookies.get("user_id", "없음")  # 쿠키 읽기
    theme = request.cookies.get("theme", "없음")
    return {"user_id": user_id, "theme": theme}

# 테스트용 HTML 페이지
@app.get("/", response_class=HTMLResponse)
async def home():
    return """
    <html>
        <body>
            <h1>FastAPI 쿠키 테스트</h1>
            <a href="/set_cookie">쿠키 설정</a><br>
            <a href="/get_cookie">쿠키 확인</a>
        </body>
    </html>
    """

서버 동작

작성 코드로 서버를 동작시켜 줍니다. 그리고 아래의 주소로 웹 브라우저로 접속합니다.

$ uvicorn main:app --reload
http://127.0.0.1:8000/

이제 쿠키의 다양한 설정값을 세팅해보면서 각 속성의 특징을 확인해 보겠습니다.

쿠키의 주요 설정값

쿠키 속성값을 테스트할때는 기존의 쿠키를 항상 지우고 테스트합시다!

쿠키의 주요 설정값은 다음과 같습니다.

key-value (필수)

response.set_cookie(
    key="user_id",
    value="tiaz",
)

max_age

response.set_cookie(
    key="user_id",
    value="tiaz",
    max_age=30,
)

expires

response.set_cookie(
    key="user_id",
    value="tiaz",
    expires=datetime(2025, 12, 31, tzinfo=UTC),
)

영속적 쿠키(Persistent Cookie)는 Expires 또는 Max-Age 속성이 있는, 지정된 시간 동안 유지하는 쿠키를 의미합니다. 반대로 Expires, Max-Age 속성이 없는 쿠키를 ‘세션 쿠키(Session Cookie)’라 합니다.

특성 세션 쿠키 영속적 쿠키
수명 브라우저 세션 동안 설정된 기간 동안
저장 위치 주로 메모리 디스크
삭제 시점 브라우저 종료 시 만료 시간 도달 또는 수동 삭제 시
속성 Expires/Max-Age 없음 Expires 또는 Max-Age 설정됨
보안 측면 상대적으로 안전 오용 가능성 있음

path

response.set_cookie(
    key="user_id",
    value="tiaz",
    path="/get_cookie",  # 쿠키가 유효한 경로
)

domain

response.set_cookie(
    key="user_id",
    value="tiaz",
    domain="localhost", # localhost로 접속 시에만 브라우저에 쿠키가 저장됨
)

쿠키와 관련된 보안 설정

쿠키의 보안 설정값은 특히 중요합니다. 실무에서도 해당 속성들을 설정하고 사용하는 과정에서 빈번히 실수를 합니다. 각 속성의 정확한 의미와 특징을 이해하고 실습해보겠습니다.

secure

response.set_cookie(
    key="user_id",
    value="tiaz",
    secure=True
)
로컬 도메인을 설정해서 `Secure` 속성을 테스트할 수 있습니다. `DNS 동작 방식 - hosts 파일: 로컬 DNS 실습`을 참고해보세요!

httponly

response.set_cookie(
    key="user_id",
    value="tiaz",
    httponly=False
)

httponly=False 설정하는 경우에는 브라우저의 콘솔창에서 쿠키 값에 접근하고 변경까지 가능합니다. 반대로 True인 경우에는 접근이 불가능 합니다.

document.cookie = 'user_id=test1234'

samesite

이 설정을 통해 브라우저가 다른 사이트에서 요청을 보낼 때 쿠키를 함께 전송할지 여부를 제어할 수 있습니다.

response.set_cookie(
    key="user_id",
    value="tiaz",
    samesite="strict",
)
SameSite 값 동일 사이트 요청 링크 클릭 폼 제출 iframe/이미지 fetch/XHR 특징
Strict ✅ 허용 ❌ 차단 ❌ 차단 ❌ 차단 ❌ 차단 가장 안전하지만 사용자 경험 저하
Lax
(기본값)
✅ 허용 ✅ 허용
(GET만)
❌ 차단 ❌ 차단 ❌ 차단 보안과 사용성의 균형
None ✅ 허용 ✅ 허용 ✅ 허용 ✅ 허용 ✅ 허용 레거시 동작
(Secure=True 필수)

마무리

지금까지 HTTP의 무상태(Stateless) 특성을 극복하기 위한 쿠키의 개념, 동작 원리, 그리고 실제 구현 방법에 대해 알아보았습니다. 쿠키는 간단한 텍스트 데이터지만, 웹 애플리케이션에서 사용자 경험을 유지하는 데 중요한 역할을 합니다.

쿠키 외에도 웹 애플리케이션에서 상태를 유지하는 다양한 방법이 있습니다. 다음에는 아래의 다른 방법에 대해서 알아보도록 하겠습니다! 감사합니다. 😊

참고 문헌

Cookie FastAPI Python

tiaz0128

Eat Sleep Coding.

Never Never GiveUp.

Security  |  BackEnd  |  Multi Cloud