Cookie

jade·2025년 8월 18일
0
post-thumbnail

intro

Next.js의 서버환경에서도 토큰에 접근할 수있도록 하기 위해 쿠키를 사용하게되었다. 유저기능을 온전히 도맡아 구현하는 것이라 우여곡절이 있었지만, 대부분의 문제는 내가 쿠키에 대해서 잘 모른다는 것에 기인했다. 다음번에 구현할 때에는 무지에서 오는 삽질이 줄어들도록 공부한점을 기록해본다.

🍪 쿠키란?

  • HTTP 쿠키란 서버가 사용자의 브라우저에 전송하는 작은 데이터 조각이다. 하나에 최대 4KB 까지 저장 할 수 있다.
  • 하나의 클라이언트에 최대 300개, 도메인당 20개 제한이 있었다(과거 브라우저 기준). 현재는 브라우저마다 훨씬 완화되어 도메인당 수백 개까지 저장 가능하다.
  • 브라우저는 동일한 서버에 요청을 보낼 때 저장된 데이터를 요청 헤더에 동봉하여 전송한다.
  • 과거에는 클라이언트 데이터를 저장할 때 쓰였으나, 매 요청 마다 쿠키가 전송되기 때문에 오버헤드가 생겨서 최근에는 스토리지에 담긴다.
  • 주로 로그인상태를 유지하는 세션관리, 혹은 사용자가 임의로 세팅한 옵션이나 테마를 저장하는데 쓰인다.
    - 유저인증에 쓰이는 JWT의 경우 Refresh Token을 쿠키에 담아 보내는 경우가 대부분이다. httpOnly, Secure 속성도 추가해서
  • 클라이언트 서버모델에서는 서버가 클라이언트의 요청에 응답할때, Set-cookie라는 응답 헤더에 브라우저가 수신해야할 쿠키정보를 명시한다.

서버에서 온 응답헤더에 set-cookie가 포함되면 브라우저에서는 해당 필드에 있던 데이터를 저장한다.

Set-Cookie 응답헤더에는 하나의 쿠키만 담을 수 있다.따라서 여러개의 쿠키를 보내려면 아래와 같이 보내면 된다.

Set-Cookie: <이름>=<>
Set-Cookie: <이름>=<>
Set-Cookie: <이름>=<>

쿠키를 받은 브라우저는 해당 쿠키를 클라이언트 컴퓨터의 하드디스크에 저장한다. 그리고 동일한 서버에 요청을 보낼 때 저장해놓은 쿠키를 Cookie라는 요청헤더에 싣어서 보낸다.

HTTP 요청 헤더에서
Cookie: <이름>=<값>; <이름>=<값>; <이름>=<값>
이렇게 보내진 쿠키를 볼 수 있다.

📌 서버에게 Set-Cookie헤더를 통해 브라우저로 쿠키를 보내는 것은 일회성 작업이다.
📌 브라우저에게 Cookie 헤더를 통해 서버로 쿠키를 돌려보내는 것은 일정시간 반복해서 수행되는 작업이다.

(쿠키를 들려 보내는 작업은 브라우저라는 HTTP 클라이언트만 해주는 독특한 작업!)


✏️ 쿠키의 유효기간 (Expires=종료시점)

  • 유효기간이 명시되지 않은 쿠키를 세션쿠키라고 부르며, 브라우저의 세션이 종료될 때 함께 만료된다.브라우저의 탭을 닫으면 서버가 보낸 쿠키는 만료된다
  • 유효기간이 명시된 쿠키를 영속쿠키(Permanent Cookie) 라고 부르며 세션과 무방하게 특정 기간, 특정 시점 까지 유효하다. 유효기간을 명시하려면, Expires속성이나 Max-Age 속성을 명시한다.
Set-Cookie: <쿠키 이름>=<쿠키 >; Expires=종료 시점
Set-Cookie: <쿠키 이름>=<쿠키 >; Max-Age=유효 기간

✏️ 쿠키의 적용범위1 (Domain=도메인)

Domain 속성을 명시하면 서브 도메인까지 포함하여 쿠키를 돌려보낼 수 있다.

Domain 속성을 test.com으로 설정하면 브라우저는 a.test.com으로 부터 받은 쿠키를, b.test.com으로도 보내게 된다. 그러므로 a.test.com과 b.test.com이 쿠키를 공유하는 효과가 발생한다.

✏️ 쿠키의 적용범위2 (Path=경로)

Path 속성을 명시하면 쿠키의 범위를 해당 도메인의 특정 경로로 쿠키의 범위를 축소시킬 수 있다.

Path 속성이 /users라고 설정되어 있는 쿠키는, 브라우저가 /users를 포함한 하위 경로로 요청을 할 때만 서버로 돌려 보낸다.

📌 path를 입력하지 않으면 루트 경로로 자동 입력된다.
📌 쿠키의 범위를 좁게 잡을 수록 보안에는 좋다.

✏️ 보안속성1 (Secure)

https 프로토콜 에서만 서버로 쿠키를 돌려보낸다.

😭 하지만 보통 개발시에는 로컬 http환경에서 작업하기 때문에 팀에서 Secure 쿠키를 사용하기로 한다면, "cloudflare, aws" 등등 ssl인증서를 발급해주는 기관을 통해 ssl인증서를 발급받아 https를 적용시켜야 한다.

대신 로컬에서 테스트할때 ssl 인증키를 간단하게 발급받으려면 mkcert를 통해 ssl 인증서를 발급 받으면 된다. (이 과정은 다음 포스팅에서..)

✏️ 보안속성2 (HttpOnly)

브라우저에서 자바스크립트로 document.cookie 객체를 통해 접근할 수 업다. 서드파티에서 JS 코드가 쿠키에 접근하는 것을 제한할 수 잇다.


🍪 서드파티 쿠키란?

  • 쿠키에 설정된 도메인 (Domain)을 기준으로 퍼스트 파티 쿠키와 서드파티 쿠키로 기준을 정한다.

  • 현재 사용자와 접속한 페이지 != 쿠키에 설정된 도메인이라면 서드파티 쿠키로 분류된다.

  • 서드파티쿠키는 주로 타게팅 광고 목적으로 사용된다.

  • ✏️ 신발 쇼핑몰 사이트를 자주 방문하게 되면 쿠키가 저장되게 되고 구글 애드센스가 이를 가져가 다른 사이트에서의 배너 광고에서 신발 광고가 화면에 나타나는 것이 서드 파티 쿠키를 이용한 원리다

  • ✅ 만약 로컬에서 개발 중인데 서버가 보낸 쿠키가 확인되지 않는다면 브라우저의 서드파티 쿠키 설정을 확인해보자.

  • 특히 Safari의 경우 ITP(Intelligent Tracking Prevention) 정책으로 인해 쿠키가 차단되는 경우가 있다.

ITP 정책이란?
서드파티쿠키를 기본적으로 차단하여 사용자의 브라우징 데이터가 외부에 노출되지 않도록 함

⚡️SameSite 정책

  • 서드파티 쿠키의 보안적 문제를 해결하기 위해 만들어진 기술
  • XSRF, CSRF 공격을 방지 할 수 있다.
  • 요청 도메인과 쿠키 정보내의 도메인이 다른 크로스 사이트로 전송하는 요청에 제한을 둘 수 있다.

SameSite 옵션

None

  • 크로스 사이트 요청에도 쿠키를 전송한다. 보안적적으로 Samesite 적요을 하지 않은 쿠키와 같다
  • SameSite=None 이려면 반드시 Secure 설정된 쿠키여야 한다.

Strict

  • 크로스사이트 요청에는 항상 전송되지 않음. 가장 보수적

Lax

  • Strict에 비해서 상대적으로 느슨한다. 몇가지 예외적인 요청에는 전송한다.

    예외기준
    SameSite=Lax 일때 쿠키가 예외적으로 전송되는 경우는 다음과 같다.

  • 사용자가<a>태크를 클릭해서 302 리다이텍트를 하거나, 자바스크립트 window.location.replace 등으로 인해 자동으로 이루어지는 이동에선 서드 파티 쿠키가 전송된다.

  • 하지만 <iframe> 태그나 <img> 태그를 문서에 삽입함으로서 발생하는 http 요청은 전송을 제한한다.

  • 또한 GET 요청에 대해선 쿠키가 전송되지만, POST 나 DELELTE 요청은 제한된다.참고로 SameSite 파라미터의 보안 속성을 서드 파티 쿠키에 한하는 것이며, 퍼스트 파티 쿠키는 Lax나 Strict여도 전송된다

profile
keep on pushing

0개의 댓글