Photo by Mohammad Rahmani on Unsplash
Chrome은 84 버전부터 Cookie의 SameSite 속성을 기본적으로 Lax로 설정했습니다. Third-party cookies를 사용하는 서비스가 SameSite를 설정하지 않았다면 영향을 받을 수 있습니다.
개요
쿠키(Cookies)는 웹 서비스에서 상태를 저장하는 데 사용되는 메커니즘으로, 로그인 유지, 장바구니, 광고 추적 등에 흔히 사용됩니다. 하지만 쿠키의 광범위한 사용은 개인 정보 보호 및 보안 우려를 동반하며, SameSite는 이러한 문제를 해결하기 위해 등장했습니다.
First-Party and Third-Party
쿠키의 출처(Set-Cookie)에 따라 각 쿠키는 고유한 도메인을 가집니다. 사용자가 브라우저에서 현재 보고 있는 URL을 기준으로, 쿠키의 도메인과 현재 URL이 일치하면 First-Party이고, 그렇지 않으면 Third-Party입니다.
Third-party
예를 들어 a.com 웹사이트를 탐색할 때 third-party.com으로 요청(Request)을 보내고 third-party.com의 쿠키를 받았다고 가정해 봅시다. 브라우저는 요청 시 동일한 도메인의 쿠키를 자동으로 포함하므로, 이후 b.com과 같은 다른 사이트를 탐색할 때도 third-party.com으로 요청을 보내면 서버는 쿠키를 받게 됩니다. 이 두 웹사이트 입장에서 third-party.com의 쿠키는 Third-party입니다.
First-party
만약 third-party.com 도메인과 일치하는 웹사이트를 탐색하면 쿠키도 함께 전송됩니다. 이때 이 쿠키는 First-party라고 합니다.
Same-Origin and Same-Site
방금 전 예시에서는 도메인 일치 여부로 쿠키의 종류를 판단한다고 했지만, 더 정확히 말하면 사이트(Site)가 같은지 여부로 판단해야 합니다. 이것이 흔히 보는 Same-origin과 관련이 있을까요?

Origin
Origin은 Scheme, Host, Port로 구성됩니다. 판단 방식은 매우 간단합니다. 두 URL의 Scheme, Host, Port가 모두 같으면 Same-origin이고, 나머지는 모두 Cross-origin입니다.
Site
Same-Site 판단에는 Effective top-level domains(eTLDs)가 관여합니다. 모든 eTLD는 Public Suffix List에 정의되어 있으며, 사이트(Site)는 eTLD에 접두사를 더한 것으로 구성됩니다.
예를 들어:
github.io는 Public Suffix List에 존재합니다. 여기에 접두사(예: a.github.io)를 더하면 하나의 사이트가 됩니다. 따라서 a.github.io와 b.github.io는 서로 다른 사이트(Cross-site)입니다.
example.com은 Public Suffix List에 존재하지 않지만 .com은 존재하므로 example.com은 하나의 사이트이며, a.example.com과 b.example.com은 같은 사이트(Same-site)입니다.
사이트에는 포트(Port)가 포함되지 않으므로 포트가 달라도 Same-site일 수 있다는 점에 유의하세요.
Why SameSite?
“모든 요청에 해당 도메인의 쿠키를 포함하는” 메커니즘은 보안 및 기타 문제를 야기했습니다. 그중 가장 중요한 것은 Cross-site request forgery(CSRF)입니다.
CSRF
사용자가 example.com에 로그인하여 쿠키를 발급받았다고 가정해 봅시다. 사용자가 악성 사이트 evil.com을 탐색할 때, 사이트 내의 자바스크립트가 example.com/pay?amount=1000으로 POST 요청을 보낼 수 있습니다. 브라우저는 자동으로 example.com의 쿠키를 포함하게 되고, 사용자는 전혀 모르는 사이에 1000달러를 결제하게 됩니다. 서버는 이 요청이 어디서 왔는지 판단할 수 없습니다.
제한
쿠키 자체는 First-party 환경에서만 전송되도록 설정할 수 없으므로, 요청은 어떤 환경에서든 쿠키를 포함하게 됩니다. 서버는 요청 출처를 식별할 수 없어 평소처럼 응답할 수밖에 없으며, 클라이언트는 쓸모없는 쿠키를 보내느라 트래픽을 낭비하게 됩니다.
해결책
SameSite 속성이 생기면서 다양한 환경에서의 쿠키 전송 조건을 개별적으로 설정할 수 있게 되었습니다.
SameSite
SameSite 속성에는 세 가지 값이 있습니다. Strict 또는 Lax로 설정하면 Same-Site 요청에서만 쿠키를 포함하도록 제한할 수 있습니다. 비워둘 경우 브라우저에 따라 동작이 다를 수 있으며, Chrome의 경우 기본값은 Lax입니다.
Strict
First-party 환경에서만 쿠키를 포함합니다. 하지만 여기에는 문제가 있습니다. 사용자가 example.com에서 페이스북 게시물 링크(fb.com이라고 가정)를 보았다고 가정해 봅시다. 사용자가 fb.com에 로그인하여 쿠키를 가지고 있더라도, 링크를 클릭한 후에는 두 사이트가 Cross-site이므로 쿠키가 전송되지 않아 로그인 페이지만 보게 됩니다.
따라서 Strict는 게시물 삭제, 결제 등의 작업에 적합합니다.
Lax
Strict의 지나치게 엄격한 제한을 해결하기 위해, Lax는 다음과 같은 경우 Cross-site여도 쿠키를 전송합니다:
- 주소 표시줄에 URL 입력
- 링크
<a href="...">클릭 - 폼 전송
<form method="GET"> - 프리렌더링
<link rel="prerender" href="...">
이 상황들의 두 가지 공통점은 모두 GET 요청이며 최상위 탐색(Top-level Navigation)을 트리거한다는 것입니다. 이를 통해 Strict처럼 매번 다시 로그인해야 하는 문제를 피하면서, 다른 웹사이트를 탐색할 때 모르는 사이에 쿠키를 전송하는 것도 방지할 수 있습니다.
Lax + POST
하지만 기존의 일부 로그인 흐름을 깨뜨리지 않기 위해, Chrome은 현재 SameSite=Lax에 대해 제한을 약간 완화하여 개발자들에게 시간을 주고 있습니다.
쿠키가 설정된 지 2분 이내라면 요청 메서드(Request Method)에 관계없이 최상위 페이지 탐색을 트리거하는 한 쿠키가 전송됩니다. 즉, 폼 전송 <form method="POST">과 같이 브라우저가 페이지를 이동하는 경우입니다.
자세한 내용은 Lax + POST에 관한 스레드를 참조하세요.
None
Third-party cookie를 보내려면 반드시 SameSite=None; Secure로 설정해야 합니다. 맞습니다. 이제 테스트 환경에서 Third-party cookie를 보내려면 https://localhost를 준비해야 합니다.
또한 XHR/Fetch로 Cross-Origin Request를 보낼 때 쿠키를 포함하고 응답 헤더의 Set-Cookie를 유효하게 하려면 별도로 withCredentials: true를 설정해야 합니다. 그리고 서버 측에서는 응답 헤더에 Access-Control-Allow-Credentials: true를 설정해야 자바스크립트가 응답 내용에 접근할 수 있습니다.
지원하지 않는 브라우저
모든 브라우저가 최신 SameSite 규칙을 지원하는 것은 아니므로, 서버에 몇 가지 임시 해결책(Workaround)을 추가하여 여러 브라우저를 지원할 수 있습니다.
두 가지 쿠키 모두 설정
이 방식은 거의 모든 브라우저 문제를 해결할 수 있지만, 단점은 쿠키가 두 개가 된다는 것입니다.
Set-cookie: name=value; SameSite=None; Secure
Set-cookie: name-legacy=value; Secure
서버 측 코드:
if (req.cookies['name']) {
// 새 것이 있으면 새 것을 사용
cookieVal = req.cookies['name'];
} else if (req.cookies['name-legacy']) {
// 아니면 옛날 것을 사용
cookieVal = req.cookies['name-legacy'];
}
User Agent
요청의 User agent로 브라우저를 판단하여 Set-Cookie 내용을 결정합니다. 이 방식은 쿠키 설정 코드만 수정하면 되고 파싱 부분은 수정할 필요가 없지만, 판단 방식에 변수가 많아 잘못된 쿠키를 설정할 가능성이 큽니다.
되돌아보기
- SameSite 속성이 설정되지 않은 쿠키는
SameSite=Lax가 되며, Cross-site 환경에서는전송할 수 없습니다. - Cross-site에서 쿠키를 보내려면
SameSite=None; Secure를 설정해야 합니다. - SameSite sandbox를 사용하여 현재 사용하는 브라우저가 최신 SameSite 규칙을 준수하는지 테스트할 수 있습니다.