프로젝트를 진행하면서 발생한 CORS 에러 때문에 많은 시간을 보냈습니다. 문제를 해결하기 위해 여러 가지 시도를 했던 기록을 남겨야 겠다는 생각이 들었습니다. 따라서 이번에는 그동안 시도했던 해결 방법과 현재 겪고 있는 문제에 대해 공유하고자 합니다.
CORS(Cross-Origin Resource Sharing) 에러는 웹 애플리케이션이 현재 페이지와 다른 출처(origin)에 있는 리소스를 요청할 때 발생할 수 있는 보안상의 문제입니다. 예를 들어, 브라우저에서 A 서버의 웹 애플리케이션이 B 서버의 API에 데이터를 요청하려고 할 때 CORS가 작동합니다.
기본적으로 웹 브라우저는 보안상의 이유로 동일 출처 정책(Same-Origin Policy) 을 따릅니다. 이 정책에 따르면, 한 출처에서 로드된 웹 페이지가 다른 출처의 리소스에 접근하려고 할 때 제한을 받습니다. 출처는 프로토콜(HTTP/HTTPS), 호스트(도메인), 포트가 동일할 때 동일 출처로 간주됩니다.
즉, 다음과 같은 상황에서 CORS 에러가 발생할 수 있습니다:
http://example.com
에서 https://another-example.com
으로 요청을 보낼 때http://example.com
에서 http://api.example.com:8080
으로 요청을 보낼 때서버에서 명시적으로 허용하지 않는 한, 브라우저는 다른 출처의 요청을 차단합니다. 이를 해결하려면 서버에서 CORS 헤더를 설정하여 요청을 허용해야 합니다.
CORS 에러는 클라이언트 측에서는 직접적으로 해결할 수 없으며, 서버에서 해당 출처를 허용하도록 CORS 설정을 변경해야만 근본적인 해결이 가능합니다. CORS는 클라이언트가 할 수 없는 설정이라는 점에서 초반에 다소 복잡하게 느껴질 수 있지만, 서버 측에서 이를 해결하면 문제없이 원격 리소스에 접근할 수 있게 됩니다.
처음에는 프론트엔드와 백엔드 모두 HTTP를 사용하고 있었기 때문에, CORS 설정이 제대로 되어 있어도 간헐적으로 CORS 에러가 발생했습니다. 로컬에서만 문제를 해결하기 위해, 다음과 같이 Vite 설정 파일에서 프록시와 CORS 옵션을 추가했습니다.
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import svgr from 'vite-plugin-svgr';
export default defineConfig({
plugins: [
react(),
svgr({
exportAsDefault: true,
}),
],
server: {
port: 5173,
proxy: {
'/proxy': {
target: 'http://example.com:8080',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/proxy/, ''),
secure: false,
ws: true,
},
},
cors: {
origin: '*',
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'PATCH'],
allowedHeaders: ['Authorization', 'Content-Type'],
credentials: true,
maxAge: 3600,
},
},
});
로컬에서는 이 설정으로 문제없이 작동했지만, Amplify로 배포 후 프론트엔드가 HTTPS로 전환되면서 CORS 에러가 다시 발생했습니다. 🤯
이 문제를 해결하기 위해 백엔드 서버를 HTTPS로 전환했습니다. 그 결과 GET, POST 등의 요청에서는 더 이상 CORS 문제가 발생하지 않았지만, PATCH 요청에서 다시 문제가 발생했습니다. 모든 요청을 해결한 줄 알았으나 PATCH에서 다시 발목을 잡혔습니다.
PATCH 요청의 문제를 해결하기 위해, Thingproxy를 사용하여 API 요청 URL 앞에 https://thingproxy.freeboard.io/fetch/
를 추가했습니다. 이 방법은 로컬 환경에서는 잘 작동했지만, 배포된 환경에서는 또다시 CORS 에러가 발생했습니다. 이 방법이 완벽한 해결책이 아님을 깨달았습니다.
const apiUrl = 'https://thingproxy.freeboard.io/fetch/https://yourapi.com';
여기서 깨달았습니다. 프론트엔드에서 해결하려고 프록시까지 붙이며 온갖 고생을 했지만, 결국 백엔드의 CORS 설정으로 해결할 수 있었습니다. 서버팀에서 설정을 변경한 뒤, thingproxy도 제거했더니...
✨ 해결! 🎉
이 에러를 통해 서버와의 소통이 얼마나 중요한지 절실히 깨달았습니다. 프론트엔드에서 해결책을 찾으려는 시도도 좋지만, CORS는 서버 측 이슈일 가능성이 큽니다. 다음부터는 서버 담당자에게 먼저 요청하고 협력하는 게 시간을 아끼는 길입니다!
여러분도 CORS에 발목 잡혔다면 제 경험을 참고하시길.. 해결이 안 되면 프론트엔드만 탓하지 말고 서버에 도움을 요청하세요. 😄🚀