쿠키로 마음을 전하고 싶으면 도메인부터 맞추자 🍪

Keinn51·2023년 2월 26일
1
post-thumbnail

사이드 프로젝트에서 계정 정보를 다루다가 쿠키가 프론트에 저장이 안 되는 상황이 발생했습니다.
page의 도메인과 server의 도메인이 달라서 벌어진 일이었습니다.

빠르게 결론을 내자면, 쿠키를 주고 받으려면 도메인을 맞추어야 합니다.
제가 이 문제를 어떻게 분석하고 해결했는지를 적어봅니다.

쿠키란 무엇인가

쿠키란 무엇인가?
서버가 사용자의 웹 브라우저에 전송하는 작은 데이터 조각입니다. 브라우저는 쿠키를 저장해 놓았다가, 동일한 서버에 재 요청 시 저장된 데이터를 함께 전송합니다. 쿠키는 두 요청이 동일한 브라우저에서 들어왔는지 아닌지를 판단할 때 주로 사용합니다. 이를 이용하면 사용자의 로그인 상태를 유지할 수 있습니다.

쿠키 직접 다루어보기

🚨23년 2월 기준의 코드이므로 node가 업데이트되거나 하면 작동이 안 될 수 있습니다.
참고용으로만 봐주시기를 부탁드립니다.🚨

same-origin인 경우

same-origin
MDN에서는 protocol, port, host 가 같으면 same-origin이라고 합니다.
사실상 같은 사이트인데 pathmame부터 다른 것을 뜻하는 것 같습니다.
생활코딩에서 출처한 그림을 참고하면 더욱 이해가 쉽습니다.

이 경우에는 아무 설정 없이 원활하게 쿠키를 주고 받을 수 있습니다.

port가 다르면 credential이 필요

code는 크게 index.htmlserver.js로 나누어져 있습니다. server.js는 node로 실행시켜둘 것입니다.

  • index.html 이 Page, 즉 Front-end 역할을 맡는다.
  • server.js 가 Server, 즉 Back-end 역할을 맡는다.

코드는 다음과 같습니다. 기본 틀이 이렇고 앞으로는 바뀐 부분을 보여줄 것입니다.

<!-- index.html -->
<head>
    <script>
        const getCookie = () => {
            fetch("http://localhost:3085/")
        };
    </script>
</head>
<body>
    <button onclick="getCookie()">getCookie</button>
</body>
// server.js
const express = require("express");
const cookieParser = require("cookie-parser");
const HTTPS_PORT = 3085;

const app = express();

// client에서 cookie를 받아올 수 있게 해줌
app.use(
	// cors로 서버에 접근할 수 있는 url 제한
    cors({
        // 통신을 허용해줄 url 적을 수 있음
        origin: ["http://localhost:5500"],
        // 클리이언트가 credentials true인데 얘를 안 켜주면 에러남
        credentials: true,
    })
);

app.get("/", (req, res) => {
    // 클라이언트에 쿠키를 보내줌. key-value 형식
    res.cookie("cookieKey", "cookieValue");
    // 클라이언트에서 보내주는 쿠키를 서버에서 받을 수 있음 (cookieParser의 역할)
    console.log(req.cookies);
    // response 를 끝내주기.
    res.end();
});

app.listen(HTTPS_PORT, () => console.log(`port ${HTTPS_PORT}!`));

page의 포트는 5500이고 server는 3085이기 때문에 cross-origin입니다.
이 때에는 Request.credentials 의 속성을 다르게 주어야 합니다.
credential이란 cross-origin의 경우 다른 도메인에서 쿠키를 보내거나 받아야 하는지 여부를 나타냅니다.

기본적으로는 same-origin 으로 되어 있는데, 이를 include로 바꾸어줍니다.
include는 cross-origin의 상황에서도 쿠키를 주고 받을 수 있게 합니다.
위의 모든 말의 근거는 MDN 에서 찾았습니다.

이 것의 결과는 아래와 같습니다. 쿠키가 잘 전달된 모습입니다.

hostname이 다르면 SameSite 설정

이런 상황입니다. localhost는 127.0.0.1 이라는 ip의 다른 이름입니다. DNS 참고!
hostname이 다른 상황이며, 이 때에는 응답 헤더에 SameSite 라는 쿠키 설정법을 써야 한다고 합니다.

SameSite 속성은 쿠키를 같은 도메인으로 제한해야 하는지 여부를 선언할 수 있습니다.
SameSite=none 을 하면 도메인이 다른 사이트에서도 쿠키를 받을 수 있습니다.
이 때 Secure 속성도 같이 켜주어야 하는데, 이는 https 요청에만 응답하도록 설정하는 것입니다.

// server.js 에서 기존 코드 변경
app.use(
    cors({
        // 통신을 허용해줄 url 을 추가로 적어주기
        origin: ["http://localhost:5500", "http://127.0.0.1:5500"],
        credentials: true,
    })
);

app.get("/", (req, res) => {
    // 응답 헤더의 cookie 설정 변경
    res.cookie("cookieKey", "cookieValue", { sameSite: "none", secure: true });
    console.log(req.cookies);
    res.end();
});

이 것은 page와 server를 배포해둔 상태여야 테스트해볼 수 있어서 이번 글에서는 넘어갑니다.

결론

내가 진행했던 프로젝트에서는, page와 server가 다른 도메인이었습니다.
SameSite=true 를 통해서 해결할 수 있었겠습니다.
우리가 만든 페이지가 아니라 다른 페이지에 쿠키가 심어질 수도 있다는 불안감이 느껴졌습니다.

결국 프론트 도메인과 서버 도메인을 맞추어주었습니다.
naver.com 이 page라고 하면 server를 api.naver.com 이런 식으로 말입니다.
이 방식은 sub-domain을 설정하는 방법이라고 합니다.

profile
책임질 수 있는 글을 쓰렴

0개의 댓글