Tech Notes

항상 보는 에러 CORS와 Preflight Request 완전 정복

miracle-tech 2025. 10. 10. 18:09
728x90
반응형
CORS와 Preflight Request 완전 정복

🌐 CORS와 Preflight Request

13살도 이해하는 완전 정복 가이드

1. CORS가 뭔가요? 🤔

집 방문 비유로 이해하기

❌ CORS 없이 (거절당함)

너: "안녕? 놀러 왔어!"

친구 엄마: "너희 집 주소가 어디야?"

너: "123번지요"

친구 엄마: "우린 456번지만 받아. 돌아가!"

→ 거절당함 😢

✅ CORS 있으면 (환영받음)

친구 엄마: "123번지에서 오는 친구는 환영해!"

너: "안녕? 놀러 왔어!"

친구 엄마: "어서와!"

→ 환영받음 🎉

🌐 웹사이트로 치면

프론트엔드 (http://localhost:8080)

"안녕, 백엔드야! 데이터 줘!"

❌ 브라우저가 막음

"너희 집 주소(Origin)가 달라서 안 돼!"

백엔드 (http://localhost:3000)

"나는 8080에서 오는 애들 환영해!"

✅ 브라우저가 허용

"오케이, 주인이 허락했네!"

2. Preflight Request가 뭔가요? 🚦

더 까다로운 방문

일반 방문 (Simple Request)

너: *똑똑* "안녕? 들어가도 돼?"

친구 엄마: "어서와!" ✅

→ 바로 들어감

까다로운 방문 (Preflight Request)

너: "나 큰 짐 들고 갈 건데..." (복잡한 요청)

친구 엄마: "잠깐! 뭐 가져올 건데?" 🤔

너: "게임기랑 간식이요" (OPTIONS 요청)

친구 엄마: "오케이, 들어와!" ✅

너: *게임기 들고 입장*


만약 친구 엄마가 "안 돼!" ❌ 하면

→ 너는 들어갈 수 없음 (Preflight 실패)

📊 언제 Preflight가 발생하나요?

요청 타입 예시 Preflight 필요?
Simple GET 요청 ❌ 불필요
Simple 기본 POST (form 데이터) ❌ 불필요
Preflight POST + JSON ✅ 필요
Preflight 커스텀 헤더 (Authorization) ✅ 필요
Preflight PUT, DELETE 메서드 ✅ 필요

3. Preflight 동작 과정 🔄

1단계: 브라우저가 먼저 물어봄 (Preflight)
OPTIONS http://localhost:3000/api/users Origin: http://localhost:8080 Access-Control-Request-Method: POST ← "POST 써도 돼?" Access-Control-Request-Headers: Content-Type ← "이 헤더 써도 돼?"
2단계: 백엔드가 답변 (중요!)
HTTP/1.1 200 OK ← 이게 중요! 200이어야 함! Access-Control-Allow-Origin: http://localhost:8080 ← "너 환영해" Access-Control-Allow-Methods: POST, GET, PUT ← "POST 가능" Access-Control-Allow-Headers: Content-Type ← "그 헤더 가능"
3단계: 브라우저 판단

"오케이 받았네! 이제 진짜 요청 보낸다!"

4단계: 실제 요청 보냄
POST http://localhost:3000/api/users Content-Type: application/json { "name": "John" }

4. 흔한 에러와 해결 방법 🔧

❌ 에러: "doesn't pass access control check: It does not have HTTP ok status"

원인: 백엔드가 OPTIONS 요청에 200 OK를 보내지 않음

브라우저: "OPTIONS 요청 보냄" 백엔드: (아무 응답 없음) 또는 (404 Not Found) 브라우저: "200 OK를 못 받았네? 실패!"

✅ 해결: CORS 미들웨어 사용

// app.js const createCorsMiddleware = require('./middlewares/security/cors'); // 모든 OPTIONS 요청을 자동으로 처리! app.use(createCorsMiddleware({ allowedOrigins: ['http://localhost:8080'] })); // 이제 POST만 신경 쓰면 됨 app.post('/api/users', (req, res) => { res.json({ success: true }); });

🛠️ CORS 미들웨어 구현

// middlewares/security/cors.js const createCorsMiddleware = (options = {}) => { const allowedOrigins = options.allowedOrigins || ['http://localhost:8080']; return (req, res, next) => { const origin = req.headers.origin; // 1. Origin 체크 if (allowedOrigins.includes(origin)) { res.setHeader('Access-Control-Allow-Origin', origin); res.setHeader('Access-Control-Allow-Credentials', 'true'); } // 2. OPTIONS 요청 처리 (Preflight!) if (req.method === 'OPTIONS') { res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization'); return res.sendStatus(200); ← 여기서 200 보내서 Preflight 통과! } // 3. 일반 요청은 계속 진행 next(); }; };

5. 핵심 요약 🎯

CORS란?

"다른 집 주소(Origin)에서 오는 손님을 관리하는 것"

Preflight란?

"복잡한 요청 보내기 전에 브라우저가 먼저 물어보는 것"

왜 필요한가?

"보안상 위험한 요청을 사전에 차단하기 위해"

어떻게 해결하나?

"OPTIONS 요청에 200 OK를 반드시 보내기!"

✅ 완벽한 해결 체크리스트

  • ✓ CORS 미들웨어를 모든 라우트 전에 등록
  • ✓ OPTIONS 메서드 처리 구현
  • ✓ Access-Control-Allow-Origin 헤더 설정
  • ✓ Access-Control-Allow-Methods 헤더 설정
  • ✓ Access-Control-Allow-Headers 헤더 설정
  • ✓ 200 OK 상태 코드 반환

🚀 이제 CORS와 Preflight Request를 완전히 이해했습니다!

Backend 모듈 라이브러리 개발 프로젝트

728x90