CORS란 무엇인가? 알고쓰자...?

Keun·2022년 6월 13일
0

CORS 에러, 백엔드랑 협업할때 자주보던것.

백엔드와 프로젝트를 진행하다보면, 항상 마주하는 에러: CORS에러.
"무슨에러에요?"
"CORS에러라는데요..?"
"제잘못인가요? 그쪽잘못인가요?"
"둘다인것같은데요"

백엔드든 프론트엔드든 우리 둘다 처음 웹프로젝트 하는 사람들이라...검색해봤었다.

잘못이 있다고 친절하게 말을 해주면 뭔지 알고 다음에 마주치지 않도록 해야하는것.

좀 알아봅시다.

SOP부터 알아야한다더라...

그냥 CORS만 알기엔 내가 너무한가보다. 구글링 해보니까, 각종 블로그에 개발자들이 써놓은 글들을 보면 SOP가 빠지지 않는다. 대학교에서 공부할때, 특히 지원할때 SOP는 나에게, Statement of Purpose. 즉,지원동기서 이런 서류였는데... 아무튼 조용히하고.

Same Origin Policy -> 같은 출처 정책. 자바스크립트 엔진 표준 스펙 저책인데, 같은 출처에서만 자원들을 공유 할 수 있도록 하는 뭔가 좀 굉장히 배타적인 정책이다.

여기서 자바스크립트 엔진이란, 내 머릿속에 알고있는것은 콜스택, 콜백큐, 이벤트루프, 메모리 힙 이런 구조로 이루어져 있는 것이다. 주로 웹 브라우저를 사용할때, 코드가 엔진에서 어떤 원리로 돌아가는지를 보여주는 그런 것이다. 어차피 이것도 공부해야하니 나중에 설명.

보안을 지키기 위해 만들어진 정책이 SOP라고 한다. 같은 출처에서만 자원 공유가능하도록. 누구든지 내 계정의 비밀번호를 가져가는 스크립트 (XSS, Cross-Site Scripting) 같은 것을 만들 가능성을 안만들기 위해서 그렇단다.

여기서 잠깐, '같은 출처' 라는 말이 좀 거슬려.

URL에는 다음과 같이 생겼다. Origin = Protocol + Host + Port / Path

Origin이라는 것을 통해서 같은 출처인지 아닌지를 비교해 본다고 한다.

URL포트번호가 생략 되있는 경우가 많다고 한다.

예)
스프링 백엔드쪽 -> http://localhost:8080
리액트 프론트쪽 -> http://localhost:3000

두개는 다른 SOP를 가진다. 왜? 포트 번호가 다르잖아. 딱 보이잖아.

리액트랑 스프링이 서로 접근하려면 당연히 뭐해야겠어?
-> 그래서 프로젝트 할때, 로컬끼리 포트가 달라서 CORS설정 해줘야 한다.
왜? 포트번호가 다르다는 것은 SOP가 다르다는 뜻이니까.
이해했어?

드디어 CORS. 이제 대충 알듯.

SOP정책이랑 CORS 랑 다른 것이 아니다. CORS: Cross-Origin Resource Sharing. 이것은 SOP정책 안에 있는것이다. 이것은 SOP정책에서 예외 상황을 두어서 ORIGIN (Protocol + Host + Port) 끼리도 자원을 주고 받을 수 있는 정책을 넣어준 것이다.

차이를 말하자면: 이전에는 동일한 도메인에서만 자료를 받아왔지만, 클라이언트에서 도메인이 다른 서버를 사용하는 일이 많아지면서 CORS등장!

스프링 백엔드쪽. 즉, 서버측에서 CORS를 설정해 줘야한다. -> ORIGIN, METHOD로는 접근만 가능 -> 제한적인 접근이 가능하다는 말.

백엔드에서 설정해 줘야 하는건 맞는데, 동작 원리 알면 더좋을거같습니답.

기본적인 동작-> CORS 동작-> Simple Request랑 Preflight가 있다고한다.

클라이언트에서 W3C 사양에 따라서, 브라우저는 지원되는 메소드가 서버에서 유효한지 아닌지 확인하기 위해서 실제 요청을 보내기전에 OPTIONS요청을 보낸다고 구글링해보니까 그런다.
(https://velog.io/@entry_dsm/%EC%8A%88%EC%8A%89-%EC%8A%88%EC%8A%89.-%EC%8A%89.-%EC%8A%89.C..C.CORS-%EB%86%88%EC%95%84)
(https://medium.com/@f2004392/cors-preflight-request-options-9d05b9248e5a).

Simple Request:

Simple Request 로 보낼때는 세가지 조건이 충족 되어야한다:

  1. GET, HEAD, POST 메서드를 사용해야한다.
  2. User agent에서 자동으로 설정한 헤더 외에 수동으로 설정할 수 있는 헤더는 Fetch에 정의되어 있는 헤더 뿐입니다.
  3. Content-Type사용할 경우: application/x-www-form-urlencoded, multipart/form-data, text/plain만 허용.

HTTP요청시에, 심지어 application/json도 설정 불가능이라고 한다.

Preflight:

Simiple Request가 생각보다 너무 복잡해서, 주로 사용하는 요청이라고 한다. 사전요청 / 예비요청 이라고 생각하면 된다고한다.

Fetch API사용하여 브라우저에게 리소스 받아오라고 명령보낸다. 그러면 다음과 같이 예비요청과 본요청으로 나뉘어진다.
예비/사전 요청:
1. OPTIONS -> 목표 리소스와의 통션 옵션을 설명하기 위해 사용되는 메소드
2. ACCESS-CONTROL-ALLOW-ORIGIN: 직역하면, 컨트롤하는거 접근하는거 허락하는 출처? 그런느낌이다. 즉, 어떤 메소드 출처등을 허용하는 지에 대한 정보를 헤더에 보내서 응답한다.

이러고 나서, 브라우저가 이때 받은 응답과 보낼 요청을 비교하고, "아, 서버랑 비교해보니까 뭐 이정도면 안전한거같고..음...일단 서버에서 받은 응답데이터 자바스크립트에 보내주고 통신하면 될듯." 이라 생각하고 동작한다.

CORS의 기본적인 것에대해서 기록을 남겨보았다. 상당히 유용하고 왜 이제서야 제대로 알게되었는지참. 프로젝트 할때, 아무것도 모르고, 그냥 "이거 서버잘못이에요 제잘못이에요?" 이러고 있던 내가 참. CORS에러만 뜨면 구글링하고 스쳐 지나가는 그런 범죄를 일으켰다.

기본적인 개념을 그래도 알게 되어서 다행이다.

그리고 https://velog.io/@entry_dsm/%EC%8A%88%EC%8A%89-%EC%8A%88%EC%8A%89.-%EC%8A%89.-%EC%8A%89.C..C.CORS-%EB%86%88%EC%95%84

여기 글써주신분 덕분에 오늘 공부 제대로 했다. 감사합니다.

0개의 댓글