CORS
Cross-Origin Resource Sharing
다른 출처의 리소스 접근을 제어하는 보안 메커니즘. 브라우저가 강제. 서버에서 허용 설정.
Cross-Origin Resource Sharing
다른 출처의 리소스 접근을 제어하는 보안 메커니즘. 브라우저가 강제. 서버에서 허용 설정.
CORS(Cross-Origin Resource Sharing)는 웹 브라우저가 다른 출처(도메인, 프로토콜, 포트)의 리소스에 접근할 때 적용되는 보안 메커니즘입니다. 기본적으로 브라우저는 동일 출처 정책(Same-Origin Policy)을 따라 다른 출처의 리소스 접근을 차단하는데, CORS는 서버가 명시적으로 허용한 출처에서만 접근을 허용합니다.
CORS의 배경은 웹 보안입니다. 만약 제한이 없다면 악성 사이트에서 사용자의 은행 사이트 API를 호출해 민감한 정보를 탈취할 수 있습니다. CORS는 서버가 Access-Control-Allow-Origin 헤더로 허용된 출처를 명시하고, 브라우저가 이를 확인해서 불허된 요청을 차단합니다.
CORS에는 두 가지 요청 유형이 있습니다. 단순 요청(Simple Request)은 GET, POST(특정 Content-Type)로 바로 보내지고, 프리플라이트 요청(Preflight Request)은 PUT, DELETE나 커스텀 헤더가 있을 때 OPTIONS 메서드로 먼저 허용 여부를 확인합니다.
실무에서 CORS 에러는 프론트엔드 개발자가 가장 자주 마주하는 에러 중 하나입니다. 로컬 개발 시 localhost와 API 서버 출처가 달라서 발생하며, 백엔드에서 적절한 CORS 헤더를 설정하거나, 프록시를 통해 우회합니다.
// Express.js CORS 설정
const express = require('express');
const cors = require('cors');
const app = express();
// 모든 출처 허용 (개발용, 프로덕션에서 비권장)
app.use(cors());
// 특정 출처만 허용 (권장)
app.use(cors({
origin: ['https://myapp.com', 'https://admin.myapp.com'],
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true, // 쿠키 허용
maxAge: 86400, // 프리플라이트 캐시 24시간
}));
// 라우트별 CORS 설정
app.get('/public', cors(), (req, res) => {
res.json({ message: '누구나 접근 가능' });
});
app.get('/private', cors({ origin: 'https://admin.myapp.com' }), (req, res) => {
res.json({ message: '관리자만 접근 가능' });
});
// Next.js API Route에서 CORS 설정
// pages/api/data.ts
export default function handler(req, res) {
res.setHeader('Access-Control-Allow-Origin', 'https://myapp.com');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
if (req.method === 'OPTIONS') {
return res.status(200).end(); // 프리플라이트 응답
}
res.json({ data: 'Hello' });
}
"로컬에서 API 호출할 때 CORS 에러 나요. 백엔드에서 localhost:3000을 허용 목록에 추가해주시거나, Next.js rewrites로 프록시 설정할게요. 프로덕션에서는 실제 도메인만 허용하면 됩니다."
"CORS는 브라우저의 보안 정책입니다. 서버가 Access-Control-Allow-Origin 헤더로 허용 출처를 지정하고, 브라우저가 이를 검증해요. PUT이나 DELETE 같은 요청은 프리플라이트로 OPTIONS 요청을 먼저 보내서 허용 여부를 확인합니다."
"Access-Control-Allow-Origin: * 설정은 프로덕션에서 위험해요. 허용할 도메인을 명시하고, credentials: true일 때는 와일드카드가 아예 안 됩니다. 환경별로 분리하세요."
모든 출처를 허용하면 CSRF 공격에 취약해집니다. 프로덕션에서는 반드시 허용할 도메인을 명시하세요.
매 요청마다 OPTIONS 호출이 발생하면 성능이 저하됩니다. Access-Control-Max-Age 헤더로 캐싱하세요.
허용 출처를 환경변수로 관리하고, credentials 사용 시 와일드카드 대신 명시적 출처를 설정하세요. 필요한 메서드와 헤더만 허용합니다.