인프런 커뮤니티 질문&답변

신영 유님의 프로필 이미지

작성한 질문수

[리뉴얼] React로 NodeBird SNS 만들기

도메인 연결하기

Application > Cookies 에 front에만 저장이 안 돼요...

작성

·

2.3K

0

안녕하세요 제로초님,

Application > Cookies 에 sid가 front에만 저장이 안 되는 문제가 있습니다. sid가 back에는 저장이 됩니다.

제가 아직 쿠키와 세션 이해가 부족한 건지.. axios config에 뭔가 문제가 있는건지,,,

구글링 해봐도 별 거 안 나오고.. 제가 이미 다 한 거고...

https://stackoverflow.com/questions/71036779/cookies-sent-from-backend-but-not-set-correctly-on-frontend

https://stackoverflow.com/questions/72105765/axios-doesnt-create-a-cookie-even-though-set-cookie-header-is-there

front: config/config.ts

import axios from "axios";
import { backUrl } from "../../config/config";

axios.defaults.baseURL = backUrl;
axios.defaults.withCredentials = true;

const instance = axios.create({
  baseURL: backUrl, // cors
  withCredentials: true, // cookie (user info)
});
// instance.interceptors.request.use(function (instance) {
//   const kakao_authorization = localStorage.getItem("kakao_authorization");
//   const Token = localStorage.getItem("Authorization");
//   const Retoken = localStorage.getItem("refresh-Token");
//   instance.headers["Authorization"] = Token;
//   instance.headers["refresh-Token"] = Retoken;
//   instance.headers["kakao_authorization"] = kakao_authorization;
//   return instance;
// });

export default instance;

front - Network 탭

Screenshot 2023-05-10 at 6.20.58 PM.pngfront - Application > Cookies 탭Screenshot 2023-05-10 at 6.21.56 PM.png

back: app.js

const express = require('express');
const morgan = require('morgan');
const cors = require('cors');
const session = require('express-session');
const cookieParser = require('cookie-parser');
const passport = require('passport');
const dotenv = require('dotenv');
const path = require('path');
const hpp = require('hpp');
const helmet = require('helmet');

const userRouter = require('./routes/user');
const postRouter = require('./routes/post');
const postsRouter = require('./routes/posts');
const db = require('./models');
const passportConfig = require('./passport');

dotenv.config();

const app = express();

db.sequelize.sync()
  .then(()=>{
    console.log('db 연결 성공');
  })
  .catch(console.error);

passportConfig();

app.use(express.json()); // axios로 data보낼 때
app.use('/', express.static(path.join(__dirname, 'uploads'))); // multipart form data 
app.use(express.urlencoded({ extended: true })); // 일반 form 일 때에는 url encoded로 받음

if (process.env.NODE_ENV === 'production') {
  app.use(morgan('combined'));
  app.use(hpp());
  app.use(helmet({ contentSecurityPolicy: false }));
  app.use(cors({
    origin: 'http://shinyoungyou.com',
    credentials: true,
  })); 
} else {
  app.use(morgan('dev'));
  app.use(cors({
    origin: true,
    credentials: true,
  })); 
}

app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(session({
  saveUninitialized: false,
  resave: false,
  secret: process.env.COOKIE_SECRET,
  cookie: {
    httpOnly: true,
    secure: false
  },
  domain: process.env.NODE_ENV === 'production' && '.shinyoungyou.com'
}));
app.use(passport.initialize());
app.use(passport.session());

app.get('/', (req, res) => {
  res.send('Express + TypeScript Server');
});

app.post('/api/post', (req, res) => {
  res.send('this is post http method');
});

app.use("/user", userRouter);
app.use("/post", postRouter);
app.use("/posts", postsRouter);

module.exports = app;

back - Application > Cookies 탭

Screenshot 2023-05-10 at 6.21.37 PM.png

답변 11

0

신영 유님의 프로필 이미지
신영 유
질문자

한 번에 2개 요청이 간걸 보아

loadMyInfo, loadPosts가 백엔드로 요청은 가는 거 같은데,

여기에서 쿠키 전달이 안 되는지

const cookie = context.req ? context.req.headers.cookie : '';
  axios.defaults.headers.Cookie = '';
  if (cookie) {
    axios.defaults.headers.Cookie = cookie;
  }

Screenshot 2023-05-11 at 1.58.48 PM.png

my에 null을 반환하는 거 같네요.. SSR이라서 그런지는 모르겠지만 새로고침 이후 Network 탭에 응답 온게 확인이 안 되네요.. html css js 받기 전에 data를 불러오는 거라서..?

프론트에서

pages/index 는 이런 식으로 코드를 짜놓았구요.

import wrapper from '../store';
import { useSelector, useDispatch } from 'react-redux';
import { loadMyInfo } from "../store/thunks/user";
import { loadPosts } from "../store/thunks/post";
import React, { useState, useEffect } from "react";
import type { NextPage } from 'next';
import RootState from "../store/state-types";
import axios from "axios";

import AppLayout from '../components/AppLayout';
import PostForm from '../components/PostForm';
import PostCard from '../components/PostCard';
import Link from "next/link";
const Home: NextPage = () => {
  const { my } = useSelector((state: RootState)=>state.user);
  const { mainPosts, loadPostsLoading, bringMorePosts } = useSelector((state: RootState)=>state.post);
  const dispatch = useDispatch();

  const [prevLastId, setPrevLastId] = useState<number>(-1);

  // useEffect(()=>{
  //   if(mainPosts.length < 10){
  //     dispatch(loadMyInfo());
  //     dispatch(loadPosts());
  //   }
  //   console.log("loadPosts")
  // }, [])

  useEffect(()=>{
    const handleScroll = () => {
      if(window.scrollY + document.documentElement.clientHeight > document.documentElement.scrollHeight - 300){
        if(!loadPostsLoading && bringMorePosts){
          if(prevLastId != mainPosts[mainPosts.length - 1]?.id){
            dispatch(loadPosts({
              lastId: mainPosts[mainPosts.length - 1]?.id
            }));
          }
          setPrevLastId(mainPosts[mainPosts.length - 1]?.id);
        }
      }
    }

    window.addEventListener("scroll", handleScroll);

    return () => {
      window.removeEventListener("scroll", handleScroll);
    }
  }, [loadPostsLoading, bringMorePosts])

  return (
    <AppLayout>
      {my !== null && <PostForm/>}
      {mainPosts.map((post)=>(post.Retweet ? <PostCard post={post.Retweet} posts={mainPosts} retweetingPostId={post.id} key={post.id} /> : <PostCard post={post} posts={mainPosts} retweetingPostId={null} key={post.id} />))}
    </AppLayout>
  )
}

export const getServerSideProps = wrapper.getServerSideProps(async (context)=>{
  const cookie = context.req ? context.req.headers.cookie : '';
  axios.defaults.headers.Cookie = '';
  if (cookie) {
    axios.defaults.headers.Cookie = cookie;
  }
  await context.store.dispatch(loadMyInfo());
  await context.store.dispatch(loadPosts({}));
  // console.log(context.req);
});

export default Home;

그리고 프론트에서 cookie를 console.log을 하고 싶은데 npx pm2 kill을 하고 터미널 kill을 해도 제 브라우저가 살아있어서 npm start를 하면 already in use ::80 에러가 뜨네요..

웃긴게 np2 pm2 reload all 을 하고 list보니까 아무것도 없고요 ㅋㅋㅋ

그래서.. 쿠키가 안 받아지는 건 어디에서 시작된 버그인지 감이 안 잡히는데 도와주실 수 있을까요 엉엉...

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

getServerSideProps에서 보낸 요청은 브라우저 콘솔에 안 뜨는 게 맞습니다.

쿠키가 안 받아지는 건 어디에서 시작된 버그인지 감이 안 잡히는데 도와주실 수 있을까요 엉엉...

쿠키가 안 받아진다는 게 무슨 뜻인가요? 지금 문제는 쿠키 문제인지 알수가 없는데요.

강좌처럼 리덕스 사가 쓰시는 건가요? 그러면 getServerSideProps 코드가 저게 아닙니다. 강좌 코드 다시 봐보세요.

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

toolkit 쓰시는 거면 HYDRATE 제대로 하셨나요?

0

신영 유님의 프로필 이미지
신영 유
질문자

제로초님 덕분에 쿠키에 domain 넣는 거는 성공 했는데, domain 넣는 거랑 새로고침 시 로그인 풀리는 건 다른 문제 인가요? 감사합니다.

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

새로고침 시에도 프론트서버, 백엔드서버로 쿠키가 전달되어야 로그인이 유지됩니다. getServerSideProps에 쿠키 처리한 코드가 그것입니다.

0

신영 유님의 프로필 이미지
신영 유
질문자

프론트& 백엔드 쿠기 다 지우고 다시 로그인 시도했을떄

프론트 Network 탭

domain=.shinyoungyou.com은 있네요

0

신영 유님의 프로필 이미지
신영 유
질문자

새로고침 후 로그인 시도 했을 때

프론트

백엔드

0

신영 유님의 프로필 이미지
신영 유
질문자

아예 NODE_ENV 컨디션을 빼보고 다시 로그인 시도 했는데도 똑같아요

사진 붙여도 의미는 없겠지만..

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

아... domain 속성을 cookie 객체 안에 넣어야 합니다. 이제 발견했네요.

0

신영 유님의 프로필 이미지
신영 유
질문자

혹시 브라우저에 캐시가 쌓여서 변경된 코드가 반영이 안되거나 그러기도 하나요..?

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

백엔드라서 상관없습니다.

0

신영 유님의 프로필 이미지
신영 유
질문자

네네

 "start": "cross-env NODE_ENV=production pm2 start index.js",

이거를 해주고 npx pm2 kill 했다가 npm start를 했고, 한 번 더 확인을 위해 process.env.NODE_ENV까지 화면에 찍어보았습니다..

0

신영 유님의 프로필 이미지
신영 유
질문자

production 환경인건 맞는 거 같아요...

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

지금 다시 로그인해서 쿠키에 Domain 속성 들어있는지 확인해보세요.

0

신영 유님의 프로필 이미지
신영 유
질문자

{
  "name": "serverjs-nextproject",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "cross-env NODE_ENV=production pm2 start index.js",
    "dev": "nodemon index"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "aws-sdk": "^2.710.0",
    "bcrypt": "^5.1.0",
    "cookie-parser": "^1.4.6",
    "cors": "^2.8.5",
    "cross-env": "^7.0.2",
    "dotenv": "^16.0.3",
    "express": "^4.18.2",
    "express-session": "^1.17.3",
    "helmet": "^3.23.3",
    "hpp": "^0.2.3",
    "morgan": "^1.10.0",
    "multer": "^1.4.5-lts.1",
    "multer-s3": "^2.9.0",
    "mysql2": "^3.1.1",
    "passport": "^0.6.0",
    "passport-local": "^1.0.0",
    "pm2": "^4.4.0",
    "sequelize": "^6.28.0",
    "sequelize-cli": "^6.6.0"
  },
  "devDependencies": {
    "nodemon": "^2.0.20"
  }
}

0

신영 유님의 프로필 이미지
신영 유
질문자

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

쿠키에 Domain 속성이없는데요.(.shinyoungyou.com이어야 합니다) 백엔드에서 process.env.NODE_ENV가 production이 맞나요? 서버 실행 명령어에 NODE_ENV=production 붙이셨나요?