Node.js, Express.js 에서 CORS 이해와 설정 방법
Taeyoung • 9개월 전 작성
CORS(Cross-Origin Resource Sharing)는 웹 페이지가 다른 도메인의 리소스를 요청하는 것을 가능하게 하는 웹 보안 표준입니다.
웹 브라우저는 기본적으로 보안 상 Same-Origin Policy를 따르기 때문에, 현재 웹 페이지와 다른 출처에서 오는 리소스에 대한 요청은 제한됩니다.
이 때문에, 웹 페이지가 다른 도메인의 API를 요청하려면 CORS 설정이 필요하게 됩니다.
Node.js에서의 CORS 설정
Node.js에서 CORS 설정을 위해 'cors' 라이브러리를 사용할 수 있습니다. 먼저, 이 라이브러리를 설치해야 합니다.
npm install cors
가장 기본적인 CORS 설정
모든 도메인에서 들어오는 요청을 허용하도록 설정합니다.
하지만 모든 도메인에서 들어오는 요청을 허용하게 될 경우, 문제가 발생할 수 있기 때문에 세부 설정을 진행해야합니다.
문제란, 다른 도메인에서 리소스를 요청하는 경우를 얘기합니다.
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors());
CORS 초급 설정
보다 세부적인 설정을 하려면, 'cors' 함수에 옵션 객체를 전달할 수 있습니다.
'origin' 속성에 허용하고 싶은 도메인을 지정할 수 있습니다. 또한, 'credentials' 속성을 'true'로 설정하면, 이 도메인에서의 요청이 쿠키와 같은 자격 증명을 포함하도록 허용합니다.
이렇게 설정하면, 브라우저가 서버에 요청을 보낼 때 'Access-Control-Allow-Origin'과 'Access-Control-Allow-Credentials' 헤더가 추가되어, CORS 정책을 준수하게 됩니다.
이상으로 Node.js에서 CORS를 설정하는 방법에 대해 알아봤습니다. 이 기능을 활용하면, 안전하게 다른 도메인의 리소스를 요청하고 사용할 수 있습니다.
app.use(
cors({
origin: 'http://localhost:3300',
credentials: true,
}),
);
CORS 세부 설정
- origin: 클라이언트 사이트의 URL을 지정합니다. 이 경우, http://localhost:3300에서 오는 요청만 허용됩니다.
- methods: 허용할 HTTP 메서드를 지정합니다. 이 경우, GET과 POST 메서드를 사용하는 요청만 허용됩니다.
- allowedHeaders: 서버가 수락할 수 있는 요청 헤더를 지정합니다. 이 경우, 요청 헤더에 Content-Type과 Authorization이 포함되어야 합니다.
- credentials: 응답 헤더에 Access-Control-Allow-Credentials를 추가합니다. 이 경우, 요청이 쿠키 및 인증 정보를 포함할 수 있습니다.
- maxAge: 사전 전달 요청의 결과를 캐시할 시간을 초 단위로 지정합니다. 이 경우, 사전 전달 요청의 결과는 600초 동안 캐시됩니다.
const express = require('express');
const cors = require('cors');
const app = express();
app.use(
cors({
origin: 'http://localhost:3300',
methods: ['GET', 'POST'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true,
maxAge: 600,
}),
);
allowedHeaders 예시
try문 내부에 headers 설정을 확인할 수 있습니다.
async function sendData() {
try {
const response = await fetch('http://localhost:3300/sample', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'token sample',
},
body: JSON.stringify({
title: 'title',
description: 'description',
}),
})
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}
const data = await response.json()
console.log(data)
} catch (error) {
console.error('Error:', error)
}
}
sendData()
credentials 예시
credentials: 'include' 설정하면 클라이언트는 쿠키를 요청에 포함시킬 수 있습니다.
반대로 'omit'으로 설정하면, 클라이언트는 쿠키를 요청에 포함시키지 않습니다.
서버에서 credentials: true를 설정했다고 반드시 자격 증명을 포함해야 하는 건 아닙니다. 반대로 credentials가 false경우에는 자격 증명을 포함 할 수 없습니다.
fetch('http://localhost:3300/sample', {
method: 'GET',
credentials: 'include',
})
fetch('http://localhost:3300/sample', {
method: 'GET',
credentials: 'omit',
})
maxAge
maxAge를 사용하면 동일한 요청에 대해 서버에게 불필요한 요청을 막는 시간값입니다.
즉 Preflight 요청은 실제 요청을 보내기 전에 보내지는 요청으로, 서버가 해당 요청을 처리할 수 있는지 확인하고 HTTP OPTIONS 메서드를 사용합니다.
maxAge는 캐시 시간을 뜻하고 위 예시에서 600을 입력했으니까, 10분 동안 요청에 대한 결과를 가지고 있으니, 다시 요청할거면 10분동안 요청을 보낼 수 없게 막아버립니다.
이렇게하면 동일한 요청에 대해 서버에게 불필요한 preflight 요청을 줄일 수 있습니다.
하지만 maxAge를 사용하더라도 클라이언트는 캐시를 무시하고 preflight 요청을 계속 다시 보낼 수 있습니다.