저는 Myfit이라는 네이버 클라우드 해커톤 프로젝트를 진행하면서, 서버 없이 프론트엔드만 개발하는 환경이였습니다.
이 과정에서 네이버 클라우드의 클로바 AI API를 호출해야 했는데, CORS 에러가 발생했습니다.
CORS 는 다른 출처에서 리소스를 공유할 때 발생하는 브라우저의 보안 메커니즘입니다.
여기서 출처는 아래의 세 가지 요소를 기준으로 정의됩니다.
동일 출처 정책(Same-Origin0Policy) 에 따라, 브라우저는 기본적으로 동일한 출처에서만 데이터를 요청할 수 있도록 제한합니다. 예를들어,
http://localhost:3000
에서 실행 중인데, API 요청을 https://api.example.com
으로 보낸다면, 이 요청은 다를 출처(Cross-Origin) 에 해당하므로 브라우저가 차단합니다.
CORS는 서버가 클라이언트 요청을 허용하도록 명시적으로 승인하는 방식으로 이 제한을 완화할 수 있도록 설계되었습니다. 이를 위해서 서버는 CORS 헤더를 추가하여 요청을 허용할 출처를 명시해야 합니다.
CORS는 다음과 같은 방식으로 동작합니다.
1. 간단 요청: 요청 헤더가 단순한 경우, 서버는 Access-Control-Allow-Origin헤더를 통해 요청 출처를 허용할지 여부를 결정합니다.
2. Preflight 요청 : 특정 조건을 마족하는 요청은 서버와 미리 협상(Preflight) 과정을 거칩니다.
웹 브라우저는 사용자의 데이터를 보호하기 위해 동일 출처 정책을 적용합니다. 이 정책이 없다면 악의적인 사이트가 사용자의 세션 쿠키를 이용해 민감한 데이터를 탈취하거나, 권한이 없는 요청을 보낼 수 있습니다.
예를들어 현재 내가 실행하고 있는 React앱은 http://localhost:3000
에서 실행중이지만
API는 https://api.example.com
에서 호스팅되기 때문에 브라우저는 React 앱의 요청을 다른 출처로 간주하여 차단합니다.
Vercel Serverless Functions는 클라이언트(React 앱)와 외부 API 서버 사이에서 프록시(proxy) 역할을 수행합니다.
• 브라우저의 동일 출처 정책은 브라우저와 서버 간의 통신에만 적용됩니다.
• 브라우저가 동일한 출처라고 판단하는 Vercel Serverless Functions에 요청을 보내면, 브라우저는 이를 차단하지 않습니다.
• Serverless Function이 외부 API와 통신하고 결과를 React 앱으로 전달하는 방식으로 CORS 문제를 해결합니다.
프록시 서버의 흐름 예시
1. React 앱은 https://my-app.vercel.app/api/data로 요청을 보냅니다. 2. Vercel Serverless Function(/api/data)는 외부 API(https://api.example.com/data)로 요청을 보냅니다. 3. 외부 API에서 데이터를 받아온 후 Vercel Serverless Function이 이를 React 앱에 응답으로 전달합니다.
React 앱은 Vercel Serverless Functions를 동일 출처로 간주하므로, 브라우저는 CORS 문제 없이 요청과 응답을 처리할 수 있습니다.
추가로 Vercel Serverless Functions을 사용하면 같은 출처일텐데, 왜 Access-Control-Allow-Origin
설정을 하는지 gpt에게 물어봤는데
Vercel에 배포된 상태에서 같은 도메인에서 Serverless Function을 호출하면 CORS 설정이 필요 없지만
개발 서버에서 호출하는 경우 localhost:3000 에서 실행돼서 CORS 정책이 적용되기 때문이라고 한다.