[WEB] Hello, CORS!

소면(Somyeon)
5 min readFeb 18, 2021

--

CORS란?

Cross Origin Resources Sharing 직역하면 교차 출처 리소스 공유로 풀이된다. 쉽게 말해 서로 다른 출처에서 리소스를 주고받는 것을 얘기한다.

출처..?

웹에서 출처는 프로토콜 도메인 포트를 의미한다. 즉 동일한 프로토콜, 도메인, 포트번호를 가진 출처들끼리 자원을 공유하면 동일한 출처로, 이 세가지 구성 요소 중 하나만 다르더라도 다른 출처로 인식한다.

원래 브라우저는 동일한 출처에서만 리소스 공유를 허용하는 SOP (Same Origin Poliy)를 따른다. 이 정책에 대한 예외사항으로 등장한 것이 CORS인데, 브라우저에서 다른 출처로 데이터를 요청할 경우 CORS 정책을 준수하면 데이터를 주고받을 수 있도록 허용해준 것이다.

CORS 오류는 브라우저에서만 발생한다.

우리가 CORS 오류를 만날 때는 브라우저에서 백엔드나 API 서버로 직접 데이터를 요청할 때이다. 내가 CORS 오류를 만난 것도 react 컴포넌트에서 공공 데이터 API 서버로 직접 데이터를 요청할 때 맞닥뜨렸다. 처음에는 ‘공공 데이터라면서 왜 호출이 안 돼!’ 하고 당황했지만, API의 오류가 아니라 브라우저에서 발생시킨 오류였던 것이다.

전통적인 SSR 방식(Server Side Rendering)의 렌더링은 클라이언트 - 프론트 서버 — 백엔드 서버 간의 통신 순서가 지켜진다. 즉,

  1. 클라이언트에서 웹사이트에 접속하면,
  2. 프론트 서버에서 백엔드 서버로 데이터를 요청하고,
  3. 프론트 서버는 백엔드 서버로부터 전달받은 데이터를 HTML, CSS, JS 등 프론트 소스와 함께 클라이언트에게 응답한다.
Server Side Rendering (SSR)

하지만 CSR(Client Side Rendering) 방식에서 클라이언트는 프론트 서버부터 프론트 관련 소스만 응답 받고, 데이터는 클라이언트가 직접 백엔드 서버에 데이터를 요청한다. 이 때 브라우저에서 실행되는 요청 서버는 다른 출처를 가지고 있기에 CORS 정책을 지키지 않는다면 오류가 발생하는 것이다.

Client Side Rendering (CSR)

브라우저가 어떻게 요청하기에?

대부분의 경우 브라우저는 요청을 보낼 때 해당 요청이 안전한지 확인하기 위해 미리 찔러보는 작업을 한다. OPTIONS 메소드를 이용해 본 요청을 보내기에 전 미리 요청을 보내는데 프리플라이트(Preflight)라고 한다. 이 때 서버가 올바른 응답을 하더라도 응답 헤더에 Access-Control-Allow-Origin가 없거나, 설정된 Access-Control-Allow-Origin의 값이 요청을 보낸 클라이언트의 도메인과 다르다면 브라우저 자체적으로 오류를 발생시켜 메인 요청을 진행하지 않는다.

출처 https://developer.mozilla.org/ko/docs/Web/HTTP/CORS

CORS 오류 해결 방법은…

서버에서 Access-Control-Allow-Origin 세팅

가장 전통적인 방법으로 서버에서 응답할 때 응답 헤더에 Access-Control-Allow-Origin값을 넣어주면 된다. 요청을 보낸 클라이언트의 도메인을 적거나 ‘모든 도메인의 접근을 허용한다’는 의미로 와일드카드 *를 넣어주면 된다. 단, 브라우저에서 쿠키를 포함하는 Credential Request을 보낼 경우에는 Access-Control-Allow-Origin값에 반드시 요청 도메인을 지정해야한다.

프록시 방식으로 요청

서버 간의 통신에서는 다른 출처라도 CORS 오류가 발생하지 않는다. 이를 이용해 서버를 세팅하는 대신 브라우저와 백엔드 서버 사이에 중간 역할인 프록시 서버(PROXY)를 둬서 요청할 수 있다. 원래 프록시의 사전적 정의는 대리의 의미로, 프록시 서버는 클라이언트와 서버 사이에서 중계기 역할을 한다. 클라이언트 — 프록시 — 백엔드 서버의 형태로 통신하며 프록시가 클라이언트의 요청과 응답을 대신 해주는 형태인 것이다.

CSR 에서는 프론트엔드 서버를 프록시로 둬 클라이언트에서 프론트엔드 서버로 요청을 보내고, 프론트엔드 서버에서 백엔드에 요청을 보내는 방식을 이용해 오류를 해결할 수 있다.

CORS는 CSR에서만 발생하는 것이 아니다.

브라우저에서 도메인이 다른 서버의 웹폰트에 접근하거나 WebGL에서 다른 도메인의 텍스쳐 (ex, 이미지)리소스를 사용하고자 할 경우에도 CORS 이슈가 발생한다.

Reference.

MDN 교차 출처 리소스 공유(https://developer.mozilla.org/ko/docs/Web/HTTP/CORS)

--

--