Skip to content
Jwoo Blog
LinkedInGitHub

NestJS - CORS와 Cookie 설정하기!

NestJS, CORS, cookie6 min read

NestJS - main.ts

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { Logger } from '@nestjs/common';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
...
// cors 설정
app.enableCors({
origin: [process.env.FRONT_URL],
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
credentials: true,
});
// cookie 설정
app.use(cookieParser());
...
const port = process.env.BACK_PORT || 9999;
await app.listen(port);
Logger.log(`Server running on ${port}`);
}
bootstrap();

Cookie

npm install cookie-parser @types/cookie-parser
app.use(cookieParser());

다음과 같이 cookie-parser 패키지를 다운받고 쿠키 설정을 해주면, 브라우저로부터 받은 쿠키를 분석할 수 있게 된다.

만약 프록시 서버를 사용하여 CORS 설정을 사용할 필요가 없다면, 위의 두줄만으로 쿠키를 쓸 수 있다. 그러나 만약 CORS 설정을 해주었다면, 쿠키를 사용하기 위해서는 추가적인 옵션 설정이 필요하다.


CORS

app.enableCors({
origin: [process.env.FRONT_URL],
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
credentials: true,
});

사실 옵션없이 app.enableCors() 만 사용해도 CORS 에러 자체는 해결이 가능하다.

하지만 위에서 언급했던 쿠키 사용을 위해 origincredentials 옵션을 사용해주었다. 쿠키를 사용하고 싶다면 credentialtrue 로 해주고, origin 은 쿠키를 받아올 주소를 적어준다.

origin 옵션은 배열도 가능하므로, 여러 주소를 한번에 넣을 수도 있다. 다만 주의할 점은 쿠키를 사용하기 위해서는 '*'로 설정해선 안된다는 점이다. 그 이유는 아래에 기술한다.


withCredentials

마지막으로 프론트에서도 백엔드에 쿠키를 사용하는 api, 즉 인증정보를 포함한 요청을 할 때마다 withCredentials 옵션을 사용해야한다. (서버 설정 다해두고 이걸 안해줘서 삽질한 기억이 있다...)

...
await axios
.post(
"/api/users/me",
{
...
},
{ withCredentials: true }
)
...


CORS 동작 시나리오

CORS의 동작 방식은 3가지가 있다. 그 중 위에서 서술한 cookie와 같이 인증 정보가 포함된 요청은 3가지 중 Credentialed Request와 관련이 깊다. 3가지 시나리오를 간단히 소개하겠다.


Preflight Request

웹개발을 할때 가장 많이 만나게 되는 방식이다. 해당 시나리오에서 브라우저는 본 요청을 바로 보내지 않고 브라우저가 예비 요청을 보내 스스로 안전한 요청인지 확인한 후 본 요청을 보낸다. 예비 요청은 http 메소드 중 OPTIONS 메소드를 사용한다. 이때 예비 요청의 성공여부보단 응답 헤더의 Access-Control-Allow-Origin 값이 더 중요하다.


Simple Request

해당 시나리오는 예비 요청 없이 본 요청을 바로 보낸 다음 브라우저가 Access-Control-Allow-Origin 을 보고 판단하는 방식이다. 하지만 이렇게 본 요청을 바로 보내는 것은 꽤나 까다로운 조건이 필요하다.


Credentialed Request

마지막은 인증된 요청에 대한 시나리오로, 교차 출처 통신에서 보안을 강화하고 싶을 때 사용하는 방법이다. 이제까지 우리가 다룬 cookie를 사용할 때 쓴다.

기본적으로 브라우저가 제공하는 리소스 요청 API인 XMLHttpRequest 객체나 fetch API는 별도의 옵션 없이 브라우저의 쿠키 정보나 인증과 관련된 헤더를 함부로 요청에 담지 않는다. 이때 요청에 인증과 관련된 정보를 담을 수 있게 해주는 옵션이 credentials 이다.  credentials 옵션에는 3가지가 있다.

옵션 값설명
same-origin같은 출처 간 요청에만 인증 정보를 담을 수 있다
include모든 요청에 인증 정보를 담을 수 있다
omit모든 요청에 인증 정보를 담지 않는다

만약 same-origin이나 include를 사용하여 요청에 인증정보를 포함하게 된다면, 브라우저는 Access-Control-Allow-Origin 뿐만 아니라 다른 항목도 좀 더 까다롭게 확인한다.

요청에 인증정보가 담길 때에는 서버의 응답 헤더 Access-Control-Allow-Origin 필드에 *(와일드 카드) 를 사용하는 것도 금지되며, 어떤 출처를 허용할 것인지 정확히 명시해두어야한다. 그리고 응답 헤더에 반드시 Access-Control-Allow-Credentials: true 가 존재해야한다.


간단한 회고

CORS 동작 방식에 대한 이론을 좀 더 빨리 알았더라면, 그 때 withCredentials 때문에 삽질할 일은 줄 일 수 있었을텐데... 하는 생각이 들었다. 다시금 CS 지식에 대한 중요성을 깨닫는다..!


참고

🍪 CORS 쿠키 전송하기 (withCredentials 옵션)
NestJS | CORS 설정
NestJS - 17. 쿠키 다루기(JWT토큰)
[Network] What is CORS
[보안] CORS 란? CORS 에러란?
CORS는 왜 이렇게 우리를 힘들게 하는걸까?
쿠키(cookie), 서버 - 클라이언트 set-cookie 에러 사항들