CORS

수민·2023년 7월 2일
0

프론트엔드 면접

목록 보기
5/8
post-thumbnail

프로젝트를 하면서 수없이 만났던 CORS(Cross Origin Resource Sharing)!
정작 제대로 알고 있지는 못한 것 같아서 더 깊게 이해해보고자 한다.

Origin

CORS의 O는 Origin으로, URL의 프로토콜 + 호스트 + 포트를 의미한다.

SOP(Same-Origin Policy)

SOP는 동일 출처 정책을 말한다.
즉, 동일 출처(Same-Origin) 서버에 있는 리소스는 자유로이 가져올 수 있지만, 다른 출처(Cross-Origin) 서버에 있는 이미지나 영상 같은 리소스는 가져올 수 없다는 것이다.

동일 출처 정책은 CSRF나 XSS 공격에 대비하여 필요하다.
(이 부분에 대해서는 다음 포스트에 다루도록 하겠다!)

즉 SOP 정책은 프로토콜, 호스트, 포트모두 같을 때만 리소스 사용을 허가한다.

CORS(Cross-Origin Resource Sharing)

그러나 웹이 발전하면서 어쩔 수 없이 다른 출처 간 상호작용을 해야 하는 경우가 많이 발생하기 시작했다.
그래서 다른 출처의 리소스를 사용하기 위한 해결책으로 CORS 정책이 나타나게 되었다.

CORS 기본 동작

  1. 클라이언트에서 HTTP 요청 Header에 Origin을 담아 전달한다.
  2. 서버는 응답 Header에 Access-Control-Allow-Origin을 담아 전달한다.
    이는 이 리소스를 접근하는 것이 허용된 url을 의미한다.
  3. 클라이언트에서 Origin이 서버에서 보내준 Access-Control-Allow-Origin에 속해 있는지 확인한다.
    속해 있지 않다면 CORS 에러가 발생한다.

CORS 심화 동작

1. 예비 요청 (Preflight Request)

브라우저는 요청을 보낼 때 한 번에 보내지 않고, 예비 요청을 보내 서버와 잘 통신되는지 확인한 후 본 요청을 보낸다.
즉, 예비 요청의 역할은 본 요청을 보내기 전에 브라우저 스스로 안전한 요청인지 미리 확인하는 것이다.
이 때 브라우저가 예비 요청을 보내는 것을 Preflight라고 부르며, 이 예비 요청의 HTTP 메소드는 GET, POST 등이 아닌 OPTIONS가 사용된다.

예비 요청의 취지는 좋지만 결국은 실제 요청에 걸리는 시간이 늘어나 성능에 영향을 미칠 수 있다.
수행하는 API 호출 수가 많으면 많을수록 서버 요청을 배로 보내기 때문이다.
따라서 브라우저 캐시를 이용해 응답 Header의 Access-Control-Max-Age에 캐시될 시간을 명시해주면 최적화할 수 있다.

2. 단순 요청 (Simple Request)

예비 요청을 생략하고 바로 본 요청을 보낸 후 그 응답을 토대로 CORS 정책 위반 여부를 판단하는 것이다.

단순 요청으로 요청을 보내기 위해서는 아래의 3가지 조건을 만족해야 한다.

  1. 요청의 메소드가 GET, POST, HEAD 중 하나여야 한다.
  2. Header가 Accept, Accept-Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width, Width일 경우 에만 적용된다.
  3. Header의 Content-Typeapplication/x-www-form-urlencoded, multipart/form-data, text/plain 중 하나여야한다.

대부분의 HTTP API 요청은 application/json이나 text/xml으로 통신하기 때문에 3번 조건을 만족하지 못한다.

3. 인증된 요청 (Credentialed Request)

위의 두 유형은 인증 정보가 없는 경우의 요청이고, 인증 정보를 함께 보내야 하는 요청이라면 조금 다른 형태로 통신하게 된다.
여기서 인증 정보란 세션 ID가 저장되어 있는쿠키 혹은 Header의 Authorization에 설정하는 토큰 값 등을 말한다.

  1. 인증 정보를 보내기 위해서는 HTTP 요청 시 credentials 옵션을 지정해야 한다.
    이는 어떤 방법을 통해 HTTP 요청을 보내는지에 따라 다르기 때문에 각 방법에 맞게 설정해줘야 한다.
  2. 서버는 HTTP 응답 시 일반적인 CORS 요청과 다르게 아래의 4가지 조건을 만족해야 한다.
    조건 1. Header의 Access-Control-Allow-Credentials를 true로 설정해야 한다.
    조건 2. Header의 Access-Control-Allow-Origin 의 값에 와일드카드 문자("")는 사용할 수 없다.
    조건 3. Header의 Access-Control-Allow-Methods 의 값에 와일드카드 문자("
    ")는 사용할 수 없다.
    조건 4. Header의 Access-Control-Allow-Headers 의 값에 와일드카드 문자("*")는 사용할 수 없다.

마치며

마지막으로, SOP와 CORS는 브라우저의 정책이다.
즉 서버는 정상적인 응답을 하고 있지만 브라우저에서 차단하는 것이다.
그렇다고 CORS 에러를 클라이언트 단에서 해결할 수 있느냐고 한다면 그것도 아니다.
서버에서 Access-Control-Allow-Origin에 해당 도메인을 추가해야 한다!

0개의 댓글