CORS에러와 해결법

정종일·2023년 2월 24일
0

Web

목록 보기
3/6
post-custom-banner

CORS 첫경험

SSAFY 시절 프로젝트를 진행하던 중 한식연구원(?) 사이트에서 이미지를 불러와 출력해야 하는 과정이 있었는데, 이 때 이미지를 불러오는 과정에서 CORS 에러를 마주하게 되었다.

얼추 이런 느낌이었던 것 같다.

지금에야 이게 어떤 에러고 어떻게 해결해야하는지 알고 있지만 당시에는 처음 겪어보는 에러라 무척 당황스러웠고 어떻게 해결해야하는지 감이 오지 않았었다. 그래서 오늘은 CORS 에러가 왜 발생하는지, 어떻게 해결하는지 알아보려 한다.

그래서 CORS가 뭔데?

Cross-Origin-Resource Sharing. 흔히들 CORS라 부른다. 한국어로는 ‘교차 출처 리소스 공유’. 사실 이렇게만 봐서는 이게 어떤 걸 의미하는지 감을 잡기 힘들다.

교차 출처.. 뭐?

쉽게 말하자면 같은 출처(URL)에서만 리소스를 공유하기 위한 SOP(Same-Origin Policy) 정책을 지키지 않아 발생하는 에러라고 보면 된다. 출처를 구성하는 세 요소는 프로토콜·도메인(호스트 이름)·포트로, 이 중 하나라도 다르면 CORS 에러를 만나게 된다.

즉 아무런 설정도 되어있지 않다는 가정 하에

https://example1.com 에서 https://example2.com 의 API를 받아오고자 요청을 하면 CORS 에러를 마주하게 되는 것이다.

누가 이걸 막아?

사실 CORS 정책을 위반하는 요청은 서버에 구현된 것이 아니라 브라우저에 구현되어 있다. 클라이언트가 CORS 정책에 위배되는 요청을 하더라도 서버에 CORS에 대한 로직이 구현되어 있지 않다면 서버는 정상적으로 응답하지만 브라우저가 해당 응답을 분석해 CORS 정책을 위반한 것인지 아닌지 판단하는 것이다.

그럼 어떻게 해결해?

크게 두 가지 해결법이 있다

Access-Control-Allow-Origin 세팅

CORS 정책 위반으로 인한 문제를 해결하는 가장 대표적인 방법이다. 서버에 Access-Control-Allow-Origin 헤더에 값을 세팅해주면 된다.

다만 와일드카드인 * 값을 넣는다면 모든 출처에 대한 요청을 허용하도록 설정되는데 이는 보안상 이슈가 발생할 수 있으니 귀찮더라도 내가 허용할 출처만 명시하는 것이 바람직하다.

Ex) Access-Control-Allow-Origin: https://example.com

이 헤더는 Nginx나 Apache와 같은 서버 엔진의 설정에서 추가할 수도 있지만, 아무래도 복잡한 세팅을 하기는 불편하기 때문에 소스 코드 내에서 응답 미들웨어 등을 사용하여 세팅하는 것을 추천한다.

Spring, Django 등의 프레임워크의 경우 CORS 관련 설정을 위한 세팅이나 라이브러리 등을 제공하고 있으니 사용하면 편리하다.

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

CORS Proxy는 브라우저와 서버간의 상호작용을 위해 중간 서버를 사용하는 방법이다. 그러나 이 방법은 추가 구성이 필요하며, 대규모 트래픽이 발생할 경우 성능 문제가 발생할 수 있다.

백엔드 서버에 http://localhost:3000 같은 범용적인 출처를 넣기란 매우 드물기 때문에 요청하는 프론트엔드 쪽에서 아래와 같은 코드로 프록시 서버를 이용할 수 있는데

module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'https://api.example.com',
        changeOrigin: true,
        pathRewrite: { '^/api': '' },
      },
    }
  }
}

이렇게 해놓으면 로컬 환경에서 /api 로 시작하는 URL로 보내는 요청에 대해 브라우저는 localhost:8000/api로 요청을 보낸 것으로 알고 있지만 사실 웹팩이 https://api.example.com 으로 요청을 프록싱해주기 때문에 CORS 정책을 우회하며 요청을 할 수 있게 된다.

다만 실제 프로덕현 환경에서 어플리케이션의 소스를 서빙하는 출처와 API 서버의 출처가 다른 경우 이상한 곳으로 요청이 갈 수 있으니 웬만해서는 백엔드 서버에서 자신이 서비스하는 페이지의 출처를 Access-Control-Allow-Origin 값으로 넣어주는 것이 좋다.

profile
제어할 수 없는 것에 의지하지 말자
post-custom-banner

0개의 댓글