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-Credentials가 true인 경우, Access-Control-Allow-Origin 헤더에 와일드카드(*)를 쓸 수 없습니다. 반드시 명시적인 도메인(예: https://frontend.com)을 적어줘야 합니다.

5. 흔한 CORS 에러

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

references