교차 출처 리소스 공유(CORS)

교차 출처 리소스 안전하게 공유

Mariko Kosaka

브라우저의 동일 출처 정책은 다른 출처에서 리소스를 읽는 것을 차단합니다. 이 메커니즘은 악성 사이트가 다른 사이트의 데이터를 읽지 못하도록 하지만 적법한 사용도 방지합니다.

최신 웹 앱은 다른 출처에서 리소스를 가져오려고 하는 경우가 많습니다. 예를 들어 다른 도메인에서 JSON 데이터를 검색하거나 다른 사이트의 이미지를 <canvas> 요소로 로드합니다. 이러한 리소스는 누구나 읽을 수 있는 공개 리소스일 수 있지만 동일 출처 정책에 의해 사용이 차단됩니다. 개발자는 지금까지 JSONP와 같은 해결 방법을 사용했습니다.

교차 출처 리소스 공유(CORS)는 표준화된 방식으로 이 문제를 해결합니다. CORS를 사용 설정하면 서버가 브라우저에 추가 출처를 사용할 수 있다고 알릴 수 있습니다.

웹에서는 리소스 요청이 어떻게 작동하나요?

요청 및 응답
클라이언트 요청 및 서버 응답을 보여줍니다.

브라우저와 서버는 하이퍼텍스트 전송 프로토콜(HTTP)을 사용하여 네트워크를 통해 데이터를 교환할 수 있습니다. HTTP는 리소스를 가져오는 데 필요한 정보를 비롯하여 요청자와 응답자 간의 통신 규칙을 정의합니다.

HTTP 헤더는 클라이언트와 서버 간의 메시지 교환을 협상하고 액세스를 결정하는 데 사용됩니다. 브라우저의 요청과 서버의 응답 메시지 모두 헤더본문으로 나뉩니다.

메시지 유형 또는 메시지 인코딩과 같은 메시지에 관한 정보입니다. 헤더에는 키-값 쌍으로 표현되는 다양한 정보가 포함될 수 있습니다. 요청 헤더와 응답 헤더에는 서로 다른 정보가 포함됩니다.

샘플 요청 헤더

Accept: text/html
Cookie: Version=1

이 헤더는 '응답으로 HTML을 수신하고 싶습니다. 여기 쿠키가 있습니다."

샘플 응답 헤더

Content-Encoding: gzip
Cache-Control: no-store

이 헤더는 '이 응답의 데이터는 gzip으로 인코딩됩니다. 캐시하지 마세요.'

본문

메시지 자체 일반 텍스트, 이미지 바이너리, JSON, HTML 또는 기타 여러 형식일 수 있습니다.

CORS는 어떻게 작동하나요?

동일 출처 정책은 브라우저에 교차 출처 요청을 차단하도록 지시합니다. 다른 출처의 공개 리소스가 필요한 경우 리소스 제공 서버는 요청을 전송하는 출처가 리소스에 액세스할 수 있다고 브라우저에 알립니다. 브라우저는 이를 기억하고 해당 리소스에 대해 교차 출처 리소스 공유를 허용합니다.

1단계: 클라이언트(브라우저) 요청

브라우저가 교차 출처 요청을 하면 현재 출처(스키마, 호스트, 포트)가 포함된 Origin 헤더를 추가합니다.

2단계: 서버 응답

서버가 이 헤더를 보고 액세스를 허용하려는 경우 요청하는 출처를 지정하는 Access-Control-Allow-Origin 헤더를 응답에 추가합니다(또는 모든 출처를 허용하려면 *).

3단계: 브라우저에서 응답 수신

브라우저가 적절한 Access-Control-Allow-Origin 헤더가 있는 이 응답을 확인하면 응답 데이터를 클라이언트 사이트와 공유합니다.

CORS와 사용자 인증 정보 공유

개인 정보 보호를 위해 CORS는 일반적으로 요청자가 식별되지 않는 익명 요청에 사용됩니다. 발신자를 식별할 수 있는 CORS를 사용할 때 쿠키를 전송하려면 요청과 응답에 헤더를 추가해야 합니다.

요청

다음 예와 같이 가져오기 옵션에 credentials: 'include'를 추가합니다. 여기에는 다음과 같이 요청에 포함된 쿠키가 포함됩니다.

fetch('https://example.com', {
  mode: 'cors',
  credentials: 'include'
})

응답

Access-Control-Allow-Origin는 특정 출처(*를 사용하는 와일드 카드 없음)로 설정해야 하며 Access-Control-Allow-Credentialstrue로 설정해야 합니다.

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true

복잡한 HTTP 호출의 사전 비행 요청

웹 앱이 복잡한 HTTP 요청을 실행하면 브라우저는 요청 체인의 시작 부분에 실행 전 요청을 추가합니다.

CORS 사양은 복잡한 요청을 다음과 같이 정의합니다.

  • GET, POST, HEAD 이외의 메서드를 사용하는 요청입니다.
  • Accept, Accept-Language 또는 Content-Language 이외의 헤더가 포함된 요청
  • application/x-www-form-urlencoded, multipart/form-data 또는 text/plain 이외의 Content-Type 헤더가 있는 요청

브라우저는 필요한 프리플라이트 요청을 자동으로 만들어 실제 요청 메시지 전에 보냅니다. 실행 전 요청은 다음 예시와 같은 OPTIONS 요청입니다.

OPTIONS /data HTTP/1.1
Origin: https://example.com
Access-Control-Request-Method: DELETE

서버 측에서 요청을 수신하는 앱은 애플리케이션이 이 출처에서 허용하는 메서드에 관한 정보와 함께 실행 전 요청에 응답합니다.

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, DELETE, HEAD, OPTIONS

서버 응답에는 프리플라이트 결과를 캐시할 기간(초)을 지정하는 Access-Control-Max-Age 헤더도 포함될 수 있습니다. 이렇게 하면 클라이언트가 실행 전 요청을 반복할 필요 없이 여러 개의 복잡한 요청을 보낼 수 있습니다.