본문 바로가기

취업/면접

지긋지긋한 CORS! 타파!!

반응형

 

CORS는 Cross Origin Resource Sharing 이란 단어의 약자로 교차 출처 리소스 공유라고 불린다. 이를 위해선 동일 출처 정책인 Same Origin Policy를 알아두어야 한다. Sop는 동일한 출처에서만 http 요청이 가능하도록 하는 정책이다.

 

간단히 말하면 인가받지 않은 클라이언트에서 서버로 http 통신을 요청할 때 이를 방지하기 위해서 나온 정책이다. 예를 들어 어느 홈페이지에 방문하였을 때 나의 웹 페이지가 가진 쿠키를 통해 내 개인정보를 네이버에 요청하면 내 개인정보가 해커에게 노출될 우려가 있다. 이를 방지하기 위해서 네이버 서버에서는 허용된 웹페이지 url이 아니면 cors를 발생시켜 정보를 제공하지 않을 정책을 수립한 것이다.

 

이게 끝이다. 간단한다. 이를 해결하기 위해서는 2가지 방법이 존재하는데

 

  1. Server to Server 통신하기.(proxy server)
  2. cors는 클라이언트에서 발생하는 현상으로 서버끼리 통신하면 발생하지 않는다. 그리하여 서비스 개발시에 프론트 서버를 하나 더 두는 방식으로 cors를 예방한다. 서버끼리 통신을 한다면 보안성도 높아지기 때문에 활용도가 높다.
  3. white-list에 추가하기.
  4. 네오위즈 때 사용했던 방식으로 그 당시에는 서버 개념이 정확히 없어서 상우가 처리해주었다. 요청하는 ip를 백엔드 쪽에서 while-list에 추가를 해놓고 해당 ip에서 오는 통신은 cors를 허용하도록 처리하는 방식이다. 말을 어렵게 했지만 가장 많이 사용하는 Access-Control-Allow-Origin 세팅하기이다.

 

동작방식도 알아보자.

 

일반적인 경우로 Access-Control-Allow-Origin 에 허용된 클라이언트라고 가정하고 시작하자.

 

HTTP 프로토콜을 사용해 요청을 보낼 때, 브라우저는 요청 헤더에 Origin이라는 필드에 요청을 보내는 출처를 함께 담아보낸다. 이후 서버가 이 요청에 대한 응답을 할때 Access-Control-Allow-Origin이라는 값에 이 리소스를 접근하는 것이 허용된 출처를 내려준고, 이후 응답을 받은 브라우저는 자신의 요청에 Origin 과 서버가 보내준 응답의 Access-Control-Allow-Origin을 비교해본 후 이 응답이 유효한 응답인지 아닌지를 결정한다.

 

위가 기본적이니 흐름이고 더 자세히 보면 세가지 시나리오가 있다. 에러를 고칠 때 파악하기 위해 좀 더 공부해보자.

Preflight Request

우리가 개발시 가장 많이 마주치는 시나리오다. 이 상황일 때 브라우저는 요청을 한번에 보내지 않고 예비 요청과 본 요청을 나누어서 서버로 전송한다.

 

이때 예비 요청을 Preflight라 부르며 이 요청은 HTTP 메소드 중 OPTIONS 메소드가 사용된다. 역할은 본 요청을 보내기 전에 브라우저 스스로 이 요청을 보내는 것이 안전한지 확인하는 것이다.

 

우리가 자바스크립트의 fetch API를 사용하여 브라우저에게 리소스를 받아오라는 명령을 내리면 브라우저는 서버에게 예비 요청을 먼저 보내고, 서버는 이 예비 요청에 대한 응답으로 현재 자신이 어떤 것들을 허용하고, 어떤 것들을 금지하고 있는지에 대한 정보를 응답 헤더에 담아서 브라우저에게 다시 보내주게 된다.

 

이후 브라우저는 예비 요청과 서버 응답을 비교한 후, 안전하다고 판단되면 다시 본 요청을 보낸다. 본 요청에 대한 응답이 오면 최종적으로 응답 데이터를 JS에 넘겨준다. 여기서 origin 값이 다르다면 에러를 뱉는다.

 

이 시나리오를 길게 다룬 이유는 바로 지금 부터인데

 

예비 요청에 대해서는 정상적인 200 코드가 떨어질 수 있으나 본 요청에서 빨간 에러를 만날 수 있는 상황 때문이다. CORS의 정책 위반은 예비 요청의 성공 여부와 관계가 없다.

 

대부분 이 방식을 사용하지만, 모든 상황에서 이렇게 두번씩 요청을 보낼 순 없다. 조금 까다롭긴 하지만 본요청만 CORS 검사하는 경우가 바로 아래의 Simple Request이다.

Simple Request

 

본 요청만을 통해 CORS를 검사한다. 한번만 보내는 만큼 조건이 까다롭다. 해당 조건은

 

  1. 요청 메소드가 GET, HEAD, POST 중 하나
  2. 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만 허용된다.

 

1번은 괜찮으나 2,3번이 까다롭다. 사용자 인증하는 Authorization 헤더조차 사용하지 못한다.(유져 관련된거니깐 당연하긴함) 3번도 대부분의 HTTP API는 text/xml, application/json 이 많이 사용되므로 어려운 조건이다.

 

Credentialed Request

 

인증된 요청을 사용하는 방법이다. 보안을 강화하고 싶을 때 사용한다. 기본적으로 브라우저가 제공하는 리소스 요청 API이니 XMLThhpRequest 객체나 fetch API는 별도의 옵션없이 브라우저의 쿠키 정보나 인증과 관련된 헤더를 함부로 요청에 담지 않는다. 이때 요청에 인증과 관련된 정보를 담을 수 있게 하는 옵션이 credentials 옵션이다. 이 옵션은 총 3가지의 값을 사용할 수 있으며, same-origin, include, omit이다.

 

 

인제 CORS 에러가 발생해도 어느정도 해결할 수 있겠지?

참고

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

 

반응형

'취업 > 면접' 카테고리의 다른 글

Protobype 면접질문  (0) 2022.02.16
Promise 면접질문  (0) 2022.02.14
React.memo 알아보기 (feat. React.callback)  (0) 2021.08.19
Callback 비교 - 1  (0) 2021.08.07
React 배열에 key가 존재하는 이유  (0) 2021.08.06