프론트엔드와 API 서버를 다른 포트에서 실행 후 API 요청을 했는데 오류가 발생했어요. 뭐가 문제일까요?
해당 API 서버에서 요청에 대한 응답 헤더에 CORS 규칙을 포함하지 않았기 때문입니다.
CORS는 무엇인가요?
CORS는 Cross-Origin Resource Sharing의 약자로 교차 출처 자원 공유 정책을 의미합니다. 브라우저가 요청을 보내는 출처와 다른 출처의 자원에 대한 접근 권한을 허용하기 위해 따르는 규칙이라고 이해하시면 됩니다.
출처가 뭐죠?
출처는 Origin을 번역한 단어로 프로토콜, 도메인, 포트가 결합된 개념입니다. 브라우저에 로드된 자원의 근원을 식별하기 위해 사용됩니다. 예를 들어,
http://127.0.0.1:8000
가 하나의 출처입니다.https
를 사용하거나5000
번 포트를 사용한다면 브라우저는 다른 출처로 간주합니다.
그럼 CORS가 왜 필요한가요?
브라우저는 기본적으로 SOP(Same-Origin Policy)를 적용하기 때문입니다. SOP는 동일 출처 정책의 약자로 같은 출처의 리소스만 접근을 허용합니다. 이에 따라 다른 출처의 서버에 API를 요청할 경우 브라우저가 응답을 거부하게 됩니다.
Postman에서 요청했을 때는 문제가 없었는데요?
CORS와 SOP는 웹 브라우저의 정책입니다. 따라서 브라우저가 아닌 환경에서 다른 출처로의 요청이 CORS 정책을 위반하더라도 응답이 거부되지 않습니다.
브라우저는 왜 SOP를 준수하죠?
클라이언트를 공격으로부터 보호하기 위해서입니다. CSRF 나 XSS 공격을 사전에 차단하고 보안 취약점을 차단합니다.
그럼 다른 출처의 서버에 요청을 보내고 싶으면요?
그걸 위해서 CORS 정책을 서버에서 제공합니다. 서버는 요청에 대한 응답으로 CORS 규칙을 헤더에 추가합니다. 브라우저가 이 CORS 규칙을 해석하여 응답을 거부할지 허용할지 결정하게 됩니다.
더 자세하게 알려주세요.
- 브라우저가 다른 출처의 서버로 요청할 경우 헤더에 현재 출처인 Origin의 정보를 추가합니다.
- 서버는 응답 헤더에 Access-Control-Allow-Origin 필드를 추가해 허용된 출처, 즉 CORS 정책을 추가합니다.
- 브라우저가 응답 헤더를 분석해 두 필드가 동일하다면 허용된 요청임을 인식하고 응답을 처리합니다. 하지만 동일하지 않다면 거부하게 됩니다.
모든 요청에 대해 위 답변처럼 동작하나요?
아닙니다. 위 답변은 간단한 요청의 경우 작동하는 방식입니다. 간단한 요청은 특정 HTTP 메서드(GET, HEAD, POST)와 일부 헤더만 사용하는 요청을 의미합니다. 복잡한 요청의 경우에는 다른 방식을 사용합니다.
복잡한 요청은 뭐죠?
복잡한 요청은 간단한 요청을 제외한 요청을 의미합니다. 이 경우에는 preflight 요청을 보내서 CORS 정책을 확인 후 허용된 출처일 경우에만 실제 요청을 보냅니다.
preflight 요청?
브라우저가 서버에 실제 요청을 보내기 전 사전 협상을 위해 보내는 요청입니다. OPTIONS 메서드를 사용해 서버가 지원하는 메서드, 헤더, CORS 등 서버의 메타데이터를 요청하게 됩니다.