CORS(Cross-Origin Resource Sharing)

GyungHo Go·2022년 12월 22일
0

웹개발을 하다보면 마주치는 수많은 에러들이 많다. 오늘은 CORS에러에 대한 이야기를 해보고자 한다. 클라이언트에서도 서버에서도 제대로 세팅해놓고, 클라이언트에서 API요청을 하고자 할때 브라우저에서 다음과 같은 시뻘건 에러줄이 나올 때가 있다.

이때 CORS가 무엇이고, 이게 왜 나오는지 어떻게 동작하는지, 그리고 CORS에러가 무엇이고, 어떻게 해결해야 하는지 정리해 보려고 한다.

면접에서도 단골 질문이기도 하다.

CORS 너 누구냐

교차 출처 리소스 공유(Cross-Origin Resource Sharing)는 추가 HTTP 헤더를 사용해서 한 출처에서 실행중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제이다.
웹 애플리케이션은 리소스가 자신의 출처(도메인, 프로토콜, 포트)와 다를 때 교차 출처 HTTP 요청을 실행한다.

  • 교차 출처요청의 예시 https://myhomepage.com 의 프론트 엔드 javascript 코드가 XMLHttpRequest를 사용해서 https://localhost:3000 을 요청하는 경우 보안상의 이유로, 브라우저는 교차출처 HTTP 요청을 제한한다.

Cross-Origin이니까 Same-Origin 동일 출처의 반대 개념이다. 말그대로 다른 출처간에 리소스를 공유할 수 있도록 하는걸 말한다.

여기서 출처는 사용하고자 하는 URL 주소(프로토콜, 도메인, 포트 등), 리소스는 주고받아지는 데이터 라고 생각하면 된다.

내가 로컬에서 개발하고있는 URL과 네이버 맵 API, 이 서로 다른 출처끼리 정보요청과 반환이 가능하게 하는게 CORS이다.

즉, 원래 서로 다른 출처끼리 요청을 주고받는게 안되는게 기본값인데, 이걸 되게 하는게 CORS이고, 서버와 클라이언트가 정해진 헤더를 통해 서로 요청이나 응답에 반응할지 결정하는 방식으로 CORS라는 이름으로 표준화 되었다. CORS는 최신 브라우저에서 구현된 동일 출처 정책 SOP(Same-Origin Policy) 때문에 등장 했다.


동일 출처 정책(Same-Origin Policy)는 무엇이고, CORS 에러는 왜 발생하는가?

동일 출처 정책(SOP)은 가장 일반적인 사이버 공격 중 하나인 사이트간 요청 위조에 대응하게 된다. 악의적인 웹사이트는 브라우저의 쿠키 저장 시스템을 이용하려고 시도할 것이다.

도메인에 대한 모든 HTTP 요청에 대해 브라우저는 해당 도메인과 연결된 모든 HTTP 쿠키를 첨부 한다. 이는 인증및 세션 설정에 특히 유용하다.

예를 들어 facebook.com이라는 사이트가 있고, 이 사이트의 api 주소는 facebook.com/api이다. 사용자가 이 사이트에 로그인 한다고 하면 브라우저는 facebook.com 도메인에 대한 관련 세션 쿠키를 저장한다. 그리고 facebook.com에 다시 방문할 때마다 로그인할 필요 없게 된다.

즉, facebook.com 도메인에 대한 요청이 있을 때 브라우저가 해당 도메인에 대한 저장된 쿠키를 자동으로 포함한다는 것이다.

이는 다음과 같은 시나리오가 발생할 수 있다.
누군가 잘못된 링크를 전달하여 내가 클릭한다고 했을때, 악의적인 웹사이트 bad-site.com 또한 facebook.com/api에 요청을 보낼 수 있다. 이때 유저가 획득한 인증 토큰이 자동으로 첨부되어 사용자 인척 요청을 보낼 수 있게 된다.

이렇게 자동으로 쿠키가 첨부되기 때문에 보안상의 이유로 브라우저는 HTTP 호출을 동일한 출처로 제한했다.

이 상황에서 브라우저가 개입해서 악성 코드가 이와같은 API 요청을 하지 못하도록 방지 합니다. bad-site를 중지하고 동일 출처 정책에 의해 차단된다.

쉽게 정리해 보자면

CORS 에러는 웹사이트를 여는 곳 크롬이나 사파리 같은 브라우저에서 내가 방문한 사이트를 못믿어서 띄우는 것이다.

내 의지와 상관없이 브라우저에 저장된 정보를 가지고 악의적인 짓을 하거나 다른 API를 통해 안좋은 짓을 할 수 있기 때문에 CORS라는 것을 통해 방지해준다.

정확히 말하면 CORS는 그것을 풀어주는것이고, 그걸 막는것은 SOP이다.

CORS? SOP!

사실 그동안 웹개발자를 괴롭히던 시뻘건 에러 메시지는 브라우저의 SOP(Same-Origin Policy) 정책에 따라 다른 출처의 리소스를 차단하면서 발생된 에러이고, CORS는 다른 출처의 리소스를 얻기위한 해결 방안이었던 것이다. 결국, SOP정책을 위반해도 CORS 정책에 따르면 다른 출처의 리소스라도 허용이 된다는 의미이다.


💡CORS 에러 해결하기

클라이언트에서 해결

1. 크롬 확장 프로그램 이용

  • Chrome에서는 CORS문제를 해결하기 위한 확장 프로그램을 제공하고있다.
    다음 링크에서 'Allow CORS: Access-Control-Allow-Origin' 크롬 확장 프로그램을을 설치 해준다. 그러면 로컬(localhost) 환경에서 API 테스트시 CORS문제를 해결 할 수 있다.

2. 프록시 사이트 이용

  • 프록시(Proxy)란 클라이언트와 서버 사이의 중계 대리점이라고 할 수 있다.

    다만 현재 무료 프록시 서버 대여 서비스들은 모두 악용 사례 때문에 실제 라이브에서 사용하기에는 무리가 있다. 로컬에서 테스트용으로 잠깐 사용하는 것을 추천한다.

3. jsonp 방식으로 json 데이터 가져오는 방법

  • 자바스크립트 파일이나 css 파일은 동일 출처 정책에 영향을 받지 않고 가져올 수 있다. 이를 이용해서 자바스크립트 파일을 가져와서 이를 json 형식으로 파싱한 후 데이터를 사용할 수 있다.

4. Webpack Dev Server로 리버스 프록싱하기

  • CORS를 가장 많이 마주치는 환경이 로컬에서 프론트엔드 애플리케이션을 개발하는 경우이다. 백엔드 에서는 이미 Access-Control-Allow-Origin 헤더가 세팅 되어 있지만, 이 헤더가 http://localhost:3000 같은 범용적인 출처를 넣어주는 경우는 드물다.
  • 프론트엔드 개발자는 대부분 웹팩과 webpack-dev-server를 사용하여 자신의 머신에 개발 환경을 구축하는데, 이 라이브러리가 제공하는 프록시 기능을 사용하면 아주 편하게 CORS 정책을 우회 할 수 있다.
module.exports={
  devServer: {
    proxy: {
      '/api': {
        target: 'http://api.guard.com',
        changeOrigin: true,
        pathRewrite: {'^/api': ''},
      },
    }
  }
}

서버에서 해결

1. Access-Control-Allow-Origin 헤더 세팅하기

  • 클라이언트측 브라우저에서 발생하는 에러이긴 하지만 서버에서 헤더를 세팅해 주는 것이 가장 기본적인 CORS에러 해결 방법이다.
  • 만약 클라이언트와 서버 모두 자신이 제어할 수 있다면 서버에서 Access-Control-Allow-Origin 헤더를 세팅해 주는것이 가장 좋다.
const express = require('exporess');
const app = express();

app.get('/api', (req, res) => {
  res.header('Access-Control-Allow-Origin', '도메인');
  res.send(data);
});

혹시나 Access-Control-Allow-Origin: * 이런식으로 작성하는 것은 피해야 한다. * 를 사용하면 모든 출처에서 오는 요청을 허용하는 것이기 때문에 사용하지 말고, 허용하고자 하는 도메인을 꼭 작성하도록 해야한다.

2. CORS 미들웨어 사용하기

  • Express로 구축한 경우 Node.js 미들웨어 중 하나인 CORS를 사용하여 쉽게 해결할 수 있다.
const express = require('express');
const cors = require('cors');
const app = express();

const corsOptions = {
  origin: '허용하고자 하는 도메인',
};

app.use(cors(corsOptions));

참고

profile
기록하는 습관

0개의 댓글

관련 채용 정보