[Web Browser] CORS, SOP

0

web browser

목록 보기
1/1
post-thumbnail

개인 공부를 위해 정리한 내용입니다. 수정이 필요한 내용 피드백주시면 감사하겠습니다 .🙂

🤔 CORS요? 오류 아닌가요?

  • 프론트엔드 개발 공부를 하는 사람이라면 서버 통신을 할 때 한번쯤 마주했을 법한 이 빨간 오류! 이 오류는 도대체 왜 나타나고 어떤 방법으로 해결할 수 있는지 알아보자.

🐝 SOP(Same-Origin Policy)

웹 브라우저는 '같은 출처에서만 리소스를 공유할 수 있다'라는 규칙을 가지고 있다. 예를 들어 데이지 닷컴에서 Fetch API를 사용해서 크롱 닷컴 API URL로 GET 요청을 보낸다고 하자. 이때 크롱 닷컴에서 데이지 닷컴의 요청을 허용해 주는 작업을 하지 않았다면, 브라우저는 보안 상의 이유로 데이지 닷컴의 GET 요청을 제한한다.

✔️ 같은 출처: URL(https://www.daisy.com:80)의 구성 요소 중 Scheme(https://), Host(www.daisy.com), Port(:80) 일치
✔️ 리소스: 주고 받는 데이터

🛠SOP가 필요한 이유

그냥 데이터를 조회해오는 것뿐인데 요청을 제한해야 하나라는 생각이 들 수도 있다. 하지만 악의적인 목적을 가진 사람이 네이버에 접속하려는 유저에게 가짜 URL을 전달하고, 유저가 그 가짜 URL로 가짜 네이버(짭이버)에 접속했다고 가정하자.

유저가 짭이버에 접속하게 되면 유저의 브라우저는 짭이버의 자바스크립트 파일을 받게 되는데 만일 그 자바스크립트 파일에 악의적인 코드가 있다면 유저의 브라우저에 저장되어 있는 인증 정보를 사용해서 진짜 유저인 것처럼 네이버 서버에 요청을 보내 유저의 개인 정보를 빼낼 수도 있을 것이다. 그렇기 때문에 브라우저의 기본 스펙이기도 한 SOP(Same-Origin Policy)는 브라우저 보안상 꼭! 필요한 존재이다.

🛠CORS가 필요한 이유

그렇다면 웹에서는 항상 같은 도메인 간 HTTP 요청만 해야 할까? 만약에 다른 도메인의 자원을 사용하고 싶으면 어떻게 할까? 다른 도메인 즉 교차 도메인끼리도 자원을 공유할 수 있도록 해줘야 하지 않을까?

이때 필요한 개념이 CORS이다. CORS는 Cross-origin resource sharing의 약자이며, 말 그대로 웹 브라우저가 보안상의 이유로 장착하고있는 Same Origin Policy의 제약을 넘어 다른 도메인의 자원을 사용할 수 있도록 해주다는 것이다! 빨간 글씨로 C.O.R.S...👾적혀있어서 오류인줄만 알았는데 웹 개발자에게 꼭 필요한 존재였던 것이다! CORS 미워하지 마시길!

🐹 CORS 정책 위반 문제 해결 방법

Access-Control-Allow-Origin 세팅하기

보안 상의 이유로, 브라우저는 스크립트에서 시작한 교차 출처 HTTP 요청을 제한합니다. 예를 들어, XMLHttpRequest와 Fetch API는 동일 출처 정책을 따릅니다. 즉, 이 API를 사용하는 웹 애플리케이션은 자신의 출처와 동일한 리소스만 불러올 수 있으며, 다른 출처의 리소스를 불러오려면 그 출처에서 올바른 CORS 헤더를 포함한 응답을 반환해야 합니다. MDN

그럼 CORS 통해 다른 출처의 리소스를 사용하고 싶다면 어떻게 해야할까? 가장 기본적인 방법은 아래처럼 HTTP 요청 시 클라이언트의 요청과 서버의 응답의 HTTP Header에 Access-Control-**류의 정보를 주고 받는 것이다.

  • 클라이언트에서 Access-Control-** 류의 HTTP Header를 서버에 보내야 하고, (출처표기)
  • 서버도 Access-Control-** 류의 HTTP Header를 클라이언트에 회신하게 되어 있어야 한다. (접근 허용 표기)
  • 브라우저는 이 둘이 일치한지 비교 → 일치하면 안전한 요청으로 판단하고 응답 데이터를 받아온다.
  • 만약 해당 서버가 CORS 정책을 위반하는 리소스 요청에 응답을 해도 브라우저가 이 응답을 분석해서 CORS 정책 위반이라고 판단되면 그 응답을 사용하지 않고 그냥 버리게 된다.
  • CORS는 브라우저의 구현 스펙에 포함되는 정책이기 때문에, 브라우저를 통하지 않고 서버 간 통신을 할 때는 이 정책이 적용되지 않는다.
  • 브라우저가 요청 내용을 분석하여 해당하는 방식으로 서버에 요청을 날리므로, 개발자는 목적에 맞는 방식을 선택하고 그 조건에 맞게 코드를 작성해줘야한다.

하지만 이때 와일드카드인 *을 사용하여 이 헤더를 세팅하게 되면 모든 출처에서 오는 요청을 받는다는 의미이기에 알 수 없는 출처에서 오는 요청까지 받을 수 있게 된다. 따라서 Access-Control-Allow-Origin: 에 출처를 명시해주는 것이 좋다.

프록시 사용하기

CORS 관련 에러 메세지를 가장 많이 마주할 때는 바로 로컬에서 프론트엔드 개발을 할 때일 것이다. 물론 백엔드에는 배포 URL을 기준으로 Access-Control-Allow-Origin 헤더가 세팅되어있겠지만, 로컬에서 사용할 때는 localhost:3000 과 같은 범용적인 URL를 사용하게 되기 때문에 CORS 정책 위반 문제가 발생하기 쉽다. 이때는 프론트쪽에서 라이브러리에서 제공하는 프록시 기능을 사용해서 간단하게 CORS 정책을 우회할 수 있다.

  • package.json에 직접 세팅
//package.json
{
  ...,
  "proxy": "http://localhost:8000",
  ...,
}
  • http-proxy-middleware 설치

이렇게 설정을 해놓으면 HTTP 요청을 프록싱해주기 때문에 마치 CORS 정책을 지킨 것처럼 브라우저를 속이면서도 우리는 원하는 서버와 자유롭게 통신을 할 수 있다.
즉, 프록싱을 통해 CORS 정책을 우회할 수 있는 것이다. 하지만 이것도 결국 브라우저를 속여서 CORS 정책 문제를 해결한 경우이기 때문에 결론적으로는 백엔드에서 Access-Control-Allow-Origin 세팅을 해주는 게 더 안정적인 방법이다!

참고 자료
웹개발 짜증유발자! CORS가 뭔가요?
MDN CORS
CORS는 왜 이렇게 우리를 힘들게 하는걸까?
Cross Origin Resource Sharing - CORS

0개의 댓글