본문 바로가기
개인 공부/프론트

[React] CORS 에러

by 육츠 2024. 10. 16.
Contents 접기

참고 블로그1 : Inpa Dev 

 

🌐 악명 높은 CORS 개념 & 해결법 - 정리 끝판왕 👏

악명 높은 CORS 에러 메세지 웹 개발을 하다보면 반드시 마주치는 멍멍 같은 에러가 바로 CORS 이다. 웹 개발의 신입 신고식이라고 할 정도로, CORS는 누구나 한 번 정도는 겪게 된다고 해도 과언이

inpa.tistory.com

 

참고 블로그 2: 호두파파

 

(React) React App에서 CORS 이슈 해결하기

CORS가 무엇인지, CORS 이슈를 어떻게 극복할지 알아보자

velog.io

그리고 gpt..

 

웹 개발자라면 한 번 쯤 겪는다는,, CORS 에러,, 이렇게 겪어보다,, 
공부 하는대로 정보 추가 할 예정 --> 추가 완료

 

CORS 에러 란?

교차 출처 리소스 공유 Cross-Origin Resource Sharing 

브라우저가 다른 도메인, 프로토콜 또는 포트에서 리소스를 요청할 때 보안상의 이유로 제한하는 기능을 말한다. 즉 브라우저가 자신의 출처가 아닌 다른 어떤 출처(도메인, 프로토콜, 포트)로부터 자원을 로딩하는 것을 허용하도록 서버가 허가 해주는 매커니즘을 말한다.

출처 ORIGIN
동일한 스킴(http)와 호스트 이름(example.com)을 갖고 있음

출처는 동일합니다.
http://example.com/app1/index.html

http://example.com/app2/index.html


다른 파일 경로는 중요하지 않습니다.
서버는 기본적으로 포트 80을 통해 HTTP 콘텐츠를 전달

출처는 동일합니다.
http://example.com:80

http://example.com


서로 다른 포트를 사용하기 때문에 동일한 출처가 아닙니다.

http://example.com
http://example.com:8080

서로 다른 스킴을 사용

동일한 출처가 아닙니다.
http://example.com/app1
https://example.com/app2
서로 다른 호스트 이름을 사용

동일한 출처가 아닙니다.
 

http://example.com
http://www.example.com
http://myapp.example.com

** 참고 블로그 내 설명

 

해결방법

1. 크롬 확장 프로그램 사용하기

2. 프록시 서버 이용하기

3. 서버에서 Access-Control-Allow-Origin 헤더 세팅하기

오류를 보면 "No 'Access-Control-Allow-Origin' header is present on the requested resource." 라고 쓰여 있는 걸 볼 수 있다.

 

3-1. 백엔드 프록시 설정 (개발 환경에서)

사용한 API는 네이버맵 API 다. (Geocoding 사용)

pakage.json 에 proxy 를 추가하여 넣는다.
이 proxy 는 Origin에서 API 요청이 나가는 것을 막고, react 개발 서버가 대신 요청을 전송하게 된다.

{* 변경 전 *}
const geo = `https://naveropenapi.apigw.ntruss.com/map-geocode/v2/geocode?query=${address}`;

{* 변경 후 *}
const geo = `/map-geocode/v2/geocode?query=${address}`;

 

변경 전 오류

변경 후 오류

 

CORS 에러가 해결된 것을 볼 수 있다.

 


(gpt가 알려준 건 이 방법인데, 아직 배포는 못 해서 이게 되는지는 모르겠다.)

3-2. CORS 문제를 백엔드에서 해결 (배포 환경에서)

프로젝트와 같은 선상에 proxy 관련 디렉토리를 만든 후 디렉토리로 이동

package.json 생성 후 express, cors 모듈 설치한다.(Node.js 프로젝트 초기화 및 패키지 설치)

npm init -y 
npm install express cors node-fetch

 

필요한 종속성을 package.json에 추가한다. (여기서 nodemon 도 같이 설정해 놓으면 좋을 것 같다)

{
  "scripts": {
    "start": "node server.js"  // server.js가 서버 파일이라면
  }
}

 

.env 파일 만들기

React 파일에서 만들었던 .env 파일을 가져오면 되는데, 여기선 이름만 'REACR_APP_'을 제거하면 된다.

아래는 내 예시이다.

API_Naver_ID = []
API_Naver_Key = []
CLIENT_URL = http://localhost:[]

 

(선택) CommonJS >> ES 모듈 변경

const express = require('express');
const fetch = require('node-fetch');
const cors = require('cors');

// .env 파일에서 환경 변수를 불러오기
require('dotenv').config();
import express from 'express';
import cors from 'cors';
import fetch from 'node-fetch';
import dotenv from 'dotenv';

dotenv.config();

const app = express();
const PORT = 4000;

 

주로 서버의 port 는 5000 이라고한다.  하지만, 나는 5000 port 에서 따로 사용되는 것이 있어 4000으로 변경했다.

 

만약 포트 충돌이 일어난다면 아래 코드로 확인하고 삭제하면 되는데, 되도록이면 다른 포트를 파는 걸 추천한다.

// 확인
lsof -i :[포트 번호]

// 삭제
kill -9 [PID 번호]

 

// app.use(cors({ origin: '*' })); // 모든 출처에서 오는 요청을 허용 (보안상 좋지 않음)

// CORS 설정을 더 제한적으로 변경
app.use(cors({ origin: process.env.CLIENT_URL || 'http://localhost:3000' }));


// 루트 경로 핸들러
app.get('/', (req, res) => {
    res.send('Welcome to the API server'); // 응답 추가
});

// 네이버 API 프록시
app.get('/api/naver', async (req, res) => {
    const address = req.query.query;
    res.send(address);
    
    const geoID = process.env.API_Naver_ID;
    const geoKey = process.env.API_Naver_KEY;

    const encodedAddress = encodeURIComponent(address);
    const response = await fetch(https://naveropenapi.apigw.ntruss.com/map-geocode/v2/geocode?query=${encodedAddress}, {
        headers: {
            'X-NCP-APIGW-API-KEY-ID': geoID,
            'X-NCP-APIGW-API-KEY': geoKey,
        },
    });

    const data = await response.json();
    res.json(data);
});


app.listen(PORT, () => {
    console.log(`Server is running on http://localhost:${PORT}`);
});