Node.js 및 React 애플리케이션에서 CORS 오류를 해결하는 방법

22498 단어 nodereactcors
이전 기사에서 how to deploy a Node.js application to Heroku에 대해 설명했습니다. 이 튜토리얼에서는 생성된 끝점을 사용하고 React 프로젝트에서 사용할 수 있는지 확인합니다.

프로젝트 설정



다음 명령을 사용하여 React 프로젝트를 생성해 보겠습니다.

npx create-react-app react-cors


이제 다음 코드를 사용하여 App.js를 업데이트합니다.

import { useEffect, useState } from "react"
import "./App.css"

function App() {
  const [message, setMessage] = useState("")
  useEffect(() => {
    fetch("https://nodejs-using-github.herokuapp.com/")
      .then(response => response.json())
      .then(data => {
        setMessage(data.message)
      })
      .catch(err => console.log(err))
  }, [])
  return <div className="App">{message ? message : "Loading.."}</div>
}

export default App


여기에는 message 라는 로컬 상태가 있으며 이를 사용자에게 보여줍니다. 메시지가 비어 있으면 로드 텍스트와 함께 표시합니다. 컴포넌트가 마운트되면(useEffect) API 엔드포인트를 호출하고 메시지를 가져옵니다.

이제 이것을 실행하고 작동하는지 봅시다:

npm start




"Loading.."텍스트만 표시되고 메시지가 로드되지 않는 것을 볼 수 있습니다. 페이지를 검사하고 콘솔을 보면 다음 오류가 표시됩니다.
Access to fetch at 'https://nodejs-using-github.herokuapp.com/' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.


다음 섹션에서는 CORS가 무엇이고 이 오류를 수정하는 방법을 살펴보겠습니다.

CORS(Cross-Origin Resource Sharing)란 무엇입니까?



CORS는 Cross-Origin Resource Sharing 을 의미하며, 이는 서버가 모든 도메인 요청이 이루어질 수 있는 브라우저를 알려주는 데 도움이 되는 HTTP 헤더 기반 메커니즘입니다(동일한 도메인 제외).

즉, 우리의 경우 https://nodejs-using-github.herokuapp.com/ 에서 호스팅되는 Node.js 서버는 http://localhost:3000 에서 요청이 이루어질 수 있음을 브라우저에 알리지 않습니다.

이런 일이 발생하면 앞에서 본 것처럼 브라우저에서 오류가 발생합니다.

왜 CORS(Cross-Origin Resource Sharing)인가?



다음 질문은 왜 우리에게 이 메커니즘이 필요한가 하는 것입니다. 은행 계좌나 소셜 미디어 웹사이트에 로그인한 다음 악성 웹사이트를 방문한다고 상상해 보십시오.
이 악성 웹사이트는 백그라운드에서 일부 스크립트를 실행하여 개인 정보를 얻기 위해 은행 또는 소셜 미디어에 대한 API 호출을 할 수 있습니다.

이를 방지하기 위해 브라우저는 악성 웹사이트에서 은행 또는 소셜 미디어 서버에 대한 요청을 할 수 있는지 확인하고 CORS 오류를 발생시킵니다.

따라서 CORS는 신뢰할 수 있는 타사(서로 다른 출처/도메인) 간에 특정 리소스를 공유하기 위해 존재하므로 Cross-Origin Resource Sharing이라는 이름이 있습니다.

Node.js에서 CORS를 구성하는 방법



CORS가 무엇이고 왜 필요한지 명확하게 알고 있으므로 Node.js 애플리케이션에서 CORS를 활성화하는 방법을 살펴보겠습니다.

Node.jscode from this repo를 복제할 수 있습니다. 프로젝트가 복제되면 코드 편집기에서 열고 cors package을 설치합니다.

npm i cors


이제 index.js를 열고 다음 코드로 업데이트합니다.

const express = require("express")
const cors = require("cors")
const app = express()
const port = process.env.PORT || 3000

const whitelist = ["http://localhost:3000"]
const corsOptions = {
  origin: function (origin, callback) {
    if (!origin || whitelist.indexOf(origin) !== -1) {
      callback(null, true)
    } else {
      callback(new Error("Not allowed by CORS"))
    }
  },
  credentials: true,
}
app.use(cors(corsOptions))

app.get("/", (req, res) => {
  res.send({ message: "Hello World!" })
})

app.listen(port, () => {
  console.log(`Example app listening at Port: ${port}`)
})


여기에서 원본(클라이언트의 도메인)이 화이트리스트에 있는지 확인한 다음 클라이언트에게 요청을 할 수 있음을 알립니다. 목록에 없으면 클라이언트가 이 서버에 CORS 요청을 할 수 없다는 오류가 발생합니다.

The domain should not have any trailing slashes (/)



deploy the changes to Heroku 이것이 작동하는지 확인할 수 있습니다.

이제 페이지를 새로고침하면 메시지를 볼 수 있습니다.



또한 Access-Control-Allow-Origin라는 응답 헤더가 http://localhost:3000 값으로 추가된 것을 볼 수 있습니다.

CORS 도메인을 구성 가능하게 만들기



연결할 클라이언트 원본이 여러 개인 경우 구성 가능하게 하려면 환경 변수를 사용하면 됩니다.

const express = require("express")
const cors = require("cors")
const app = express()
const port = process.env.PORT || 3000

const domainsFromEnv = process.env.CORS_DOMAINS || ""

const whitelist = domainsFromEnv.split(",").map(item => item.trim())

const corsOptions = {
  origin: function (origin, callback) {
    if (!origin || whitelist.indexOf(origin) !== -1) {
      callback(null, true)
    } else {
      callback(new Error("Not allowed by CORS"))
    }
  },
  credentials: true,
}
app.use(cors(corsOptions))

app.get("/", (req, res) => {
  res.send({ message: "Hello World!" })
})

app.listen(port, () => {
  console.log(`Example app listening at Port: ${port}`)
})


로컬에서 환경 변수 테스트



환경 변수를 로컬에서 테스트하려면 dotenv라는 패키지를 설치할 수 있습니다.

npm i dotenv


이제 도메인이 있는 프로젝트의 루트 디렉터리에 .env라는 파일을 만듭니다.

CORS_DOMAINS = http://localhost:3000, http://localhost:3001, https://example.com

index.js 패키지를 사용하도록 업데이트dotenv:

const express = require("express")
const cors = require("cors")
const app = express()
const port = process.env.PORT || 3000

if (process.env.NODE_ENV !== "production") {
  require("dotenv").config()
}

const domainsFromEnv = process.env.CORS_DOMAINS || ""

const whitelist = domainsFromEnv.split(",").map(item => item.trim())

const corsOptions = {
  origin: function (origin, callback) {
    if (!origin || whitelist.indexOf(origin) !== -1) {
      callback(null, true)
    } else {
      callback(new Error("Not allowed by CORS"))
    }
  },
  credentials: true,
}
app.use(cors(corsOptions))

app.get("/", (req, res) => {
  res.send({ message: "Hello World!" })
})

app.listen(port, () => {
  console.log(`Example app listening at Port: ${port}`)
})


여기서 우리는 .env 파일이 비프로덕션 환경에서만 로드되도록 했습니다. 프로덕션용 .env 파일이 아닌 서버 호스트에 구성을 저장하는 것이 좋습니다.

Remember to add .env* to the .gitignore file so that you don't accidentally push them to the repo.



heroku에서 환경 파일 구성



최신 코드를 사용하여 heroku 설정에서 환경 파일을 구성할 수 있습니다.



프로젝트 설정으로 이동하여 "구성 변수 표시"를 클릭합니다. 이제 여기에 키와 값을 제공하고 "추가"를 클릭할 수 있습니다.



추가되면 변경 사항을 푸시하고 변경 사항이 작동하는지 확인할 수 있습니다.

좋은 웹페이지 즐겨찾기