사이드 프로젝트에서 계정 정보를 다루다가 쿠키가 프론트에 저장이 안 되는 상황이 발생했습니다. page의 도메인과 server의 도메인이 달라서 벌어진 일이었습니다. 빠르게 결론을 내자면, 쿠키를 주고 받으려면 도메인을 맞추어야 합니다. 제가 이 문제를 어떻게 분석하고 해결했는지를 적어봅니다.
쿠키란 무엇인가
쿠키란 무엇인가?서버가 사용자의 웹 브라우저에 전송하는 작은 데이터 조각
입니다. 브라우저는 쿠키를 저장해 놓았다가, 동일한 서버에 재 요청 시 저장된 데이터를 함께 전송합니다. 쿠키는 두 요청이 동일한 브라우저에서 들어왔는지 아닌지를 판단할 때 주로 사용합니다. 이를 이용하면 사용자의 로그인 상태를 유지할 수 있습니다.
쿠키 직접 다루어보기
🚨23년 2월 기준의 코드이므로 node가 업데이트되거나 하면 작동이 안 될 수 있습니다. 참고용으로만 봐주시기를 부탁드립니다.🚨
same-origin인 경우
MDN에서는 protocol, port, host 가 같으면 same-origin이라고 합니다.
사실상 같은 사이트인데 pathmame부터 다른 것을 뜻하는 것 같습니다.
생활코딩에서 출처한 그림을 참고하면 더욱 이해가 쉽습니다.
이 경우에는 아무 설정 없이 원활하게 쿠키를 주고 받을 수 있습니다.
port가 다르면 credential이 필요
code는 크게 index.html
과 server.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을 설정하는 방법이라고 합니다.
'Develop' 카테고리의 다른 글
lazy loading으로 Entry Point File 크기 줄이는 방법 연구 (0) | 2024.07.20 |
---|---|
React context 대신 Event bus를 사용해 렌더링 개선하는 방법 조사 (0) | 2024.07.20 |
drag event 성능 개선을 위한 JS web worker 사전 조사 (0) | 2024.07.20 |
React : performamce, profiler를 통한 성능 개선 측정하기 (drag & drop, state refactoring) (0) | 2024.07.20 |
친구 프로그램 만들어주기 (with C) (0) | 2024.07.20 |