본문 바로가기
TIL

AxiosError: Network Error / CORS 에러

by 케이리케리 2024. 2. 29.

헤더에 쓸 카테고리 데이터들을 받아오기 위해 서버에 카테고리 api를 요청했다.

그런데 axios 에러 중 네트워크 에러가 발생했다.

 

 

콘솔 창을 확인해보니

 

Access to XMLHttpRequest at 'http://localhost:1225/category' from origin 'http://localhost:3003' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

 

CORS 정책에 의해 브라우저(클라이언트) origin에서 보낸 요청이 막혔다. 'Access-Control-Allow-Origin' 헤더가 요청된 리소스(서버)에 없다. 라고 말해주고있다.

 

서버에 'Access-Control-Allow-Origin' 헤더를 추가해주면 되겠네?

단순히 헤더 설정을 하기 전에 왜 CORS에 대해 먼저 알아야한다.

 

CORS는 무엇인가?

CORS(Cross-Origin Resource Sharing, 교차 출처 리소스 공유)

출처: 토스 페이먼츠

출처(Origin)는 프로토콜 + 도메인(호스트 이름) + 포트 세 요소로 구성되고, 이 중 하나라도 다르면 CORS 에러를 만나게 된다.

같은 출처다 = 프로토콜, 도메인, 포트가 같다

 

다시 말해, 출처가 교차한다(cross origin)’ = 리소스를 주고받으려는 ‘두 출처가 서로 다르다’

CORS를 설정한다는 건 ‘출처가 다른 서버 간의 리소스 공유’를 허용한다는 의미이다.

 

서로 다른 출처끼리 자유롭게 소통을 하는게 왜 위험한가?


토큰, 쿠키와 같이 민감한 사용자 정보가 브라우저에 저장되는데, 제약이 없는 상황에서 해커가CSRF(Cross-Site Request Forgery)XSS(Cross-Site Scripting) 등의 방법을 이용해서 사용자개인 정보를 탈취할 수 있기때문이다.

그래서 서로 다른 서버 리소스는 공유하지 않는 브라우저 정책인 SOP(Same-Origin Policy, 동일 출처 정책)이 필요하다.

 

CORS는 서로 다른 출처끼리 리소스를 요청/응답하려고해서 발생한 문제니까
같은 출처 안에서만 리소스를 주고받으면 되지 않을까? 

 

라고 생각할 수 있지만

지금처럼 로컬에서 개발할 때 포트번호가 다른 상태에서 개발을 하는 경우가 많고,

웹페이지에서 외부 서버(다른 출처)의 리소스를 가져와 사용하는 것이 흔한 일이라 CORS를 만나는게 불가피하다.

 

그래서 서로 다른 출처라도 리소스 요청, 응답(=통신)을 허용할 수 있도록 하는 CORS가 필요하다

 

해결 방법

1.  서버에서 Access-Control-Allow-Origin 응답 헤더 세팅하기

서버에서 Access-Control-Allow-Origin 헤더를 설정해서 요청을 수락할 출처를 명시적으로 지정할 수 있다.

이 헤더를 세팅하면 출처가 다르더라도 클라이언트의 리소스 요청을 허용하게 된다.

 

✅  cors 모듈 사용 방법

npm install cors
const express = require('express');
const cors = require('cors');
const app = express();

// 모든 출처에 대해 CORS를 허용할 경우
app.use(cors());

// 특정 출처에 대해서만 CORS를 허용할 경우
app.use(
  cors({
    origin: 'http://localhost:3003', // 허용할 출처
    methods: 'GET, POST, PUT, DELETE',
    credentials: true, /// 사용자 인증이 필요한 리소스(쿠키 ..등) 접근
  })
);

const PORT = process.env.PORT || 1225;
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});

 

✅  Node.js에 직접 헤더에 명시

const express = require('express');

const app = express();

// 미들웨어를 사용하여 CORS를 허용할 수도 있습니다.
app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', 'http://localhost:3003');
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
  res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  res.header('Access-Control-Allow-Credentials', true);
  next();
});


const PORT = process.env.PORT || 1225;
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});
  • Access-Control-Allow-Origin : 서버에 요청할 수 있는 Origin
  • Access-Control-Allow-Methods : 허용되는 HTTP 메서드
  • Access-Control-Allow-Headers : 서버에 요청할 때 원본이 사용할 수 있는 HTTP 헤더
  • Access-Control-Allow-Credentials : 쿠키/Authorization 헤더에 설정하는 토큰 값 주고받기 허용

 

2. 프록시 서버 사용하기

웹 애플리케이션이 리소스를 직접적으로 요청하는 대신, 프록시 서버를 사용하여 웹 애플리케이션에서 리소스로의 요청을 전달하는 방법도 있다.

이 방법을 사용하면, 웹 애플리케이션이 리소스와 동일한 출처에서 요청을 보내는 것처럼 보여 CORS 에러를 방지할 수 있다.

  ✅ http-proxy-middleware

  ✅ package.json에 proxy추가 (create-react-app으로 프로젝트를 생성한 경우) 

 

 

 

나는 cors 모듈을 사용했다. 정상적으로 작동하는 것을 확인 할 수 있다.

헤더 이미지
서버에서 받아오는 데이터 확인

 

 

참고자료 

https://bobbyhadz.com/blog/react-axios-network-error-stack-trace

 

Axios Network Error when making HTTP request [Solved] | bobbyhadz

To solve the "Axios Network Error", make sure your server sends back all the necessary CORS headers to enable requests from a different origin.

bobbyhadz.com

https://blog.tossbusiness.com/articles/dev-3?utm_source=docs&utm_medium=glossary&utm_campaign=cors

 

결제창에서 CORS 대응하기

콘솔창에서 CORS policy 에러 만나본 적 있으시죠? 이번 아티클에서는 CORS를 알아보고 토스페이먼츠 결제창에서 CORS 에러를 만났을 때 해결하는 방법도 알아봅니다.

blog.tossbusiness.com

https://inpa.tistory.com/entry/WEB-%F0%9F%93%9A-CORS-%F0%9F%92%AF-%EC%A0%95%EB%A6%AC-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95-%F0%9F%91%8F