CORS란?
Cross Origin Resource Sharing 의 약자로
교차가 되는 출처 리소스들의 공유를 말합니 다.
쉽게, 다른 출처에서 데이터를 주고 받는 것을 허용하는 정책이라고 생각하면 될 것 같습니다.
출처(Origin)란?
예를 들어 우리가 주로 쓰는 유튜브,
이 서버의 위치를 의미하는 https://www.youtube.com 와 같은 URL은 사실 아래와 같이 이루어져 있습니다.
여기서 출처는 Protocol + Host + Port 까지 합친 것(https://AhnDongSup.github.io:433) 을 의미합니다.
여기서 프로토콜, 포트, 호스트 모두 일치할 경우를 Same Origin
이 세가지 중 한가지라도 일치하지 않다면 Cross Origin이 됩니다.
SOP정책
Same Origin Policy 의 약자로
현재 웹에서는 SOP(Same Origin Policy)와 CORS(Cross Origin Resurce Sharing) 두가지 정책이 있습니다만
과거에는 프론트엔드 / 백엔드 레이어를 별도로 구성하지 않고,
서버가 직접적으로 요청 처리의 결과를 HTML 문서로 만들어 클라이언트에게 보내주었습니다.
즉, 다른 도메인이 아닌 동일한 도메인 안에서 일어나는 것이 대부분 이었기에
동일한 출처 사이에서만 데이터를 주고받을 수 있다는 SOP정책만이 존재했습니다.
하지만 기술의 발전으로 단순히 문서를 제공하는 용도가 아닌 어플리케이션을 만들기 시작하면서
다른 출처로 데이터를 주고 받아야 하는 일이 증가하다보니,
기존의 SOP정책에 불편함을 느끼기시작하면서 등장한 것이 CORS정책입니다.
CORS 동작과정
- 클라이언트에게 HTTP요청의 헤더에 Origin을 담아 전달합니다.
- 서버는 응답헤더에 Access-Control-Allow-Origin을 담아 클라이언트로 전답합니다.
- 클라이언트에서, 자신이 보냈던 요청의 Origin과 서버가 보내준 Access-Control-Allow-Origin을 비교합니다.
CORS 정책은 공부하다보면 당연히 거칠 수 밖에 없는 부분인 것 같습니다.
저는 이번에 프로젝트를 하나 준비하면서 알게된 사실이고,
프론트 서버 http://localhost:3000 와
백엔드 서버 http://127.0.0.1:5000 의 출처 가 다른 것이 원인이 되었습니다.
이러한 error 메세지를 보면,
CORS를 허용하도록 해서 다른 출처 리소스 공유 하도록 권하는 것이라고 생각하면 되겠습니다.
잘 보시면, Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.
"요청 헤더 필드 content-type은 예비요청 응답의 Access-Control-Allow-Headers에서 허용되지 않습니다 "
라는 메시지가 보입니다.
이 경우 저는 서버에서 Access-Control-Allow-Origin을 세팅함으로써 문제를 해결할 수 있었습니다.
예비요청
만약 POST요청을 할 경우 브라우저는 요청을 한번에 보내지 않습니다.
대부분의 경우 예비요청 (Preflight Request)으로 서버에 전달하게 됩니다.
예비요청은 GET이나 POST가 아닌 OPTIONS라는 요청 메서드로 보내지게 됩니다.
서버는 예비요청에 대한 응답으로 서버가
어떤 것을 허용하고 어떤 것을 금지하고 있는지에 대한 정보를 담아서 브라우저로 보내고,
브라우저는 보낸 요청과 서버가 응답해준 정책을 비교하여
해당 요청이 안전한지 확인하고 본 요청(POST)를 보내게 됩니다.
서버에서 정상적으로 응답(상태코드: 200 OK) 을 했습니다.
하지만 브라우저가 응답을 CORS정책 위반이라고 분석한 것 같습니다.
Origin에서 오는 요청을 따로 허용하지 않았기 때문에
서버가 응답해준 정책과 비교하여 해당 요청이 위반된다고 판단 했기 때문입니다.
이를 통해 브라우저가 CORS정책을 분석하는 시간은 서버의 응답이 도착한 이후라는 것을 알 수 있습니다.
출처를 비교하는 로직
CORS정책에 벗어나는 요청에 서버가 정상적으로 응답을 했다고 하더라도
출처를 비교하는 로직은 서버에 구현된 스펙이 아닌 브라우저에 구현된 스펙이기 때문에
결과적으로 응답처리가 되지 않습니다.
그렇기때문에 서버와 서버 간의 통신에서는 발생하지 않는다는 것을 인지해야합니다.
CORS 해결방법
서버에서 세팅하기
Access-Control-Allow-Origin 세팅
저는 FLASK를 통해 백엔드 서버를 이용하고 있기때문에 flask_cors 에서 CORS와 같이 사용할 모듈을 불러왔습니다.
그리고 Flask의 인스턴스로 만들어진 app을 CORS에 넣어 app에 설정된 서버에 CORS를 적용했습니다.
from flask_cors import CORS
CORS(app)
그랬더니 error 없이 정상적으로 데이터를 불러올 수 있었습니다 ㅎ
하지만 이 경우 모든 Origin 에서 오는 요청을 허용한다는 뜻이기에 보안이 허술해진다는 단점이 있습니다.
그렇기에 특정 도메인 을 허용할 수 있도록 아래와 같이 수정해줬습니다.
from flask_cors import CORS
CORS(app, resources={r'*': {'origins': '<http://localhost:3000>'}})
http://localhost:3000 에 해당하는 모든 포트. 하위 주소를 허용한다는 뜻입니다.
만약 하위경로와 포트번호까지 디테일하게 허용하고 싶다면 아래와 같이 수정해주면 됩니다.
from flask_cors import CORS
CORS(app, resources={r'/users/*': {'origins': '<http://localhost:3000>'}})
Chrome 확장 프로그램
급할 때 Chrome에서 간단하게 확장프로그램을 설치해서 해결할 수도 있습니다.
하지만 로컬 환경에서만 해결이 가능하고 결론적으로 다른 방법을 이용해야합니다.
CSR vs SSR
CSR이란 무엇인가?
CSR Client Side Rendering의 약자로
렌더링이 클라이언트 쪽에서 일어나는 방식을 의미합니다.
쉽게 말해, 모든것이 클라이언트에서 다 이루어지는 것입니다.
구체적인 단계는 아래와 같습니다.
- 유저가 웹사이트 요청을 보냄
- 서버가 요청을 받으면 클라이언트로 HTML파일과 JS로 접근할 수 있는 링크를 보냄
- 클라이언트는 HTML과 JS를 다운로드 받음 (유저는 빈 화면만 보임)
- 다운이 완료된 JS가 실행되고, 데이터를 위한 API가 호출됨
- 서버가 API로부터의 요청을 응답함
- API로부터 받아온 data를 placeholder 자리에 넣어줌으로써 상호작용이 가능해짐
+
장점
- 연속된 렌더링으로 인한 과부하를 줄일 수 있음
-
단점
- 사용자가 첫 화면을 보기까지 시간이 오래 걸릴 수 있음
-> 이것은 서버에서 처리없이 클라이언트로 보내주기 때문에 자바스크립트가 모두 다운로드 되고
실행이 끝나기 전까지 시간이 걸리게 된다고 보면 되겠습니다.
- 검색 엔진 최적화에 문제가 발행함
-> SEO(Search Engine Optimization) 검색엔진최적화로, 특정 키워드를 검색했을 때
그에 관련된 웹사이트나 컨텐츠를 가장 상단에서 보여줄 수 있도록 하는 작업을 말합니다.
이 작업이 이루어지기 위해선 HTML에 많은 컨텐츠가 저장되어 있어야
원할하게 이루어지는데, CSR의 경우 HTML의 바디는 대부분 비어있기에 검색엔진들이
CSR로 작성된 웹페이지를 분석하는데 어려움이 있습니다.
SSR이란 무엇인가?
Sever Side Rendering의 약자로
서버쪽에서 필요한 데이터를 모두 가져와서 렌더링 준비를 끝마친 상태로 클라이언트에 전달하는 방식을 의미합니다.
구체적인 단계는 아래와 같습니다.
- 유저가 웹사이트 요청을 보냄
- 서버는 바로 렌더링이 가능한 HTML파일을 만듬
- 클라이언트에 전달되는 순간, 렌더링 준비가 마친 HTML은 바로 렌더링이 됨
- 클라이언트가 JS를 다운받음 (유저는 화면을 볼 수 있지만 조작은 불가능)
- 브라우저가 JS프레임워크를 실행
- JS가 성공적으로 컴파일되어 상호작용이 가능해짐
+
장점
- 첫 번째 페이지로딩이 빨라짐
-> 모든 컨텐츠가 HTML에 담겨져 있기 때문에 더 효율적인 SEO가 가능해짐
-
단점
- 사용자가 클릭을하면 전체적인 웹사이트를 다시 서버에서 받아오는 것과 동일하기 때문에 깜빡임 이슈가 발생할 수 있음
- 서버에 요청해서 서버에서 HTML을 만들어야하는 빈도가 많을 수록 즉, 사용자가 많을 수록 서버에 과부하가 걸릴 수 있음
TTV 과 TTI
TTV (Time To View)
사용자가 사이트를 볼 수 있는 시점
TTI (Time To Interact)
사용자가 클릭을 하거나 인터랙션이 가능한 시점
CSR은 TTV 동시에 TTI가 가능하고
SSR은 TTV 와 TTI 사이의 공백기간이 길다는 것이 차이점 입니다.
여기까지 CORS와 CSR, SSR 에 대해 알아봤습니다!
아래 링크를 참고해서 글을 작성했으니 더 자세하게 살펴보고 싶다면 링크 참고하시길 바랍니다.
'flask' 카테고리의 다른 글
flask clone coding [2] (데이터 검증) (0) | 2022.11.13 |
---|---|
flask clone coding [1] (Flask-SQLAlchemy 3.0 변경사항) (0) | 2022.11.06 |
Flask - 테스트 코드 / 관리자 페이지 / 카테고리, 게시물 (0) | 2022.08.10 |
Flask - 회원가입/로그인/로그아웃 처리 [블로그 웹 애플리케이션 개발] (0) | 2022.07.27 |
Flask - 라이브러리 설치부터 정적 파일 다루기까지 ( Blueprint / jinja template engine / render_template() ) (0) | 2022.07.11 |