헤더에 쓸 카테고리 데이터들을 받아오기 위해 서버에 카테고리 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 에러를 만나게 된다.
같은 출처다 = 프로토콜, 도메인, 포트가 같다
- 프로토콜 : https | http
- 도메인(Hostname): myshop.com
- 출처(Origin): https://www.myshop.com
다시 말해, ‘출처가 교차한다(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 에러를 방지할 수 있다.
✅ 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
'TIL' 카테고리의 다른 글
| 리버스 프록시, 단위 테스트 (1) | 2024.03.22 |
|---|---|
| 비관적 업데이트(pessimistic)? 낙관적(optimistic) 업데이트? (0) | 2024.03.14 |
| SQL 에러 errno: 121 "Duplicate key on write or update" , ERROR 1061: Duplicate key name ~~ (0) | 2024.01.12 |
| Error: listen EADDRINUSE: address already in use [PORT] (1) | 2023.12.29 |
| Error Cannot find module 'express' & your cache folder contains root-rowned files, due to a bug ~ (0) | 2023.12.14 |