본문 바로가기

React/실험실

[React] Cookie

프론트엔드 개발을 하다보면 로그인 방식으로 JWT 방식을 사용하는 경우가 있을 것이다. 

 

JWT 방식은 구현하는 방법은 조금씩 차이가 있지만 기본적으로 로그인을 하는 경우 AccessToken과 RefreshToken을 

서버에서 클라이언트로 넘겨주고 이것을 통해서 로그인 유지와 사용자 검증을 한다. 

 

결국 Token을 통해서 로그인 정보를 관리하는 것이다. 

 

여기서 이번에 쿠키를 통해서 Token을 관리하는 방법으로 개발을 진행했는데, 

배포 환경은 문제가 없겠지만 개발 환경에서 서버가 보낸 Cookie를 브라우저가 저장하지 못하는 문제가 있었다. 

 

서버 ( 192.168.45.123 ) 이고, 클라이언트 ( 192.168.45.321 )일 때, 가장 먼저 할 일이 서버에 cors 설정을 했다. 

// ...
const app = express();

// ...
const corsOptions = {
  origin: "http://192.168.45.321:3000",
  credential: true,
}

app.use(cors(corsOptions));
// ...

추후 배포 환경에서는 배포된 클라이언트의 URL이 들어가야 하겠지만 

당장은 개발 환경을 테스트 하기 때문에 그 부분은 따로 작성하지 않겠다. 

 

설정을 마치고 로그인 테스트를 했을 때, 정상적으로 통신은 되지만 서버에서 설정한 Cookie가 브라우저에 저장되지 

않았다. 

 

이제부터 이 문제를 해결하는 과정이다. 

 

1. SameSite 옵션 

Cookie가 저장되지 않는 이유를 알아보니, Cookie의 SameSite 옵션이 "lax"로 되어 있어서 발생한 문제였다. 

 

lax 설정은 클라이언트에서 링크를 클릭하는 등 작업을 통해서는 전달이 가능하지만 AJAX 요청을 통해서 쿠키를 전달하는 것은 불가능하기 때문이다. 

 

이것을 해결하기 위해서는 SameSite 옵션을 "None"으로 설정해야 한다. 

이때 SameSite를 None으로 설정하기 위해선 secure 옵션을 true로 해야한다. 

 

app.use(function (req, res, next) {
  res.cookie('cookieName', 'cookieValue', { 
    sameSite: 'none', 
    secure: true
  });
  next();
});

설정을 모두 마치고 다시 요청을 했을 때 쿠키는 전달되지만 여전히 브라우저에 저장이 되지 않았다. 

secure 옵션이 true가 되기 위해선 https 환경에서만 가능한 것이다. 

 

즉, sameSite를 none으로 설정하기 위해선 secure옵션을 true로 설정해야하고 secure 옵션을 true로 설정하기 위해선 

https 환경이어야 한다. 

 

개발환경이 https라면 문제가 없겠지만 일반적으로 http 환경이고 이번 프로젝트 역시 http 환경이다. 

그래서 위와 같은 방법으로 해결할 수 없었다. 

 

다시 원점으로 돌아와서 쿠키를 브라우저에 저장하는 방법으로 

1. 개발 환경을 HTTPS 사용 

2. 프록시 서버 사용 

3. CORS 설정 변경 

 

1. 개발 환경을 HTTPS로 사용하는 것은 추가적으로 개발 환경에 세팅이 필요해서 배제했다. 

이번 문제가 아닌 HTTPS 환경이 필요한 경우라면 사용하겠지만 그게 아니라면 이것을 위해서 개발 환경을 HTTPS를 사용하는 것은 더 큰 일이라고 생각했다. 

 

2. 프록시 서버 사용 

그래서 생각한 것이 프록시 서버를 사용하는 것이다. 

CRA 환경에서 http-proxy-middleware를 사용하면 따로 라이브러리를 설치할 필요없이 개발 환경에서 

프록시 서버를 설정할 수 있다. 

 

http-proxy-middleware 역시 CRA 환경에 내장 되어 있기 때문에 설치할 필요가 없다. 

 

// /src/setupProxy.js

const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
  app.use(
    '/api',
    createProxyMiddleware({
      target: "http://192.168.45.123:4043",
      changeOrigin: true,
    })
  );
};

다음과 같이 설정하면 "/api" 경로로 시작하는 모든 요청을 'http://192.168.45.1234:4043' 경로로 프록시한다. 

이렇게 설정하면, 클라이언트는 모든 API 요청을 같은 "/api" 경로로 보낼 수 있다. 그리고 실제 요청은 

http://192.168.45.123:4043으로 전송된다. 

 

해당 설정으로 간단하게 쿠키 문제를 해결했다. 

 

정리 

결과적으로 서버와 클라이언트끼리 쿠키를 주고 받기 위해서 먼저 서버에 cors 설정을 진행한다. 

// ...
const app = express();

// ...
const corsOptions = {
  origin: "http://192.168.45.321:3000",
  credential: true,
}

app.use(cors(corsOptions));
// ...

 

그리고 개발 환경에서 SameSite 문제로 쿠키를 브라우저에 저장할 수 없으므로 클라이언트에 프록시 설정을 한다. 

// /src/setupProxy.js

const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
  app.use(
    '/api',
    createProxyMiddleware({
      target: "http://192.168.45.123:4043",  // 서버 URL
      changeOrigin: true,
    })
  );
};

클라이언트에서 "/api" 경로로 요청하면 설정해둔 target의 경로로 전송되며 문제를 해결할 수 있었다. 

 

이러한 방법은 개발 환경에서는 서버와 클라이언트의 URL이 달라 발생하는 쿠키 문제를 해결하기 위한 것이며, 

실제 배포 시에는 서버와 클라이언트가 같은 URL이라는 것을 가정하고 작업한 것이다. 

반응형

'React > 실험실' 카테고리의 다른 글

[React] dayjs  (0) 2023.06.13
[React] MSW 잘 사용해보기  (0) 2023.06.08
[React] Polymorphic 한 컴포넌트  (1) 2023.05.17
[React] useMemo를 사용하지 말아야 한다!  (0) 2023.04.20
[React] React18에서 추가된 Hook  (0) 2023.04.17