Jerry's Log

CORS

contents

CORS(Cross-Origin Resource Sharing, 교차 출처 리소스 공유) 는 웹 페이지가 자신을 제공한 도메인(Origin)이 아닌 다른 도메인의 서버에 있는 제한된 리소스에 접근할 수 있도록 허용하는 브라우저 보안 메커니즘입니다.

CORS를 이해하려면 먼저 CORS가 완화시켜 주는 보안 규칙인 동일 출처 정책(SOP, Same-Origin Policy) 을 알아야 합니다.

1. 핵심 문제: 동일 출처 정책 (SOP)

기본적으로 웹 브라우저는 '동일 출처 정책(SOP)'을 강제합니다. 이는 한 페이지(예: evil.com)의 악성 스크립트가 다른 페이지(예: yourbank.com)의 민감한 데이터를 탈취하지 못하도록 막기 위함입니다.

두 URL이 "동일 출처(Same Origin)"로 간주되려면 다음 세 가지가 정확히 일치해야 합니다:

  1. 프로토콜 (예: https)
  2. 호스트 (예: example.com)
  3. 포트 (예: :443 또는 :8080)

이 중 하나라도 다르면, 브라우저는 보안상 이유로 스크립트가 응답을 읽는 것을 차단합니다. CORS는 브라우저에게 "이 특정 교차 출처(Cross-Origin) 요청은 안전하니 허용해도 된다"고 알려주는 표준 방법입니다.


2. CORS의 동작 방식

CORS는 요청을 서버로 보내는 것을 막는 필터가 아니라, 서버로부터 돌아온 응답을 브라우저가 읽지 못하게 막는 메커니즘입니다.

브라우저가 다른 출처(Cross-Origin)로 요청을 보낼 때 특정 헤더를 추가합니다. 서버는 이에 대해 적절한 CORS 헤더로 응답해야 합니다. 만약 서버의 헤더가 접근을 허용하지 않는다면, 브라우저는 응답 데이터를 버리고 자바스크립트 에러를 발생시킵니다.

CORS 상호작용에는 크게 단순 요청(Simple Requests)프리플라이트 요청(Preflighted Requests) 두 가지 유형이 있습니다.

A. 단순 요청 (Simple Requests)

표준 HTML form 전송과 유사하여 비교적 "안전하다"고 간주되는 요청들입니다. 다음 조건을 모두 만족해야 합니다:

동작 흐름:

  1. 브라우저: Origin 헤더를 포함하여 요청을 보냅니다 (예: Origin: https://frontend.com).
  2. 서버: 데이터와 함께 Access-Control-Allow-Origin 헤더를 응답으로 보냅니다.
  3. 브라우저: 돌아온 Access-Control-Allow-Origin 헤더가 요청한 Origin과 일치하는지 확인합니다. 일치하면 자바스크립트가 데이터를 받습니다.

B. 프리플라이트 요청 (Preflighted Requests)

Authorization 같은 커스텀 헤더를 보내거나, PUT, DELETE 메서드를 사용하거나, application/json 타입의 데이터를 보낼 때 발생합니다. 브라우저는 "이 요청은 서버의 데이터를 변경할 수도 있으니, 먼저 허락을 받아야겠다"라고 판단합니다.

동작 흐름:

  1. 브라우저 (프리플라이트): 실제 요청을 보내기 에, 자동으로 OPTIONS 메서드 요청을 서버로 보냅니다.
    • 질문 내용: "제가 PUT 메서드와 Authorization 헤더를 사용해도 될까요?"
  2. 서버: OPTIONS 요청에 대해 200 또는 204 상태 코드와 함께 허용 여부가 담긴 헤더로 응답합니다.
  3. 브라우저: 허락이 떨어지면, 그때 비로소 실제(Actual) 요청을 보냅니다.

3. 핵심 HTTP 헤더

CORS 동작을 제어하는 주요 헤더들입니다.

요청 헤더 (브라우저가 전송)

응답 헤더 (서버가 전송)


4. 자격 증명 (Credentials: 쿠키 및 인증)

기본적으로 교차 출처 요청은 쿠키나 HTTP 인증 정보를 보내지 않습니다.

자격 증명을 포함하려면:

  1. 클라이언트(JS)에서 withCredentials 옵션을 true로 설정해야 합니다.
  2. 서버는 반드시 Access-Control-Allow-Credentials: true로 응답해야 합니다.
  3. 중요 규칙: Access-Control-Allow-Credentialstrue인 경우, Access-Control-Allow-Origin 헤더에 와일드카드(*)를 쓸 수 없습니다. 반드시 명시적인 도메인(예: https://frontend.com)을 적어줘야 합니다.

5. 흔한 CORS 에러

6. 보안 모범 사례 (Best Practices)

references