API 호출 차단 설명
CORS란? API 호출 차단 설명


CORS란? API 호출이 막히는 이유 쉽게 이해하기

프론트엔드와 백엔드를 처음 연결해보면 높은 확률로 한 번쯤 보게 되는 오류가 있습니다. 바로 CORS 오류입니다.

브라우저 콘솔에서 이런 메시지를 본 적이 있을 겁니다.

Access to fetch at 'https://api.example.com'
from origin 'http://localhost:3000'
has been blocked by CORS policy
처음 보면 이런 생각이 듭니다.

API 서버가 죽었나?
프론트엔드 코드가 잘못됐나?
fetch가 문제인가?

하지만 대부분의 CORS 오류는 코드 문제가 아니라 브라우저 보안 정책 때문에 발생합니다.

이번 글에서는 CORS란 무엇인지, 왜 API 호출이 막히는지, Same-Origin Policy, Preflight Request, 그리고 실무에서 CORS를 어떻게 해결하는지까지 초보자 기준으로 쉽게 정리해보겠습니다.


CORS란 무엇인가?

CORS는 Cross-Origin Resource Sharing의 줄임말입니다. 쉽게 말하면, 다른 출처(Origin)끼리 리소스를 공유할 수 있게 허용하는 규칙 입니다.

여기서 핵심은 Origin(출처) 입니다.

Origin은 아래 3가지 조합으로 결정됩니다.
  • Protocol (http / https)

  • Domain

  • Port

예를 들어:

도메인은 같아 보여도 Port가 다르기 때문에 다른 Origin입니다. 즉, 브라우저는 이 둘을 다른 출처로 판단합니다.


API 호출은 왜 막히는 걸까?

초보자가 가장 헷갈리는 부분입니다. 

중요한 포인트는 이것입니다.

CORS는 서버가 막는 것이 아니라 브라우저가 막는 것입니다.

예를 들어:

  • 프론트엔드 → localhost:3000

  • API 서버 → localhost:8000

프론트엔드가 API 호출을 시도합니다.

fetch("http://localhost:8000/api/users")

API 서버가 응답을 정상적으로 보내더라도, 브라우저가 보안상 위험하다고 판단하면 응답을 차단합니다.

즉 : 
  • 요청은 실제로 서버까지 갔을 수 있음

  • 서버도 응답했을 수 있음

  • 하지만 브라우저가 응답 사용을 막음

이것이 CORS 오류입니다.


Same-Origin Policy 쉽게 이해하기

CORS를 이해하려면 먼저 Same-Origin Policy를 알아야 합니다. Same-Origin Policy는 브라우저의 핵심 보안 정책입니다.

쉽게 말하면, 같은 출처끼리만 자유롭게 통신 가능 입니다.

비유해보면:

  • 브라우저 = 출입 관리 직원

  • API 서버 = 건물

  • 요청 = 방문 요청

브라우저는 “허가되지 않은 외부 건물 출입”을 제한합니다.

예를 들어:

프론트엔드API 서버결과
localhost:3000localhost:3000허용
localhost:3000localhost:8000차단 가능
win-j.comapi.win-j.com설정 필요

이 정책이 없으면 악성 사이트가 사용자의 로그인 정보를 악용할 수 있습니다.

TIP

Same-Origin Policy는 불편해 보이지만 웹 보안에서 매우 중요한 역할을 합니다.


CORS 동작 흐름

CORS 동작은 생각보다 단순합니다.


1. 브라우저가 API 요청을 보냄

예:

fetch("https://api.example.com/users")

2. 서버가 허용 여부를 응답함

응답 Header 예시:

Access-Control-Allow-Origin: http://localhost:3000

3. 브라우저가 응답 사용 여부 결정

브라우저가 Header를 확인합니다.
  • 허용됨 → 응답 사용 가능

  • 허용 안 됨 → CORS 오류

즉 핵심은 서버 응답 Header입니다.


Preflight Request란?

어떤 API 호출은 실제 요청 전에 먼저 확인 요청을 보냅니다. 이걸 Preflight Request라고 합니다.

보통 OPTIONS 요청으로 먼저 전송됩니다.

예:

OPTIONS /api/users
브라우저가 서버에 먼저 묻습니다.

POST 요청 보내도 돼?
Authorization Header 써도 돼?

서버가 허용하면 실제 요청이 진행됩니다.

응답 예시:

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

특히 아래 경우 Preflight가 자주 발생합니다.

  • POST 요청

  • PUT / DELETE

  • JSON Body

  • Authorization Header 포함


CORS 오류 예시

가장 흔한 오류 메시지입니다.

No 'Access-Control-Allow-Origin' header present

의미:

서버가 CORS 허용 Header를 보내지 않음


또는:

Blocked by CORS policy

의미:

브라우저가 응답 차단


코드 예제

JavaScript fetch 예시

fetch("http://localhost:8000/api/data")
  .then(res => res.json())
  .then(data => console.log(data))
  .catch(err => console.error(err));

코드는 문제 없어 보여도 서버 CORS 설정이 없으면 오류가 납니다.


Node.js Express 설정 예시

Express에서는 cors 패키지를 많이 사용합니다.

설치:

npm install cors

설정:

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

const app = express();

app.use(cors({
  origin: "http://localhost:3000"
}));

app.listen(8000);

Django 설정 예시

Django에서는 django-cors-headers를 많이 사용합니다.

설치:

pip install django-cors-headers

settings.py:

INSTALLED_APPS = [
    "corsheaders",
]

middleware:

MIDDLEWARE = [
    "corsheaders.middleware.CorsMiddleware",
]

허용 Origin:

CORS_ALLOWED_ORIGINS = [
    "http://localhost:3000",
]

자주 발생하는 CORS 오류와 해결법

1. localhost 포트 다름

원인:

  • 3000 ↔ 8000

해결:

  • 서버 CORS 허용 설정


2. Access-Control-Allow-Origin 누락

원인:

  • 서버 Header 미설정

해결:

  • 서버 응답 Header 추가


3. Authorization Header 차단

원인:

  • Header 허용 안 됨

해결:

Access-Control-Allow-Headers: Authorization

4. Cookie 인증 문제

원인:

  • credentials 설정 문제


개발 환경에서 임시 해결 방법

개발 환경에서는 아래 방식도 사용합니다.

  • 프록시 서버

  • Vite proxy

  • Webpack proxy

예:

proxy: {
  "/api": "http://localhost:8000"
}

하지만 주의할 점:

  • 브라우저에서 CORS 우회 플러그인 설치
  • Access-Control-Allow-Origin: *

이런 방식은 개발 중 테스트용으로만 사용해야 합니다.


운영 환경에서 안전하게 설정하기

운영 환경에서는 모든 Origin 허용은 피하는 것이 좋습니다.

좋은 예:

Access-Control-Allow-Origin: https://win-j.com

주의할 예:

Access-Control-Allow-Origin: *

실무에서는 보통:

  • 개발 서버 허용

  • 운영 도메인만 허용

  • 필요한 Method만 허용

이렇게 설정합니다.

TIP 
운영 환경에서는 와일드카드(*)보다 허용 도메인을 명확하게 지정하는 것이 좋습니다.

CORS와 쿠키, JWT 사용 시 주의점

이전 글의 Cookie, Session, JWT와도 연결됩니다.

Cookie 인증

쿠키 기반 인증은 추가 설정이 필요합니다.

예:

fetch(url, {
  credentials: "include"
})

서버도 설정 필요:

Access-Control-Allow-Credentials: true

JWT 인증

JWT는 보통 Authorization Header 사용.

Authorization: Bearer TOKEN

이 경우 CORS에서 Authorization Header 허용이 필요합니다.


이런 사람에게 추천합니다

이 글은 이런 사람에게 추천합니다.

  • CORS 오류를 처음 만난 사람

  • 프론트엔드와 백엔드를 연결 중인 사람

  • React / Vue 입문자

  • API 호출이 자꾸 막히는 사람

  • Django / Express 백엔드 개발자

  • JWT, Cookie 인증 구조를 함께 이해하고 싶은 사람


마무리

CORS는 초보자가 가장 자주 만나는 API 오류 중 하나입니다.

핵심만 정리하면:

  • CORS는 브라우저 보안 정책

  • Same-Origin Policy 때문에 발생

  • 서버가 아니라 브라우저가 차단

  • 해결은 서버 CORS 설정에서 해야 함

  • 운영 환경에서는 안전하게 Origin 제한 필요

처음에는 어렵게 느껴질 수 있지만 핵심은 간단합니다. 브라우저가 “이 API 호출을 허용해도 되는가?”를 확인하는 과정 HTTP Header, JWT, Cookie/Session과 함께 이해하면 API 통신 구조가 훨씬 명확하게 보이기 시작합니다.