Notice
Recent Posts
Recent Comments
Link
«   2025/03   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
Archives
Today
Total
관리 메뉴

성빈

CORS 에러 본문

React

CORS 에러

성빈나 2024. 8. 6. 17:47

 

개발도중, API에 접근하려하자 CORS 정책에 의해 막혔다는 에러가 발생했다. 

 

 

시작하기에 앞서, CORS에 대해 학습하고자 한다.

 

🔺 CORS(Cross-Origin Resource Sharing)

  • 교차 출처 리소스 공유
  • 도메인이 다른 서버끼리 리소스를 주고 받을 때 보안을 위해 설정된 정책

 

일반적으로, 프론트엔드와 백엔드가 협업하면서 각자 따로 서버를 띄우게 되었을 경우에 발생한다. 서로 다른 React 서버(3000포트)와 Springboot(8080포트) 서버가 리소스를 주고 받으려 한다면 포트번호가 달라 서로 다른 출처로 판단되어 CORS 위반 에러가 발생한다.

 

📌 Origin(출처)

그렇다면 같은 출처와 다른 출처를 어떻게 구분할 수 있을까?

Protocal + Host + Port 가 같으면, 동일 출처(Origin)이라고 한다.

 

URL 구성요소

 

✅ 각 웹에서 사용하는 HTTP(80포트), HTTPS(443포트) 프로토콜의 기본포트번호가 정해져있기 때문에 출처 내의 포트 번호는 생략 가능한데, 출처에 포트 번호가 명시적으로 포함되어 있다면 이 포트번호까지 모두 일치해야 같은 출처라고 인정된다.

 

 

🔺 CORS 정책은 언제 검사할까?

출처 : https://evan-moon.github.io/2020/05/21/about-cors/#출처origin가-무엇인가요

 

  • 여기서 중요한 점은 출처를 비교하는 로직이 서버에 구현된 것이 아니라 브러우저에 구현되어있다는 것이다.
  • 우리가 CORS 정책을 위반하는 리소스 요청을 하더라도 해당 서버가 같은 출처에서 보낸 요청만 받겠다는 로직을 가지고 있는 경우가 아니라면 서버는 정상적으로 응답을 하고, 이후 브라우저가 이 응답을 분석해서 CORS 정책 위반이라고 판단되면 그 응답을 사용하지 않고 그냥 버린다.
  • CORS는 브라우저의 구현 스펙에 포함되는 정책이기 때문에, 브라우저를 통하지 않고 서버 간 통신을 할 때는 이 정책이 적용되지 않는다.

 

🔺 CORS의 동작 시나리오 3가지

 

CORS는 세 가지의 시나리오에 따라 변경되기 때문에 내 요청이 어떤 시나리오에 해당되는지 잘 파악한다면 CORS 정책 위반으로 인한 에러를 고치기 쉬워질 것이다.

 

✅ Preflight Request

  • 일반적으로 우리가 웹 어플리케이션을 개발할 때 가장 많이 마주치는 시나리오
  • 브러우저는 요청을 한번에 보내지 않고 예비 요청(Preflight)과 본 요청으로 나누어서 서버에 전송한다.
    • 예비 요청의 역할 → 본 요청을 보내기 전에 브라우저 스스로 이 요청을 보내는 것이 안전한지 확인한다.
우리가 자바스크립트의 fetch API를 사용하여 브라우저에게 리소스를 받아오라는 명령을 내리면 브라우저는 서버에게 예비 요청을 먼저 보내고, 서버는 이 예비 요청에 대한 응답으로 현재 자신이 어떤 것들을 허용하고, 어떤 것들을 금지하고 있는지에 대한 정보를 응답 헤더에 담아서 브라우저에게 다시 보내주게 된다.
이후 브라우저는 자신이 보낸 예비 요청과 서버가 응답에 담아준 허용 정책을 비교한 후, 이 요청을 보내는 것이 안전하다고 판단되면 같은 엔드포인트로 다시 본 요청을 보내게 된다. 이후 서버가 이 본 요청에 대한 응답을 하면 브라우저는 최종적으로 이 응답 데이터를 자바스크립트에게 넘겨준다.
  • CORS 정책 위반으로 인한 에러는 예비 요청의 성공 여부와 관계 없다.
  • 예비 요청의 성공/실패 여부가 중요한 것이 아니라, “응답 헤더에 유효한 Access-Control-Allow-Origin값이 존재하는지”가 중요하다.

 

 

✅ Simple Request

 

Simple Request(단순 요청)은 예비 요청 없이 본 요청만을 보내고, 서버가 이에 대한 응답의 헤더에 Access-Control-Allow-Origin 과 같은 값을 보내주면 그때 브라우저가 CORS 정책 위반 여부를 검사하는 방식이다.

  • Preflight Request와 전체적인 로직 자체는 같되, 예비 요청의 존재 유무만 다르다.
  • Credential이 없는 요청의 경우 를 통해 브라우저의 Origin에 상관없이 모든 Origin 을 허용할 수 있다.

특정 조건을 만족하는 경우에만 예비 요청을 생략할 수 있다.

(까다로운 조건이기 때문에, 실제로 모두 충족시키기에는 어려움이 있다.)

 

단순 요청을 사용할 수 있는 경우
1. 요청의 메소드는 GET, HEAD, POST 중 하나여야 한다.
2. Request Header에는 다음 속성만 허용 Accept, Accept-Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width, Width
3. 만약 Content-Type를 사용하는 경우에는 application/x-www-form-urlencoded, multipart/form-data, text/plain만 허용된다.
4. 요청에 사용된 XMLHttpRequestUpload 객체에는 이벤트 리스너가 등록되어 있지 않다. 이들은 XMLHttpRequest.upload 프로퍼티를 사용하여 접근한다.
5. 요청에 ReadableStream 객체가 사용되지 않는다.

 

✅ Credentialed Request

  • 인증된 요청을 사용하는 방법
  • 다른 출처 간 통신에서 좀 더 보안을 강화하고 싶을 때 사용하는 방법이다.
  • credentials 옵션을 사용해 요청에 인증과 관련된 HTTP Cookie와 HTTP AUthentication 정보를 담을 수 있게 해준다.
  • Access-Control-Allow-Origin에는 모든 요청을 허용하는 *를 사용할 수 없으며, 명시적인 URL이어야 한다.

 

 

🔺 CORS를 해결할 수 있는 방법

 

방법 1️⃣.  Access-Control-Allow-Origin 세팅하기

  • CORS 정책 위반으로 인한 문제를 해결하는 가장 대표적인 방법
  • 정석대로 서버에서 Access-Control-Allow-Origin 헤더에 알맞은 값을 세팅해주는 것
  • *을 사용하여 이 헤더를 세팅하게 되면, 모든 출처에서 오는 요청을 다 받겠다는 의미이므로 당장은 편할 수 있지만, 보안적으로 심각한 이슈가 발생할 수도 있다.

방법 2️⃣. Webpack Dev Server로 리버스 프록싱하기

  • 프록싱을 통해 CORS 정책을 우회하는 방법
    • 마치 CORS 정책을 지킨 것처럼 브라우저를 속여 우리가 원하는 서버와 자유롭게 통신할 수 있다.
  • 실제 프로덕션 환경에서도 클라이언트 어플리케이션의 소스를 서빙하는 출처와 API 서버의 출처가 같은 경우에 사용하는 것이 좋다.
    • 어플리케이션을 빌드하고 서버에 올리고 나면 더 이상 webpack-dev-server가 구동하는 환경이 아니기 때문에 이상한 곳으로 API 요청을 보내게 된다.

결론

  • webpack-dev-server 방법은 로컬 개발 환경에서만 통하는 방법인데다가, 근본적인 문제 해결 방법이 아니기 때문에,
  • 결국 운영 환경에서 CORS 정책 위반 문제를 해결하기 위해서는 백엔드 개발자가 서버 어플리케이션의 응답 헤더에 올바른 Access-Control-Allow-Origin이 내려오도록 세팅해줄 수밖에 없다.
  • 실제 배포 단계에서는 같은 origin을 사용하기 때문에 문제가 되지 않기 때문에, 일단락 개발단계에서는 백엔드 개발자가 cors를 모두 허용하여 문제를 해결하였다.

 


참고

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

 

Cross-Origin Resource Sharing (CORS) - HTTP | MDN

Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that allows a server to indicate any origins (domain, scheme, or port) other than its own from which a browser should permit loading resources. CORS also relies on a mechanism by which

developer.mozilla.org

https://evan-moon.github.io/2020/05/21/about-cors/#%EC%B6%9C%EC%B2%98origin%EA%B0%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80%EC%9A%94

 

CORS는 왜 이렇게 우리를 힘들게 하는걸까?

이번 포스팅에서는 웹 개발자라면 한번쯤은 얻어맞아 봤을 법한 정책에 대한 이야기를 해보려고 한다. 사실 웹 개발을 하다보면 CORS 정책 위반으로 인해 에러가 발생하는 상황은 굉장히 흔해서

evan-moon.github.io

https://velog.io/@effirin/CORS%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80

 

CORS란 무엇인가?

CORS가 무엇인지 알기 전에, 이 CORS가 등장하게 된 배경을 먼저 알아보자.SOP는 2011년 RFC 6454에서 등장한 보안 정책으로 "같은 출처에서만 리소스를 공유할 수 있다"라는 규칙을 가진 정책이다.그러

velog.io

https://kk-programming.tistory.com/63

 

[Web] CORS (Cross Origin Resource Sharing)

* 아래 Source들을 참고하여 작성했습니다. 🔥 CORS (Cross Origin Resource Sharing) 사용자가 가져오는 리소스들이 안전한지 검사하는 관문 프론트 애플리케이션과 다른 origin(출처)를 가진 서버 애플리케

kk-programming.tistory.com