CORS 쉽게 이해하기: 웹 세계의 국경 검문소 🛂
안녕하세요! 오늘은 웹 개발에서 자주 마주치게 되는 CORS에 대해 알아보겠습니다. 백엔드 개발자라면 반드시 알아야 할 개념이니 쉽게 설명해 드릴게요! 😊
CORS란 무엇인가요? 🤔
CORS(Cross-Origin Resource Sharing)는 다른 출처(Origin)의 리소스를 공유할 수 있게 해주는 보안 메커니즘입니다.
여기서 출처(Origin)란 프로토콜 + 도메인 + 포트의 조합을 말합니다.
🌍 현실 세계의 비유: CORS는 마치 국가 간 국경 검문소와 같습니다. 다른 나라(출처)에서 온 사람(요청)이 입국(리소스 접근)하려면 비자(허가)가 필요한 것처럼, 다른 출처에서의 요청도 특별한 허가가 필요합니다!
CORS는 왜 필요한가요? 🛡️
과거에 CSRF(Cross-Site Request Forgery) 라는 공격이 있었습니다. 이는 사용자가 로그인한 상태에서 악의적인 사이트가 사용자 모르게 요청을 보내는 공격이었죠.
이를 방지하기 위해 브라우저는 동일 출처 정책(Same-Origin Policy) 을 도입했습니다. 하지만 현대 웹에서는 여러 도메인의 리소스를 사용하는 것이 일반적이 되었고, 이 제한을 안전하게 완화하기 위해 CORS가 탄생했습니다!
CORS는 어떻게 작동할까요? 🔄
1. 단순 요청 (Simple Request) 🚶
가장 기본적인 CORS 처리 방식입니다.
클라이언트 → 서버: "안녕! 나는 https://client.com 출신이야. 데이터 좀 줄래?"
서버 → 클라이언트: "https://client.com은 허용 목록에 있네. 여기 데이터 있어!"
브라우저는 자동으로 Origin 헤더를 요청에 추가하고, 서버의 Access-Control-Allow-Origin 헤더와 비교합니다.
2. 사전 요청 (Preflight Request) 🚁
조금 더 복잡한 요청은 본 요청 전에 "사전 확인"을 합니다.
클라이언트 → 서버: "안녕! OPTIONS 요청이야. 내가 DELETE 메소드로 요청해도 될까?"
서버 → 클라이언트: "응, DELETE 메소드 허용할게. 3600초 동안 다시 물어보지 않아도 돼!"
클라이언트 → 서버: "고마워! 이제 진짜 DELETE 요청을 보낼게."
이 과정은 OPTIONS HTTP 메소드를 사용합니다.
3. 인증 포함 요청 (Credential Request) 🔐
쿠키나 인증 정보를 포함한 요청은 더 엄격한 규칙이 적용됩니다.
클라이언트 → 서버: "안녕! 내 쿠키도 같이 보낼게."
서버 → 클라이언트: "확인했어. 특정 출처만 허용하고, 와일드카드(*)는 사용 안 해!"
코드로 보는 CORS 예제 👨💻
프론트엔드 (React)
// API 요청 예시
fetch('https://api.example.com/data', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ key: 'value' }),
credentials: 'include' // 쿠키 포함 요청
})
백엔드 (Node.js/Express)
// CORS 설정 예시
const express = require('express');
const app = express();
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'https://myapp.com');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.header('Access-Control-Allow-Credentials', 'true');
next();
});
Next.js API 라우트
자주 발생하는 CORS 오류와 해결법 🚫➡️✅
1. "Access to fetch at 'X' from origin 'Y' has been blocked by CORS policy"
이 오류는 서버에서 클라이언트의 출처를 허용하지 않았을 때 발생합니다.
해결법
- 서버에서 올바른 Access-Control-Allow-Origin 헤더 설정
- 개발 환경에서는 프록시 서버 사용하기
2. "Method X is not allowed by Access-Control-Allow-Methods"
해결법
- 서버에서 Access-Control-Allow-Methods에 해당 메소드 추가
3. 인증 관련 CORS 오류
해결법
- Access-Control-Allow-Credentials: true 설정
- 와일드카드(*) 대신 명시적 출처 지정
요약 📝
CORS는
- 다른 출처 간의 리소스 공유를 안전하게 해주는 메커니즘 🔄
- 웹 보안의 중요한 부분으로, CSRF 공격을 방지 🛡️
- 단순 요청, 사전 요청, 인증 요청 등 다양한 시나리오 지원 🌐
- 적절한 HTTP 헤더를 통해 구현 📝
CORS란 무엇인가요?
CORS(Cross Origin Resource Sharing)는 출처가 다른 곳의 리소스를 요청할 때 접근 권한을 부여하는 메커니즘입니다. 리소스를 주고받는 두 곳의 출처가 다르면 출처가 교차한다고 합니다. 이때 출처는 URL뿐만 아니라 프로토콜과 포트까지 포함됩니다. 만약 클라이언트의 출처가 허용되지 않았다면 CORS 에러가 발생할 수 있습니다.
CORS는 왜 필요한가요?
과거에는 크로스 사이트 요청 위조(CSRF, Cross-Site Request Forgery) 문제가 있었습니다. 피해자의 브라우저에서 다른 애플리케이션으로 가짜 클라이언트 요청을 전송하는 공격입니다.
CSRF를 예방하기 위해 브라우저는 동일 출처 정책(SOP, same-origin policy)을 구현했습니다. SOP가 구현된 브라우저는 클라이언트와 동일한 출처의 리소스로만 요청을 보낼 수 있습니다.
하지만, SOP는 한계가 있습니다. 현대의 웹 애플리케이션은 다른 출처의 리소스를 사용하는 경우가 많기 때문입니다. 따라서, SOP를 확장한 CORS가 필요합니다.
CORS는 어떻게 작동할까요? 🤔
브라우저가 요청 메시지에 Origin 헤더와 응답 메시지의 Access-Control-Allow-Origin 헤더를 비교해서 CORS를 위반하는지 확인합니다. 이때, Origin에는 현재 요청하는 클라이언트의 출처(프로토콜, 도메인, 포트)가, Access-Control-Allow-Origin은 리소스 요청을 허용하는 출처가 작성됩니다.
이렇게 단순하게 요청하는 것을 Simple Request라고 합니다. Simple Request은 요청 메서드(GET, POST, HEAD), 수동으로 설정한 요청 헤더(Accept, Accept-Language, Content-Language, Content-Type, Range), Content-Type 헤더(application/x-www-form-urlencoded, multipart/form-data, text/plain)인 경우에만 해당합니다.
브라우저가 사전 요청을 보내는 경우도 있습니다. 이때 사전 요청을 Preflight Request라고 합니다. 브라우저가 본 요청을 보내기 이전, Preflight Request를 OPTIONS 메서드로 요청을 보내어 실제 요청이 안전한지 확인합니다.
Preflight Request는 추가로 Access-Control-Request-Method로 실 요청 메서드와, Access-Control-Request-Headers 헤더에 실 요청의 추가 헤더 목록을 담아서 보내야 합니다.
이에 대한 응답은 대응되는 Access-Control-Allow-Methods와 Access-Control-Headers를 보내야 하고, Preflight Request로 인한 추가 요청을 줄이기 위해 캐시 기간을 Access-Control-Max-Age에 담아서 보내야 합니다.
또한 인증된 요청을 사용하는 방식도 있는데요. 이를 Credential Request라고 합니다. 쿠키나 토큰과 같은 인증 정보를 포함한 요청은 더욱 안전하게 처리되어야 합니다. 이때 Credential Request를 수행합니다.
Credential Request를 요청하는 경우에는 서버에서는 Access-Control-Allow-Credentials를 true로 설정해야 하며 Access-Control-Allow-Origin에 와일드카드를 사용하지 못합니다.
'1일 1CS(Computer Science)' 카테고리의 다른 글
낙관적 업데이트에 관하여 설명해주세요. (0) | 2025.05.07 |
---|---|
리버스 프록시와 포워드 프록시의 차이점에 대해 설명해주세요. (0) | 2025.04.29 |
SSR(Server Side Rendering)에 대해 설명해주세요. (0) | 2025.04.28 |
데이터베이스 시스템에서 동시성을 제어하는 방법에 대해 설명해주세요. (0) | 2025.04.24 |
웹 접근성의 개념과 개선 방법에 대해 설명해주세요. (0) | 2025.04.24 |