CORS(Cross-Origin Resource Sharing) 은 무엇이며 왜 필요한가
교차출처공유 검증에 관련된 정책이다. 프론트엔드나 백엔드로 서로 연결을 시도했을때 가장 많이 보는 오류 중 하나일것이다.
출처가 같은지를 검사하는 대표적인 로직이라고 봐야 할 것 같은데. 프론트엔드에서 서버로 요청시에 서버와 출처가 같지 않다면 외부로부터의 공격일 가능성이 있기때문에 방어하는거라고 볼 수 있겠다.
우리가 흔히 사용하는 URL 은 http://localhost:3000/route 방식인데 여기에서 맨 앞의 http 는 프로토콜이고 localhost 는 origin 3000은 포트가 될 것이다. 이때 localhost:3000을 포함하여 출처로 보고. 해당 출처를 확인하는 방식이다.
cors 를 해결하기 위해서는 다양한 방법들이 있는데. 일단 프론트엔드에서는 사실상 근본적 해결이 불가능하고 서버에서 해당 출처에 대한 허용을 해주어야 한다.
또는 하나의 docker 네트워크 안에서 참조하거나, 프록시를 통한 동일 출처로 먼저 보낸 다음. 그곳에서 백엔드와 내부통신되게 하는 방법등이 있을 것이다.
CORS는 서로 다른 출처(origin) 에서 제공되는 리소스에 접근할 수 있도록 허용하는 정책이다.
기본적으로 브라우저에는 보안 상의 이유로 동일 출처 정책(Same-Origin Policy) 가 적용되어있다. 해당 리소스가 같은 출처에서 제공되는 것이 아니라면 브라우저가 이를 차단하도록 되어 있다. 다시 말해, 다른 출처의 서버에 요청을 보낼 경우, 해당 요청에 대한 응답에 접글할 수 없도록 막는다는 것이다. 이러한 정책은 보안을 강화하지만 이로 인해 합법적인 요청까지 차단될 수 있다. 그러한 상황을 해결하기 위해 CORS 가 개발되었다
CORS 를 적용하는 방법. 서버 측에서 Access-Control-Allow_origin 헤더를 설정하면 특정 출처에서의 접근을 허용할 수 있다. 예를들어 Access-Control-Allow-Origin: * 로 모든 출처에 대해 허용하거나 특정 출처만 선택적으로 허용할 수 있다. 추가로 Access-Control-Allow-Methods와 Access-Control-Allow-Headers 헤더를 통해 HTTP 메소드나 특정 헤더를 허용할 수도 있다.
이는 서버에서 수행되는 동작이므로, 프론트엔드 개발자는 일반적으로 서버 개발자에게 클라이언트의 도메인을 허용하도록 요청해야 한다.
동일 출처 정책은 어떤 공격을 막기 위해 존재하는건가
동일 출처 정책은 주로 크로스사이트 요청 위조(CSRF) 공격의 위력을 낮추기 위해 존재한다.
CSRF 공격은 악성 웹사이트가 사용자의 요청을 도용하여, 의도치 않은 요청을 서버에 보내게 만드는 공격이다. 예를 들어, 피해자가 공격자의 웹사이트에 들어왔을 때 해당 사용자의 요청인 것처럼 타 사이트에 GET 요청을 보내 사용자의 개인정보를 탈취할 수 있다. SOP는 악성 사이트에서 임의로 다른 출처의 서버로 요청을 보내거나, 응답에 접근하는 것을 막아 CSRF 공격의 효과를 줄여준다
답변에서는 “SOP는 주로 CSRF 공격을 낮추기 위해 존재한다” 라고 되어 있는데, 이는 엄밀히 말해 틀린 설명이에요.
SOP는 원래 CSRF 방어를 목적으로 한 정책이 아니고, XSS(크로스 사이트 스크립팅)나 임의 데이터 탈취 같은 보안 위험을 막기 위해 존재해요.
다만 SOP 때문에 브라우저 스크립트가 다른 origin의 응답을 읽을 수 없으니 CSRF의 위력도 제한되는 효과가 있을 뿐이에요.
👉 정리하면:
SOP 목적: 리소스 무단 읽기 차단 (주로 XSS 계열 방어)
부수 효과: CSRF 피해 범위를 줄여줌 (완전히 막는 건 아님, CSRF 토큰 같은 별도 방어 필요)
CORS 자체는 보안 기능이 아니라, 원래 막혀있던 걸 서버가 명시적으로 허용할 수 있게 해주는 규칙이다.
https://docs.tosspayments.com/resources/glossary/cors
추가적으로 참조한 자료이다.
출처 즉 Origin 이 어떤걸 뜻하는지를 명확히 알면 좋을 것 같다.
도메인(Hostname): myshop.com
출처(Origin) : https://www.myshop.com 이 될것 이다.
대표적인 이미지로

즉, 출처가 교차한다 -> 두 출차가 서로 다르다.
CORS 를 설정한다는 건 '출처가 다른 서버 간의 리소스 공유' 를 허용한다는 것이다.
SOP 가 서로 다른 출처일때 리소스 요청과 응답을 차단하는 정책이라면
CORS 는 반대로 서로 다른 출처라도 리소스 요청 응답을 허용할 수 있도록 하는 정책이다.
URL 접근이 가능한가? (SOP를 준수했는가?)
https://www.myshop.com/example/ ✅ 프로토콜, 도메인, 포트가 같음
https://myshop.com/example2/ ✅ 프로토콜, 도메인, 포트가 같음
http://myshop.com:8080/example/ ❌ 프로토콜과 포트가 다름
http://en.myshop.com/example/ ❌ 도메인이 다름
http://www.myshop.com/example/ ❌ 프로토콜이 다름
http://myshop.com:8080/example/ ❌ 포트가 다름
CORS 에러 대응하기
서버에서 Access-Control-Allow-Origin 응답 헤더 세팅하기
서버에서 Access-Control-Allow-Origin 헤더를 설정해서 요청을 수락할 출처를 명시적으로 지정할 수 있다. 이 헤더를 세팅하면 출처가 다르더라도 리소스 요청을 허용하게 된다.
프락시 서버 사용하기
웹 애플리케이션이 리소스를 직접적으로 요청하는 대신, 프록시 서버를 사용하여 웹 애플리케이션에서 리소스로의 요청을 전달하는 방법이 있다.
예를들어 http://example.com에서 동작하는 웹 애플리케이션이 http://api.example.com에 데이터를 요청하는 상황을 가정해보자 . 두 도메인의 출처는 다르기 때문에 cross-origin 요청으로 판단 후 실패할 것이다.
이 문제를 해결하려면, 직접 http://api.example.com에 API 요청하는 대신, 같은 출처(http://example.com)에 위치한 프락시 서버를 통해 API 요청을 중계하도록 구성하면 된다.
요즘 많이 사용하는 Nextjs 를 기준으로 할때 예시를 들어보면
// URL 리라이트 설정 (API 경로 매핑)
async rewrites() {
// MSW가 활성화된 경우 또는 CI 환경에서는 rewrite를 비활성화
if (
process.env.NEXT_PUBLIC_ENABLE_MSW === 'true' ||
process.env.CI === 'true'
) {
return [];
}
const backendUrl = process.env.BACKEND_URL || 'http://backend:8000';
return [
{
source: '/api/v0/:path*',
destination: `${backendUrl}/api/v0/:path*`,
},
];
},
해당 방식을 통해 내가 원하는 backend url 으로 프록시를 돌리는 방법을 사용할 수 있을 것 같다.