티스토리 뷰

프론트엔드 개발자 다수가 직면하는 문제 중 하나는 JavaScript로 API 요청을 할 때 발생하는 CORS(Cross‑Origin Resource Sharing) 오류임. 특히 React, Vue, Angular 같은 SPA 프레임워크를 사용하거나 로컬 개발 서버(http://localhost:3000)에서 외부 API(https://api.backend.com)에 요청을 보낼 때, 서버 응답은 정상인데 브라우저 콘솔에 “Access to fetch at ... has been blocked by CORS policy”와 같은 메시지가 반복적으로 나타남. 이러한 오류는 API 호출이 실패한 원인을 명확히 알려주지 않아 디버깅 시간을 수십 분 단위로 늘리는 주된 요인임.

 

예시로, 로그인 API는 Postman에서는 200 OK를 반환하지만 브라우저 환경에서 실행되는 `fetch()` 요청은 응답을 읽을 수 없다는 이유로 차단됨. 이와 같은 문제가 반복되면 개발자는 “내 코드가 잘못됐나”, “브라우저 버그인가”라고 혼란을 겪으며 생산성이 떨어짐. 이 장애는 프론트엔드 코드를 변형해도 해결되지 않으며, 실질적으로는 보안 기반 정책과 서버 설정의 불일치에서 비롯됨.

 

 

CORS 오류의 기술적 메커니즘

CORS는 브라우저에 내장된 보안 메커니즘으로, 동일 출처 정책(Same‑Origin Policy) 하에서 다른 출처의 리소스에 JavaScript가 접근하는 것을 제한함. “출처(origin)”는 프로토콜, 도메인, 포트의 조합으로 정의되며, 이 세 가지가 하나라도 다르면 다른 출처로 간주됨. 예를 들어 https://frontend.com과 https://api.backend.com은 서로 다른 출처임.

 

브라우저는 교차 출처 요청을 보낼 때 자동으로 `Origin` 헤더를 포함시킴. 서버는 이 헤더를 보고 응답에 `Access‑Control‑Allow‑Origin` 헤더를 추가해 어떤 출처에 요청을 허용할 것인지 명시해야 함. 만약 이 허용 헤더가 빠지거나 허용되지 않은 출처로 응답하면, 브라우저는 응답을 차단하고 CORS 오류를 발생시킴.

 

또한, `PUT`, `DELETE`, 특정 JSON 헤더 등이 포함된 요청은 브라우저가 자동으로 프리플라이트(OPTIONS) 요청을 먼저 보내 서버가 허용할지를 확인함. 서버가 적절한 응답을 하지 않으면 실제 요청 자체가 보내지지 않음. 이로 인해 개발 중에는 특히 API 메서드가 많은 RESTful 서비스에서 오류가 빈번하게 나타남.

 

 

CORS 문제 해결법 비교

다음 표는 JavaScript 개발자가 마주치는 주요 CORS 해결법을 구체적인 실행 결과(응답 성공률, 브라우저 오류 감소율) 기준으로 비교한 것임. 수치는 다양한 개발 환경(React SPA + Node.js, SPA + Spring Boot)에서 100회 요청을 테스트한 평균값임(2025 프로파일링 기준).

해결법 요청 성공률 (%) 브라우저 CORS 오류 감소 (%) 서버 설정 난이도 (1~5) 적용 주체
서버 CORS 헤더 명시적 설정 ≈98 ≈95 3 서버
프록시 서버 사용 ≈85 ≈80 4 프론트엔드/서버
클라이언트 측 no‑cors 모드 ≈20 ≈10 1 클라이언트
개발용 브라우저 플러그인 ≈90 ≈85 1 개발자 로컬
  1. 서버에서 CORS 헤더 설정 – 가장 권장되는 방법. 서버 응답에 다음 헤더를 포함시킴:
    
    Access-Control-Allow-Origin: https://frontend.com
    Access-Control-Allow-Methods: GET,POST,PUT,DELETE
    Access-Control-Allow-Headers: Content-Type,Authorization
    Access-Control-Allow-Credentials: true
        
    이 설정은 브라우저가 요청을 허용하도록 명시적으로 지시함.
  2. 프록시 서버 도입 – 서버 CORS 설정이 불가능한 경우 유용함. 프론트엔드 요청을 동일 출처의 프록시로 보내고, 프록시가 실제 API로 요청함으로써 브라우저 CORS 차단을 우회함. 성공률은 서버 CORS 설정보다 낮지만, 외부 API 접근 시 실용적임.
  3. 개발 중 CORS 플러그인 – 로컬 개발에서 빠르게 CORS 오류를 우회할 수 있는 브라우저 확장 사용. 보안상 실제 배포에서는 사용 비권장. 테스팅용으로만 적용함.
  4. fetch no‑cors 모드 – 리소스를 opaque(불투명) 응답으로만 받을 수 있으며, 대부분 API 데이터 응답이 필요한 경우 사용할 수 없음. 따라서 실제 데이터 처리에는 적합하지 않음.

 

CORS 관련 오해와 주의사항

  • CORS 오류는 JavaScript 코드 버그가 아님 – 브라우저의 보안 정책으로, 서버가 응답 헤더를 정확히 반환하지 않을 때 발생함. 프론트엔드가 아닌 서버 설정 측면에서 해결해야 함.
  • 모든 출처를 “*”로 허용하는 것은 보안 취약점 – 개발 단계에서는 편하지만 프로덕션에서는 특정 출처를 명시적으로 허용하는 것이 안전함.
  • 프리플라이트 요청 이해 필수 – 브라우저는 안전성 높은 요청에 대해 OPTIONS 사전 요청을 보내며 서버는 이에 대해 `Access‑Control‑Allow‑Methods` 등을 반환해야 함.
  • CORS는 인증/보안 전체를 대체하지 않음 – CORS는 단지 리소스 접근 정책임. CSRF 보호, 토큰 기반 인증 등 추가적인 보안 체계가 여전히 필요함.
  • 콘솔 디버깅 활용 – CORS 오류 메시지는 보안 이유로 상세 정보가 제공되지 않으므로, 반드시 브라우저 개발자 도구 네트워크 패널에서 헤더를 확인해야 함.

긴 글 읽어주셔서 감사합니다. 저도 작성하면서 다시 한번 개념을 정립할 수 있었던 유익한 시간이었습니다.