포시코딩

[Nest.js][CORS] cookie를 전달받지 못하는 문제 본문

Node.js

[Nest.js][CORS] cookie를 전달받지 못하는 문제

포시 2023. 2. 17. 16:21
728x90

개요

클라이언트 서버 localhost:3000 을 react로 운영중이고

백엔드 서버 localhost:8080 을 Nest.js로 운영중인 상황이다.

 

controller

@Post(':id/join')
async joinGroup(@Param('id') boardId: number, @Req() req: Request) {
  console.log(req.cookies);
}

Nest.js 서버에 이런 코드가 있는데 쿠키를 세팅해놓고 요청을 해도 계속 

[Object: null prototype] {}

이 값만 반환한다.

 

신기한건 Insomnia 상에서 테스트할 땐 잘 된다는거..

Headers에 세팅해놓은 값이 잘 전달된다.

 

그래서 처음에는 클라이언트쪽 문제로 생각했다.

 

시행착오

axios의 문제가 아닐까해서

이전 프로젝트에서 fetch를 통해 로그인 상태의 쿠키를 잘 전달했던 코드에서

쿠키를 넣어놓고 요청주소만 바꿔 요청해보았다.

 

결과는 실패.

 

여기서 나는 클라이언트 문제가 아니라 서버 문제라 생각했다.

 

해당 현상에 대해 구글링해보면 모두 cors 설정이 필요해서 그렇다는데

나는 이미 예전에 cors 설정이 되어있는 상황이었다.

 

main.ts

import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import cookieParser from 'cookie-parser';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.enableCors({
    origin: true,
    credentials: true,
  });
  app.useGlobalPipes(
    new ValidationPipe({
      whitelist: true,
      forbidNonWhitelisted: true,
      transform: true,
    }),
  );
  app.use(cookieParser());
  await app.listen(8080);
}
bootstrap();

 

해결방법

스택오버플로우에 나온 모든 방법들을 테스트하던 도중

axios에 credential 관련 세팅을 추가하는 방법을 발견했다.

 

https://stackoverflow.com/questions/68224532/req-cookies-returns-object-null-prototype-even-if-the-cookie-is-set

 

req.cookies returns [Object: null prototype] {} even if the cookie is set

I try to store and read a cookie via cookie-parser. Setting the cookie is working fine. Its listed under the "Application"-Tab of the dev tools: But if i try to read the cookie like this...

stackoverflow.com

 

before

axios
  .post(
    `http://localhost:8080/boards/${boardId}/join`,
    {
      // 데이터
    },
  )
  .then((response) => {

기존에는 이렇게 작성했다면

 

after

axios
  .post(
    `http://localhost:8080/boards/${boardId}/join`,
    {
      // 데이터
    },
    { withCredentials: true },
  )
  .then((response) => {

 

이렇게 하고 하니 [Object: null prototype] {}가 아닌 원래 쿠키 값들이 잘 출력된다..!

 

정리

cors 문제긴 했지만 그와 더불어 credential 문제가 있었던 것이었다.

만약 위 방법으로도 안된다면 Nest.js에서 

app.enableCors({
  origin: 'http://localhost:3000',
  credentials: true,
});

이렇게 요청하는 클라이언트 서버 주소를 직접 명시하고 테스트해보시기 바란다.

 

왜 withCredentials 설정을 통해 해결할 수 있었는지 찾아봤는데

withCredentials 옵션은 서로 다른 도메인(크로스 도메인)에 요청을 보낼 때 

요청에 credential 정보를 담아서 보낼지를 결정하는 항목이라고 한다.

 

여기서, credential 정보가 포함되어 있는 요청은 아래 두 가지 경우를 의미한다.

  1. cookie를 첨부해서 보내는 요청
  2. header에 Authorizationo 항목이 있는 요청

따라서, 보내고자 하는 요청이 위 두 가지 항목 중 하나라도 포함한다면 

withCredentials 옵션을 true로 줘야했던 것이다.

 

axios뿐만 아니라 fetch에서도 마찬가지인데 

fetch("https://example.com:1234/users", {
  credentials: "include",
})

이런식으로 세팅을 할 수 있나보다. (테스트 안해봄)

 

credential 관련 정보는 아래 블로그에서 참고했다.

 

https://junglast.com/blog/http-ajax-withcredential

 

HTTP Ajax 요청시 사용하는 withCredentials 옵션의 의미

Ajax 요청에서 'credential'의 의미

junglast.com

 

만약 실제 서비스를 한다면 위에서 origin에 클라이언트 서버 주소를 명시한거처럼

.env를 통해 명시하는게 좀 더 안전한 서비스 운영 방법이 될 것으로 보인다.

 

공부중에 이렇게 헤딩해서 다행이지 바쁠 때 이런 현상을 겪었으면 

Insomnia 상에서는 잘 되니까 조금만 뭔가 변경하면 될 것 같은데..? 라는 생각과 함께

여유가 사라져 몇 시간은 박았을 것 같다.. 

 

아무튼 Nest.js를 겪으며 또 새롭게 겪는 문제들이 많은데

이렇게 시행착오를 겪으며 배우는 과정이 제일 재밌는 것 같다.

 

추가사항

GET 요청에 대해서도 비슷한 상황을 겪을 수 있는데

POST 요청과는 withCredentials 옵션을 적용하는 위치가 다르니 아래 글을 통해 해결하길 바란다.

 

https://4sii.tistory.com/446

 

[Nest.js][CORS] GET 요청에서 cookie를 전달받지 못하는 문제

개요 https://4sii.tistory.com/421 [Nest.js][CORS] cookie를 전달받지 못하는 문제 개요 클라이언트 서버 localhost:3000 을 react로 운영중이고 백엔드 서버 localhost:8080 을 Nest.js로 운영중인 상황이다. controller @Post

4sii.tistory.com

728x90