CORS 오류가 발생하는 이유와 해결 방법
프론트엔드와 백엔드를 분리해 개발하다 보면 “CORS 오류”라는 메시지를 자주 마주하게 됩니다. 브라우저 콘솔에는 “Access to fetch at … from origin … has been blocked by CORS policy” 같은 에러가 표시됩니다. 서버는 정상적으로 동작하는 것 같은데, 브라우저에서만 요청이 막히는 상황입니다. 그렇다면 CORS란 무엇이며, 왜 이런 오류가 발생할까요?
먼저 기본 개념부터 이해해야 합니다. CORS는 Cross-Origin Resource Sharing의 약자입니다. 직역하면 “교차 출처 리소스 공유”입니다. 여기서 출처(Origin)는 프로토콜, 도메인, 포트의 조합을 의미합니다. 예를 들어 다음 세 가지는 모두 서로 다른 출처입니다.
프로토콜이 다르거나, 포트가 다르거나, 도메인이 다르면 다른 출처로 간주됩니다.
웹 브라우저는 기본적으로 동일 출처 정책(Same-Origin Policy)을 따릅니다. 이는 보안을 위해 도입된 정책으로, 한 출처에서 로드된 웹페이지는 다른 출처의 리소스에 자유롭게 접근할 수 없도록 제한합니다. 만약 이 정책이 없다면 악성 사이트가 사용자의 인증 정보를 이용해 다른 사이트에 요청을 보내는 보안 문제가 발생할 수 있습니다.
CORS는 이러한 제한을 완화하기 위한 메커니즘입니다. 서버가 특정 출처의 요청을 허용하겠다고 명시하면, 브라우저는 그 요청을 허용합니다. 즉, CORS는 서버가 브라우저에게 “이 출처에서 오는 요청은 허용해도 된다”라고 알려주는 방식입니다.
CORS 오류는 대부분 서버가 적절한 허용 헤더를 설정하지 않았을 때 발생합니다. 예를 들어 프론트엔드가 http://localhost:3000에서 실행되고 있고, API 서버가 http://localhost:8080에 있다면 두 출처는 다릅니다. 이 상태에서 프론트엔드가 API 요청을 보내면 브라우저는 교차 출처 요청으로 인식합니다. 서버 응답에 CORS 허용 헤더가 없다면 브라우저는 요청을 차단합니다.
CORS 동작 방식에는 두 가지가 있습니다. 단순 요청(Simple Request)과 사전 요청(Preflight Request)입니다.
단순 요청은 GET, POST(특정 조건 충족), HEAD 요청처럼 비교적 단순한 요청입니다. 이 경우 서버는 응답 헤더에 Access-Control-Allow-Origin을 포함하면 됩니다.
예를 들어 다음과 같은 헤더를 추가하면 됩니다.
Access-Control-Allow-Origin: http://localhost:3000
이 헤더는 해당 출처의 요청을 허용한다는 의미입니다.
사전 요청은 PUT, DELETE 같은 메서드나, 커스텀 헤더를 사용하는 경우 발생합니다. 이때 브라우저는 실제 요청을 보내기 전에 OPTIONS 요청을 먼저 보냅니다. 이를 Preflight 요청이라고 합니다. 서버는 이 요청에 대해 허용 메서드와 허용 헤더 정보를 응답해야 합니다.
예를 들어 다음과 같은 헤더가 필요합니다.
Access-Control-Allow-Origin
Access-Control-Allow-Methods
Access-Control-Allow-Headers
서버가 이를 적절히 응답하지 않으면 브라우저는 실제 요청을 보내지 않고 차단합니다.
CORS 오류 해결 방법은 다음과 같습니다.
첫째, 서버에서 CORS 허용 설정을 추가합니다. Node.js(Express) 환경에서는 cors 미들웨어를 사용하면 간단하게 해결할 수 있습니다. Spring Boot에서는 @CrossOrigin 어노테이션이나 전역 설정을 통해 해결할 수 있습니다.
둘째, 개발 환경에서 프록시 설정을 활용할 수 있습니다. 예를 들어 React 개발 서버에서 proxy 설정을 하면, 브라우저 입장에서는 같은 출처로 인식하여 CORS 문제를 우회할 수 있습니다.
셋째, 모든 출처를 허용하는 설정도 가능합니다.
Access-Control-Allow-Origin: *
하지만 이는 보안상 위험할 수 있습니다. 인증이 필요한 API에서는 특정 도메인만 허용하는 것이 안전합니다.
중요한 점은 CORS 오류는 서버 문제가 아니라 “브라우저 보안 정책”이라는 것입니다. Postman이나 curl로는 요청이 정상 동작하지만, 브라우저에서만 차단되는 이유가 바로 이것입니다. 브라우저는 사용자 보안을 위해 동일 출처 정책을 강제합니다.
정리하자면 CORS는 서로 다른 출처 간 리소스 공유를 허용하기 위한 보안 메커니즘입니다. 출처는 프로토콜, 도메인, 포트의 조합이며, 서버가 적절한 CORS 헤더를 설정하지 않으면 브라우저가 요청을 차단합니다. CORS 오류를 해결하려면 서버에 Access-Control-Allow-Origin 등의 헤더를 올바르게 설정해야 합니다.
프론트엔드와 백엔드를 분리하는 현대 웹 개발 환경에서는 CORS를 이해하는 것이 필수입니다. CORS는 단순한 에러 메시지가 아니라, 웹 보안 구조의 핵심 개념입니다.
Leave a Reply