근 2주동안 쿠키세팅이 안되서 애를 먹었다...
로그인 과정에서 쿠키가 세팅되고 대시보드로 넘어가야하는 상황이다.
로그인 플로우를 보자
- 로그인페이지에서 로그인을 하면 서버에서
set-cookie
헤더를 통해 클라이언트에 쿠키를 넘겨준다.
- 브라우저에 쿠키가 저장된다.
- 그리고 대시보드(
/
)로 router.push가 되면서 페이지가 전환된다.
- next.js의 getserversideprops에서 쿠키를 읽어오면서 로그인된 정보 요청을 서버에 보내 로그인된 사용자의 정보를 클라이언트에 세팅하고 채팅 준비가 완료된다.
그런데 페이지 전환이 안되는 것이다...
삽질(이라 적고, 인내력 키우기 라 읽는다)이 시작된다.
네트워크 탭에 요청을 보니 느낌표 표시가 나타났다. 마우스 커서를 보니 아래와 같은 에러가 뜨는 것이다.
this attempt to set cookie via set-cookie header was blocked due to user prefernece
구글링 해보니 sameSite=None , Secure
를 해야한다고 한다.
했는데도 같은 에러가 뜬다.
보니깐 크롬 브라우저 세팅에 서드파티 쿠키 허용
란에 체크를 해줘야한다고 한다. 체크하고 다시 시도해보니 위의 에러는 뜨지 않지만 새로운 느낌표가 나타났다...ㅋㅋㅋ
이때부터 stackoverflow에서 찾은 모든 해결책을 시도해봄.
backend - index.ts에서 cookie-session 시도 // 실패
nginx.conf에서 proxy_cookie_path Domain=..설정 // 실패
nginx.conf에서 proxy_cookie_domain 설정 // 실패
nginx.conf에서 proxy_cookie_redirect 설정 //실패
다 안됨..이때부터 절망....
그러나 절대 포기하지 않는다 😤 이 글 마지막 댓글에서 도메인에 대한 실마리를 얻음.
서버와 클라이언트 간의 도메인이 맞지 않아서 생기는 문제라고 한다...
그래서 프론트와 백엔드를 .online
으로 통일하고 SameSite=None Secure
해서 크로스사이트에서도 허용하게 해서 개방시킨다음 Domain=.online 또는 Domain=chat-app-clinet.online
으로 하면 쿠키가 클라이언트에 저장이 되고 클라이언트에서 쿠키를 읽어와서 로그인에 성공할 줄 알았다.
그렇게 한 결과 일단 저장이 되긴 하는데 대시보드로 넘어가지를 않는다...
그렇게 삽질이 계속 되었다. next.js middleware.ts를 달아보고 쿠키를 로그한 결과 쿠키가 읽어지지 않았던것... 그래서 대시보드(/
) - getserversideprops에서 로그인페이지(/login
)로 리다이렉팅을 하고 있었던 것이었다...
브라우저에 저장이 되면 당연히 읽어져야하는데 이해가 가지 않았다... 그러나 쿠키저장된 곳에 도메인을 보니 chat-app-backend.online
인 것이다??
아니 어떻게 이럴 수 있지?? 도메인은 백엔드인데 클라이언트에 저장이 되어버린것..( 백엔드에서 보내준 set-cookie 도메인이 백엔드이면 클라에서 저장이 안되어야 하는게 아닌가...)
그러니깐 당연히 chat-app-front.online
인 클라이언트에서 읽어올 수 가 없었던것...
근데 알아보니깐. 이건 도메인을 통일한게 아니라 그냥 다른 도메인인 것이었다.
보통 클라이언트와 백엔드 도메인이 도메인 - 서브도메인
의 관계로 설정된다는 것. 그래서 클라이언트는 ppp.online
, 백엔드는 api.ppp.online
이런식으로 한다는 것이다.
그래서 goDaddy에서 도메인을 다시 샀다. chat-app.live라는 도메인을 구입후 프론트(vercel) , 백엔드(oracle cloud VM)을 각각 연결해주었다.
(서브도메인 설정방법은 그냥 이름에다가 api
를 적어주면 됨ㅎㅎ)
그러고 nginx.conf - proxy_cookie_path에 도메인으로 chat-app.live
를 추가해주었다.
proxy_cookie_path / "/; Domain=.chat-app.live; HTTPOnly; SameSite=None; Secure"
vercel의 .env의 백엔드 환경변수를 api.chat-app.live
로 변경해주었다.
그러니 아래와 같이 쿠키가 세팅이 되면서 대시보드로 화면 전환이 되었다...
그리고 이 스샷은 내 카톡 프사가 되었다.(눈물이 찔끔 날정도로 감격스러웠기 때문).
글로 적고 보니 굉장히 짧고 간단한 작업인데도, 이런 문제를 맞닥뜨린적이 없어서 쿠키 세팅하고 잘 읽어오기 까지 거의 2주정도 소요가 되었다...
인터넷에 워낙 정보가 많았는데 쿠키와 서버에 대한 개념이 확립이 안되어있어서 가이드라인이 안잡혀있었고, 결국 온갖 stackoverflow와 블로그, 유튜브 방법을 시도하다가 길을 잃었기 때문...😅
처음부터, 쿠키를 왜 쓰고, 어떻게 사용이 되고, 각각 attribute는 어떤 기능을 담당하는지 부터 제대로 알고 시작했다면 시행착오가 줄었을라나...
여튼 담엔 개념부터 먼저 공부해야겠다는 생각이 들었다!
그래서 이 참에 쿠키를 파보자 해서 공부후 글을 적었으니 참고!
(쿠키 이제 다 먹어치울거다.🍪)
쿠키가 브라우저에 저장되는게 보안상 문제가 있다고 판단이 되면 서버에 저장해도 된다.
그대신 express-session과 redis의 도움을 받아야한다.
let redisClient = createClient();
redisClient.connect().catch(console.error);
let redisStore = new RedisStore({
client: redisClient,
prefix: "my-chat-app:",
});
app.use(
session({
secret: "chat-app-backend-secret",
resave: false,
saveUninitialized: true,
cookie: {
secure: true,
domain: process.env.NODE_ENV === "production" && ".chat-app.live",
},
store: redisStore,
})
);
이렇게 하고 서버에 요청을 보내면 connect.sid라는 값이 쿠키에 저장된다.
그럼 그 값을 가지고 쿠키를 주고 받는 것이다.
로그인 할때 api.chat-app.live/sign-in 로 요청을 보내는데, pending상태가 한참 되다가 200.ok 가 된다.
백엔드에서 webpack설정으로 build를 해준 다음 start를 하니 잘 되었다.
// webpack.config.js
const path = require("path");
module.exports = {
entry: {
main: "./index.ts",
},
output: {
path: path.join(__dirname, "dist"),
publicPath: "/",
filename: "bundle.js",
clean: true,
},
mode: "production",
target: "node",
devtool: "inline-source-map",
resolve: {
extensions: [".tsx", ".ts", ".js"],
},
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
loader: "ts-loader",
},
],
},
};
// package.json
"scripts":{
"build:prod": "webpack --config webpack.config.js --mode production",
"start:prod": "nodemon --exec 'ts-node' ./dist/bundle.js",
}
서버 502 에러가 발생하면 그 에러 내용이 넘어와야하는데 뜬금없이 cors에러가 뜬다.
구글링 해보니 에러 발생시 nginx에서 access-allow-control-origin 헤더가 포함되지 않아서 생기는 문제라고한다.
nginx.conf에서 always 값을 추가해주면서 해결했다.
그럼 이제 header가 항상 추가된다.
https://miriya.net/blog/l9QAZuGpbXmdSMsffoSA
https://yangbongsoo.tistory.com/5
https://m.blog.naver.com/pjok1122/221555161680