Network

CORS에러를 서버 우회 방법을 통해 해결

범데이 2022. 5. 16. 17:15

1. 개요

때는 웹사이트를 개발할 때의 일이였다.

 

Tistory 블로그에 작성한 글을 크롤링하여서 웹사이트에 뿌려주고 싶은데, CORS에러가 발생하게 되었다.

(CORS에 대해 알고자 한다면, 지난포스팅 참조)

 

웹사이트 상에서 직접적으로 axios 라이브러리를 통해 Tistory 게시글을 fetch하려고 하니, 당연하게도 origin이 달라서 브라우저에서 막는 것이었다.

 

그래서 해결하기 위한 방법 중 일종의 우회 서버를 두는 방식으로 해결을 하고자 하였고, 이에대해 오늘 포스팅 할 예정이다.

 

 

 

2. 서버 우회 환경 구축

아래 그림 중 서버 우회 환경을 구축하기 전의 흐름도는 아래의 좌측과 같고, 우회 서버를 거치는 방식은 우측과 같다.

 

좌측 방식은 Tistory글을 직접적으로 가져오려고 했지만, 우측 방식은 중간에 서버를 두어, 서버로 요청하면 서버에서 Tistory 글을 가져오고, 그 가져온 글을 Client로 리턴해주는 형식이다.

 

간단히 말하자면 CORS에러는 브라우저에서 발생하는 것이기 때문에, 중간의 서버가 다른 origin의 리소스를 가져오는 역할을 대신 해주도록 하는 것이다.

 

 

아래 NodeJS express를 사용한 REST API서버의 참고용 코드 일부이다.

Tistory의 글을 요청하여 가져와서, 호출한 곳으로 리턴해주는 역할을 한다.

...

router.get("/getAboutMe", (req, res) => {
  axios.get("https://bumday.tistory.com/3").then((html) => {
      ...
    
      res.json({
        success: true,
        data: html.data,
      });
    })
    
    ...
});

...

 

아래는 위의 API를 호출하는 웹사이트의 참고용 코드 일부이다. 

  getCrawlingAboutMe() {
    try {
      axios.get("http://localhost:3000/web/getAboutMe").then((html) => {
        ...
      });
    } 
    
    ...
  }

 

 

 

이렇게 처리를 해주었지만, 웹사이트의 포트는 8080이고, API서버의 포트는 3000 이어서,

포트가 달라 또 CORS에러가 난다.

 

하지만 처음의 CORS에러와는 달리 이번 경우는 비교적 쉽게 해결이 가능하다.

  • 요청받는 서버가 내가 구축한 서버이기 때문에, CORS에러가 나지 않도록 서버에서 해당 포트를 열어줄 수도 있고, 
  • 클라이언트에서 proxy 설정을 사용하여 CORS에러가 나지않도록 포트를 맞춰주는 방법을 사용할 수 있다.

이번엔 두번째 방법을 써보도록 한다.

 

 

 

3. 클라이언트에서의 proxy설정

 

다음과 같이 http-proxy-middleware 모듈을 설치해준다.

(해당 모듈에대해 더 알고자 한다면, 공식사이트를 참조하자)

npm i --save http-proxy-middleware

 

설치해준 후 프로젝트 폭더 내 src 폴더 내에 setupProxy.js파일을 생성하여 다음과 같이 설정해준다.

// [PROJECT_ROOT]/src/setupProxy.js
const { createProxyMiddleware } = require("http-proxy-middleware");

module.exports = function (app) {
  app.use(
    "/web", // 호출하는 URL
    createProxyMiddleware({
      target: "http://localhost:3000/", // 대상 URL
      changeOrigin: true,
    })
  );
};

해당 설정은  "/web" 으로 시작되는 URL의 호출이라면 "http://localhost:3000" URL로 Origin을 변경시켜주는 것이다.

 

그런 다음, axios로 요청 시 아래와 같이 "web/~~"를 호출하게 하면,

  ...
  // const getUrl = "http://localhost:3000/web/getAboutMe"; //Before
  const getUrl = "web/getAboutMe"; // New
  axios.get(getUrl).then((html) => {
    ...
  });    
  ...

Proxy설정을 해준것과 같이 http://localhost:3000/web/getAboutMe로 호출하게 된다.

이렇게 요청 URL이 동일 Origin으로 맞춰지게 되면서, CORS 에러가 발생하지 않게 된다.

 

 

4. 결과

위와같이 설정해 준 후, 다시 Application을 실행시켜 주면 다음과 같이 요청이 성공함을 확인할 수 있다. 

 

여기서 주목할 것은 Request URL은 http://localhost:8080/web/getAboutMe으로 보여지나, 

클라이언트의 proxy설정으로 인해 내부적으로 http://localhost:3000/web/getAboutMe으로 바뀌어 요청되게 된다.

 

이렇게 해서 Origin이 맞춰져, 성공 응답( 200 OK )을 받고, 데이터가 정상적으로 리턴됨을 확인할 수 있다.

 


 

웹사이트 개발자라면 흔하디 흔하게 겪는 CORS이슈, 오늘은 우회 서버를 두는 방법으로 해결해 보았다.

 

어떤 에러가 발생하던지 간에 전체적인 구조와 흐름을 파악하는것이 가장 중요한듯 하다. 전체적인 구조에 대한 그림을머릿속으로 그리지 못한다면, 원인도 쉽게 파악하지 못하고, 금방 해결할 일도 에러를 막는데에만 급급하여 삽질을 하고 먼 길을 돌아갈 때가 있다. 

 

코딩만 하는 단순 코더가 아닌 생각을 할 줄 아는 개발자가 되어야겠다.

 

 

 

이외에도 궁금하신 사항이 있다면, 댓글로 남겨주세요. 감사합니다

반응형