
CORS란? API 호출이 막히는 이유 쉽게 이해하기
프론트엔드와 백엔드를 처음 연결해보면 높은 확률로 한 번쯤 보게 되는 오류가 있습니다. 바로 CORS 오류입니다.
브라우저 콘솔에서 이런 메시지를 본 적이 있을 겁니다.
Access to fetch at 'https://api.example.com'
from origin 'http://localhost:3000'
has been blocked by CORS policyAPI 서버가 죽었나?
프론트엔드 코드가 잘못됐나?
fetch가 문제인가?
하지만 대부분의 CORS 오류는 코드 문제가 아니라 브라우저 보안 정책 때문에 발생합니다.
이번 글에서는 CORS란 무엇인지, 왜 API 호출이 막히는지, Same-Origin Policy, Preflight Request, 그리고 실무에서 CORS를 어떻게 해결하는지까지 초보자 기준으로 쉽게 정리해보겠습니다.
CORS란 무엇인가?
CORS는 Cross-Origin Resource Sharing의 줄임말입니다. 쉽게 말하면, 다른 출처(Origin)끼리 리소스를 공유할 수 있게 허용하는 규칙 입니다.
여기서 핵심은 Origin(출처) 입니다.
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:3000 | localhost:3000 | 허용 |
| localhost:3000 | localhost:8000 | 차단 가능 |
| win-j.com | api.win-j.com | 설정 필요 |
이 정책이 없으면 악성 사이트가 사용자의 로그인 정보를 악용할 수 있습니다.
Same-Origin Policy는 불편해 보이지만 웹 보안에서 매우 중요한 역할을 합니다.
CORS 동작 흐름
CORS 동작은 생각보다 단순합니다.
1. 브라우저가 API 요청을 보냄
예:
fetch("https://api.example.com/users")
2. 서버가 허용 여부를 응답함
응답 Header 예시:
Access-Control-Allow-Origin: http://localhost:3000
3. 브라우저가 응답 사용 여부 결정
허용됨 → 응답 사용 가능
허용 안 됨 → 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만 허용
이렇게 설정합니다.
운영 환경에서는 와일드카드(*)보다 허용 도메인을 명확하게 지정하는 것이 좋습니다.
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 통신 구조가 훨씬 명확하게 보이기 시작합니다.
첫 댓글을 남겨보세요.