CORS(Cross-Origin Resource Sharing)란?

시훈·2025년 4월 22일

웹 개발을 하다 보면 자주 마주치는 문제 중 하나가 바로 CORS 에러다. 이 글에서는 CORS가 무엇인지, 왜 필요한지, 그리고 실제로 어떻게 작동하는지를 쉽게 정리한다.


🚧 CORS(Cross-Origin Resource Sharing)란?

CORS는 교차 출처 리소스 공유를 의미한다. 말 그대로 출처가 다른 서버 간 리소스를 공유할 수 있도록 허용하는 보안 메커니즘이다.

❗ 출처(origin)는 프로토콜 + 도메인 + 포트의 조합이다.

예를 들어, 다음 두 출처는 서로 다르다:

  • https://example.com (443 포트)
  • http://example.com (80 포트)

이처럼 서로 다른 출처 간에 요청이 발생하면 브라우저는 보안 상의 이유로 요청을 차단한다. 이 제한을 풀어주는 것이 CORS다.


🔐 왜 CORS가 필요한가?

과거에는 CSRF(Cross Site Request Forgery) 공격이 자주 발생했다. 이는 사용자의 브라우저를 이용해 의도치 않은 요청을 다른 서비스로 전송하게 만드는 방식이다.

이러한 공격을 막기 위해 브라우저는 SOP(Same-Origin Policy, 동일 출처 정책)을 도입했다. 이는 동일한 출처에서만 요청을 허용하는 정책이다.

하지만, 현대 웹 환경에서는 프론트엔드와 백엔드가 서로 다른 도메인이나 포트에서 동작하는 경우가 많기 때문에 SOP만으로는 부족하다. 그래서 이를 보완하기 위해 CORS가 사용된다.


⚙️ CORS의 동작 방식

브라우저는 요청을 보낼 때 Origin 헤더를 자동으로 포함한다. 서버는 Access-Control-Allow-Origin 응답 헤더를 통해 이 요청을 허용할지를 판단한다.

📥 요청 예시

GET /api/data HTTP/1.1
Origin: http://localhost:3000

📤 응답 예시

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://localhost:3000

만약 응답에 해당 헤더가 없다면 브라우저는 응답을 차단하고 CORS 오류를 발생시킨다.


📌 요청 유형별 CORS 흐름

✅ Simple Request

단순 요청으로 분류되기 위해서는 다음 조건을 만족해야 한다:

  • 메서드: GET, POST, HEAD
  • Content-Type: application/x-www-form-urlencoded, multipart/form-data, text/plain
  • 사용자 정의 헤더가 없어야 한다

이 경우 브라우저는 별도의 사전 요청 없이 바로 요청을 전송한다.

🔄 Preflight Request

Simple Request 조건을 만족하지 않는 경우, 브라우저는 실제 요청 전에 사전 요청(OPTIONS)을 보낸다. 이를 Preflight Request라고 한다.

OPTIONS /api/data HTTP/1.1
Origin: http://localhost:3000
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type, Authorization

서버는 다음과 같이 응답해야 한다:

Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 3600

🔑 Credential Request

쿠키나 인증 토큰 같은 민감한 정보를 포함하는 요청의 경우 자격 요청(Credential Request)이 발생한다.

  • 요청은 withCredentials: true로 설정한다.
  • 서버는 Access-Control-Allow-Credentials: true를 설정해야 하며, Access-Control-Allow-Origin에 와일드카드는 사용할 수 없다.
Access-Control-Allow-Origin: https://myapp.com
Access-Control-Allow-Credentials: true

💡 실제 코드 예시

✅ Axios에서 Credential 요청 보내기

axios.get('https://api.example.com/user', {
  withCredentials: true
});

✅ Express.js에서 CORS 설정

const express = require('express');
const cors = require('cors');

const app = express();

app.use(cors({
  origin: 'http://localhost:3000',
  credentials: true
}));

📚 요약 테이블

요청 유형설명조건
Simple Request바로 요청, 사전 요청 없음메서드/헤더 제한 있음
Preflight RequestOPTIONS로 사전 요청커스텀 헤더나 메서드 사용 시
Credential Request인증 정보 포함, 보안 강화 필요Allow-Credentials: true 필요

✅ 마무리

CORS는 웹 보안을 지키면서도 유연한 리소스 공유를 가능하게 해주는 중요한 기능이다. 백엔드 개발자는 서버에서 적절한 CORS 헤더 설정을 통해 클라이언트가 다른 출처에서 안전하게 리소스를 요청할 수 있도록 해야 한다.

브라우저가 요청을 막는다고 해도, 서버가 명확한 허용 정책을 지정하면 원활하게 통신할 수 있다.

profile
Backend Developer / Cloud Engineer

0개의 댓글