100% 브라우저 메모리 연산 • 서버 로그 수집 제로 • 즉각적인 실행
Curious Techie개발자 툴박스
← 전체 가이드/웹 표준•9 min read

CORS 및 동일 출처 정책(SOP)의 동작 원리

교차 출처 리소스 공유(CORS) 완벽 해설: 브라우저 프리플라이트 OPTIONS 요청, 응답 헤더 및 보안 취약점 방지.

ⓘ핵심 요약 (Key Takeaways)
  • 동일 출처 정책(SOP)은 프로토콜, 호스트, 포트가 다른 출처의 리소스 응답을 읽지 못하도록 브라우저가 차단하는 보안 규칙입니다.
  • CORS는 백엔드 서버가 특정 외부 출처의 요청을 명시적으로 허용할 수 있게 해주는 표준 규격입니다.
  • 복잡한 요청 전송 시 브라우저는 먼저 OPTIONS 프리플라이트 요청을 전송하여 허용 여부를 사전 확인합니다.
  • 쿠키나 인증 헤더가 포함된 요청에서는 와일드카드 Access-Control-Allow-Origin: * 설정이 엄격히 금지됩니다.
  • CORS는 전적으로 클라이언트 웹 브라우저가 검증하고 강제하는 보안 메커니즘입니다.
CT
Curious-Techie Engineering Team검증된 작성자

Web Protocols & Security Architecture Research

발행일:
•
수정일:
•9 min read
검토자: Curious-Techie Architecture Peer Review Group
Primary Question • Core Architectural Definition

What is CORS?

By default, web browsers apply the Same-Origin Policy (SOP) to isolate documents and prevent malicious websites from reading sensitive data. Under SOP, client-side scripts running on https://app.curious-techie.com cannot read responses fetched from https://api.curious-techie.com unless the destination server explicitly enables CORS.

Two URLs share the same origin if and only if their Protocol (Scheme), Host (Domain), and Port are strictly identical:

https://api.example.com:443 vs https://example.com:443CROSS-ORIGIN (Subdomain mismatch)
http://example.com:80 vs https://example.com:443CROSS-ORIGIN (Protocol mismatch)
https://example.com/app vs https://example.com/apiSAME-ORIGIN (Path differences allowed)
#
Answer-Ready Section • Standalone Statements

Key Facts: Cross-Origin Resource Sharing (CORS)

  • CORS is enforced exclusively by client web browsers, not by server firewalls, command-line utilities, or backend scripts.
  • A web origin consists strictly of three components: URI Scheme (protocol), Host (domain name or IP), and Port number.
  • Two URLs are cross-origin if scheme, host, or port differ, even if they share the exact same top-level domain.
  • Non-simple HTTP requests trigger an automatic preflight HTTP OPTIONS probe before the browser transmits the actual payload.
  • The Fetch Standard explicitly forbids the wildcard Access-Control-Allow-Origin: * when Access-Control-Allow-Credentials: true is set.
  • CORS does not prevent an HTTP request from hitting an API server; CORS prevents the web browser from releasing the response body to untrusted JavaScript.
Factual statements formulated to be self-contained and independently verifiable.
Contextual Graph • Semantic Connections

How CORS Relates to Other Entities

Cross-Origin Resource Sharing (CORS)→ relaxes →Same-Origin Policy (SOP)

CORS acts as a standardized, server-controlled exception mechanism to the browser default Same-Origin Policy.

Cross-Origin Resource Sharing (CORS)→ specifies →Access-Control-Allow-Origin

The Access-Control-Allow-Origin HTTP response header dictates which requesting origins are permitted to read the response payload.

Cross-Origin Resource Sharing (CORS)→ depends on →HTTP OPTIONS Preflight Request

Browsers send an automated HTTP OPTIONS preflight request to verify server authorization before executing mutating methods (PUT, DELETE) or sending custom headers.

Cross-Origin Resource Sharing (CORS)→ governs →Fetch API & XMLHttpRequest

Client-side network requests initiated through window.fetch() or XMLHttpRequest are subject to browser CORS validation.

Secondary Question • Problem Space & Evolution

Why does CORS exist?

Direct Answer:CORS exists to allow decoupled modern web applications—such as Single Page Applications hosted on edge CDNs communicating with distinct microservice API backends—to legitimately access cross-domain data without eliminating the browser's essential Same-Origin Policy protection against cross-site data exfiltration.

In the early web, client-side JavaScript was restricted entirely to contacting the exact server that delivered the HTML page. As software architecture evolved toward decoupled architectures (microservices, cloud API gateways, and external SaaS providers), modern applications required a standardized protocol to authorize legitimate cross-domain data sharing.

Without CORS, browsers would either have to block all cross-domain API integrations (crippling modern web apps) or disable origin checks completely (leaving users vulnerable to malicious websites executing authenticated calls against internal company intranets or banking dashboards).

Secondary Question • Protocol Mechanism

How does CORS work?

Direct Answer:CORS works through an automated HTTP header handshake: when JavaScript initiates a cross-origin request, the browser automatically appends an Origin request header; the destination server evaluates this origin and returns corresponding Access-Control-* headers indicating whether the browser is permitted to share the response with the script.

The conversation relies on specific standardized HTTP response headers:

  • Access-Control-Allow-Origin: Specifies allowed requesting origins (e.g. https://curious-techie.com or *).
  • Access-Control-Allow-Methods: Lists permitted HTTP methods (e.g. GET, POST, PUT, DELETE, OPTIONS).
  • Access-Control-Allow-Headers: Declares acceptable custom request headers (e.g. Content-Type, Authorization).
  • Access-Control-Allow-Credentials: Tells the browser whether cookies and HTTP authorization headers may be exposed to JavaScript (requires explicit true).
  • Access-Control-Max-Age: Defines the duration in seconds that the browser may cache preflight verification results.
Secondary Question • Request Lifecycle & Probe

What is a preflight request?

Direct Answer:A preflight request is an automated HTTP OPTIONS probe dispatched by the browser before sending a "non-simple" cross-origin request (such as PUT, DELETE, or any request carrying custom headers like Authorization or JSON bodies) to verify whether the server authorizes the operation before actual payload transmission.

A request is categorized as a "Simple Request" and bypasses preflight only if it meets strict criteria:

  • It uses only GET, POST, or HEAD methods.
  • Its headers contain only browser-standard safe headers (Accept, Accept-Language, Content-Language).
  • Its Content-Type is strictly limited to application/x-www-form-urlencoded, multipart/form-data, or text/plain.

Any modern REST or GraphQL API request carrying Content-Type: application/json or a bearer token header triggers an OPTIONS preflight. If the server does not handle HTTP OPTIONS with 200/204 status and valid CORS headers, the browser immediately blocks the main request.

Secondary Question • Practical Implementation & Code

How do you fix a CORS error?

Direct Answer:You fix a CORS error by configuring the backend server or API gateway to respond with matching Access-Control-Allow-Origin, Access-Control-Allow-Methods, and Access-Control-Allow-Headers headers for both preflight OPTIONS and substantive API requests, or by routing frontend traffic through a same-origin reverse proxy during development.
Production-Ready CORS Configuration (Express / Node.js)javascript
import express from 'express';
import cors from 'cors';

const app = express();

// Whitelist of approved origins
const allowedOrigins = [
  'https://curious-techie.com',
  'https://app.curious-techie.com',
  'http://localhost:3000' // Local development
];

app.use(cors({
  origin: (origin, callback) => {
    // Allow non-browser requests (e.g. mobile apps, cURL, server-to-server)
    if (!origin || allowedOrigins.includes(origin)) {
      callback(null, true);
    } else {
      callback(new Error('Cross-Origin Request Blocked by CORS Policy'));
    }
  },
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
  allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'],
  credentials: true, // Allow cookies and authorization headers
  maxAge: 86400      // Cache preflight OPTIONS responses for 24 hours
}));

// Handle preflight explicitly across all routes
app.options('*', cors());

Client-Side Fetch Invocation:

const response = await fetch('https://api.curious-techie.com/v1/user/profile', {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer ' + authToken
  },
  credentials: 'include' // Required when exchanging cookies across origins
});
Secondary Question • Security Model Clarification

Can CORS protect an API?

Direct Answer:No, CORS cannot protect an API against unauthorized access or malicious attacks. CORS is strictly enforced by web browsers to protect end-users from having their authenticated browser sessions exploited by unauthorized third-party websites; command-line utilities (cURL, Postman, Python scripts) and malicious bots bypass CORS entirely.

A server's API endpoints must always be defended by real security controls: authentication tokens (JWTs, session IDs), cryptographic signature verification, rate limiting, and input sanitization.

Relying on CORS as a security firewall is dangerous because any adversary can forge the Origin header using tools like cURL or Node.js scripts:

curl -H "Origin: https://evil.com" -H "Authorization: Bearer token" https://api.curious-techie.com/v1/data
Technical Realities • Myth Busting

What are common misconceptions about CORS?

Myth #1: CORS is a Server Firewall

"CORS prevents attackers from querying our backend database."

Technical Reality: CORS only prevents web browsers from giving the response payload back to JavaScript. Attackers using bots or command line tools can still query unprotected endpoints freely.

Myth #2: Wildcard * Works with Cookies

"Setting Access-Control-Allow-Origin: * allows credentialed login calls from anywhere."

Technical Reality: The WHATWG Fetch Standard explicitly forbids * when Access-Control-Allow-Credentials: true is present. The browser will deliberately reject the response.

Myth #3: Fix It in Frontend JavaScript

"I can resolve this CORS error by adding headers to my frontend fetch() call."

Technical Reality: Adding custom headers in frontend JavaScript often makes the problem worse by triggering preflight requests. CORS headers must be returned by the server, not the client.

Myth #4: Blocked Requests Never Run on the Server

"If the browser throws a CORS error, the server never received or processed the request."

Technical Reality: For simple GET/POST requests that bypass preflight, the server processes the request and executes mutations; the browser merely blocks JavaScript from reading the response.

Direct Answers • Technical FAQ

Frequently Asked Questions About CORS

Q:Why do I see a CORS error in my browser console but the request works in Postman?

Direct Answer:Because CORS is an exclusively browser-enforced security mechanism designed to stop untrusted websites from reading your private data. Postman is a developer tool, not a browser executing third-party scripts, so it ignores CORS headers.

The server usually returns HTTP 200 OK to both tools, but Chrome or Firefox checks for Access-Control-Allow-Origin and hides the response from JavaScript when that header is missing.

Q:How can I test an API locally during development without configuring CORS on staging?

Direct Answer:Configure a local development reverse proxy in Vite, Next.js, or Webpack to forward /api/* requests to the target server, turning cross-origin browser calls into same-origin requests.

Because the browser connects to localhost:3000/api, no cross-origin boundary is crossed and no CORS headers are required.

Q:What is the difference between CORS and CSRF?

Direct Answer:CORS controls whether a website can READ responses from another origin; CSRF (Cross-Site Request Forgery) tricks the browser into WRITING unauthorized requests using the user's cookies.

CORS does not stop simple POST requests from reaching the server, which is why CSRF tokens or SameSite=Lax cookies remain essential for state-changing endpoints.

Authoritative Sourcing & Verification

References & Primary Sources

Every source below directly substantiates technical statements and protocol behaviors explained in CORS (Cross-Origin Resource Sharing). Curious-Techie prioritizes official Internet standards (IETF RFCs, W3C Recommendations, WHATWG specifications) and established security bodies (OWASP, NIST). Zero sponsored or secondary links.

  1. [1]WHATWGPrimary SpecificationWHATWG Fetch • § 3.2 HTTP-network-fetch
    Verified Primary Source
    Technical Claim Supported:

    Defines the normative browser CORS protocol, preflight cache validation (Access-Control-Max-Age), and the prohibition of wildcard Access-Control-Allow-Origin: * when Access-Control-Allow-Credentials is true.

    “For a CORS request with credentials, the server cannot specify a wildcard for Access-Control-Allow-Origin. It must specify an explicit origin.”
  2. [2]IETFPrimary SpecificationRFC 9110 • § 9.2.1
    Verified Primary Source
    Technical Claim Supported:

    Specifies that the Origin request header indicates the scheme, host, and port of the originating context and must not be altered by user-agent JavaScript.

  3. [3]OWASPAuthoritative Security StandardOWASP Cheat Sheet Series • Origin Validation & Credentials
    Verified Primary Source
    Technical Claim Supported:

    Documents the security risks of dynamic origin reflection without strict server-side allowlist verification (CORS misconfiguration vulnerabilities).

  4. [4]MDNDeveloper Authority (MDN)MDN Web Docs • CORS Preflight & Simple Requests
    Verified Primary Source
    Technical Claim Supported:

    Provides developer reference for simple requests vs. preflighted requests and safelisted headers (Accept, Accept-Language, Content-Language, Content-Type).