본문 바로가기

프로그래밍 공부내용/개인 프로젝트

Local 환경에서 Open API 사용하기 (feat. CORS)

가만히 앉아서 결과를 기다리는 건 성미에 안 맞기도 하고,

 

뭔가를 만든다는 건 그 자체로도 굉장히 재밌는 행위라, D3 공부도 할 겸 프로젝트를 시작했다.

 

그리고 역시나 그렇듯 시작부터 난관에 봉착했다.

문제

개발자라면 BE, FE를 가지리 않고 누구나 익숙한 문제이다. 바로 CORS..

우테코 과정동안은 많이 만나서 BE에서 allow origin을 해주거나, local server를 따로 만들어줘서 해결했었지만

이번엔 Open API를 사용하고 있어서 이런 해결책을 쓸 수 없었다.

오늘은 Localhost에서 Open API를 사용하며 만났던 CORS와 이를 해결하기 위한 여정을 기록하려 한다.

 

CORS가 뭔데?

간단하게만 설명하고 넘어가려고 한다.

 

다들 글로 정리를 잘 해놓으신 분들이 많아서 참조로 올린 블로그들을 확인해주기 바란다.

 

CORS

CORS라는 이름은 Cross Origin Resource Sharing을 줄여놓은 뜻으로 교차출처에 관한 규칙이다.

 

교차출처가 뭐냐고?

 

나누는 기준이 세가지 있다.

 

Protocal(http,https), Host(domain), Port(포트번호).. 이 세 가지가 일치하지 않으면 SOP에 의해서 브라우저가 요청을 막는다.

 

이유는 보안때문인데, 동일출처가 아닌경우 CSRF나 XSS등의 공격에 취약할 수 있다.

 

뭐 여담으로 CORS가 먹히지 않는 요청이 3가지 있는데 preflight, Simple request, Credential Request등이 있다.

 

해결 방법

가장 중요한 것은 왜? 에서 끝나지 않고 어떻게? 로 이어져 나가는 그 과정아니겠는가?

 

그래서 CORS를 어떻게 해결하면 되는지 살펴보자

1.정석대로 Access-Control 해주기

가장 좋은 방법이다. 사실 백엔드 단에서 처리해주면 더할나위 없이 좋다.

혹은 local에서 서버를 돌리도록 docker 이미지를 공유해준다면, 같은 출처(localhost, domain, port)가 되기 때문에 쉽게 해결된다.

하지만 지금 상황에서는 Open API라 백엔드 단을 함부로 손댈 수 없었다.

 

이걸 또 해결할 수 있는데, 내가 백엔드 서버를 배포해서 reverse proxy하도록 하면 된다.

근데 이것도 손이 굉장히 많이 가는 작업이고 사실 개발만 하겠다면 상관없지만 서비스라고 생각하면 상당히 안 좋은 선택이다. CORS의 목적을 위배하는 편이기도 하고, CORS 회피를 위한 server를 올리는 것은 비용이 너무 많이 든다.

 

2. postman + msw 사용하기

postman을 이용하면 굳이 로컬에서 응답하지 않아도 요청의 응답형태를 확인할 수 있다.

다만 실제 응답처럼 보여야 개발할 때 편하기 때문에 msw를 이용해서 mocking data를 넣어줄 수 있다.

근본적인 해결책은 아니지만 개발단에서는 이 정도로도 충분할지도 모른다.

 

다만 나는 각 query param으로 보내준 요청에 대해서 dynamic하게 바뀌는 경우가 생기지 않을까 생각해서 이 방법은 사용하지 않았다.

(사실 msw까지 달아줘야해서 손이 많이가고 유지보수가 좀 어려운 점도 한 몫 했다.)

 

3. webpack dev server 이용해서 바꿔주기!!

이걸 보고 정말 webpack이 대단하구나 느꼈다.

최종적으로 사용한 방법이 이것이다.

놀랍게도 webpack에서 reverse proxy를 해줄 수 있다.

 

어떻게 하냐고? webpack 문서를 잠깐 보고 오자. 여기보면 dev server에 proxy라는 것을 넣어줄 수 있다.

 

module.exports = {
  mode,
  devServer: {
    historyApiFallback: true,
    port: 3000,
    hot: true,
    proxy: {
      '/': {
        target: 'https://api.steampowered.com', //url을 target url로 변경하도록 설정
        changeOrigin: true, //host header의 origin을 변경하도록 설정
        pathRewrite: { '^/': '' }, //https가 invalid certificate를 default로 막는 것을 우회
      },
    },
  },
  ...
  }

이렇게 proxy에 해당하는 부분에 url을 넣어주게 되면 해당 url을 target으로 변경한 것 "처럼" 작동한다.

(나는 steam api를 써서 요청이 steampowered로 돼 있다 ㅋㅋ)

 

4. img 태그?

이건 조사하다가 찾은 재밌는 글인데, CORS 예외조항을 이용해서 가져오려는 시도를 발견했다.

 

렌더될 이미지, 스타일 시트 같은 경우 CORS 우회가 되기 때문에 img 태그나 script 태그를 이용해서 가져오려는 시도였다.

 

<img src="https://api.steampowered.com">
<script src="https://api.steampowered.com" />

하지만 이렇게 가져오면 요청은 성공하고 데이터도 주긴 하는데,, JS단에서 절대 손을 댈 수가 없단다.

 

(역시 똑똑한 석학들이 모여서 만든 규범에 예외를 찾는 것은 쉽지 않다.)

 

5. Chrome 확장 프로그램 이용하기

이것도 꼼수에 가깝지만 브라우저에 확장프로그램을 깔아서 해결할 수 있다. 아까 CORS는 브라우저가 관리한다고 한 것이 기억나는가? 그래서 브라우저를 조작하면 적어도 로컬환경에서 CORS가 나는 것을 막을 수 있다.

로컬에서 개발을 하기 위해서는 괜찮은 선택지라고 생각한다.

아래 사이틀르 이용해서 extension을 추가할 수 있다.

https://chrome.google.com/webstore/detail/allow-cors-access-control/lhobafahddgcelffkeicbaginigeejlf

 

Allow CORS: Access-Control-Allow-Origin

Easily add (Access-Control-Allow-Origin: *) rule to the response header.

chrome.google.com

 

 

결론

이렇게 CORS를 만나서 해결을 해봤다.

 

우테코에서 처음 CORS를 만났을 때는 적잖이 당황했지만, 이제는 새로운 방법이 없나 찾아볼 정도로 여유가 생겼다.

 

나는 이 정책이 꽤 재밌는 정책이라고 생각한다.

 

브라우저가 이걸 관리한다는 것이 좀 신기하고, 우회하는 방법들도 신기하다. 그래서 익숙해 질 수록 즐거운 것 같다.

 

나는 Webpack으로 해결을 했지만, Open Api가 아니거나 혹은 다른 사정이 있다면 본인만의 해결방법을 익혀나가길 바란다.

 

 

 

(참고)

https://developer.mozilla.org/ko/docs/Web/HTTP/CORS

 

교차 출처 리소스 공유 (CORS) - HTTP | MDN

교차 출처 리소스 공유(Cross-Origin Resource Sharing, CORS)는 추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라

developer.mozilla.org

https://webpack.js.org/configuration/dev-server/#devserverproxy

 

DevServer | webpack

webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.

webpack.js.org

https://evan-moon.github.io/2020/05/21/about-cors/

 

CORS는 왜 이렇게 우리를 힘들게 하는걸까?

이번 포스팅에서는 웹 개발자라면 한번쯤은 얻어맞아 봤을 법한 정책에 대한 이야기를 해보려고 한다. 사실 웹 개발을 하다보면 CORS 정책 위반으로 인해 에러가 발생하는 상황은 굉장히 흔해서

evan-moon.github.io

https://joshua1988.github.io/webpack-guide/devtools/webpack-dev-server.html#webpack-dev-server

 

Webpack Dev Server | 웹팩 핸드북

Webpack Dev Server 웹팩 데브 서버는 웹 애플리케이션을 개발하는 과정에서 유용하게 쓰이는 도구입니다. 웹팩의 빌드 대상 파일이 변경 되었을 때 매번 웹팩 명령어를 실행하지 않아도 코드만 변경

joshua1988.github.io

https://inpa.tistory.com/entry/WEB-%F0%9F%93%9A-CORS-%F0%9F%92%AF-%EC%A0%95%EB%A6%AC-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95-%F0%9F%91%8F

 

[WEB] 📚 악명 높은 CORS 개념 & 해결법 - 정리 끝판왕 👏

악명 높은 CORS 에러 메세지 웹 개발을 하다보면 반드시 마주치는 멍멍 같은 에러가 바로 CORS 이다. 웹 개발의 신입 신고식이라고 할 정도로, CORS는 누구나 한 번 정도는 겪게 된다고 해도 과언이

inpa.tistory.com