본문 바로가기

프로그래밍 일반/프론트엔드

[react] cra, vite 없이 직접 리엑트 프로젝트 세팅하기2(webpack) - 프록시 서버

목차
프로젝트 기본 구조
웹팩
바벨
타입스크립트
CSS전처리
환경변수

정적 파일1(image, svg)
정적 파일2(font)
라우팅
완성파일

chat gpt가 제공한 웹팩 그림1

 

저번 글에서는 리엑트와 웹팩 기반 프론트엔드 프로젝트에서 기본적인 웹팩 세팅에 대해 알아보았다.

이번에는 백엔드 및 서드파티 api와 원활한 소통을 위한 프록시 설정에 대해 알아보겠다.

 

* 이 글은 이전 글인 "[react] cra, vite 없이 직접 리엑트 프로젝트 세팅하기1(webpack) - 바벨, 타입스크립트, css 전처리, 환경변수, 정적 파일"에서 이어진다.

2024.08.18 - [프로그래밍 일반/프론트엔드] - [react] cra, vite 없이 직접 리엑트 프로젝트 세팅하기1(webpack) - 바벨, 타입스크립트, css 전처리, 환경변수, 정적 파일

 

[react] cra, vite 없이 직접 리엑트 프로젝트 세팅하기1(webpack) - 바벨, 타입스크립트, css 전처리, 환

목차프로젝트 기본 구조웹팩바벨타입스크립트CSS전처리환경변수정적 파일1(image, svg)정적 파일2(font)라우팅완성파일 일반적으로 리엑트 프로젝트는 cra나 vite 등의 cli로 자동 세팅이 가능하다.이

chartist1206.tistory.com

 

프록시에 대한 배경지식

 


1. 프록시 서버란?

  • 네트워크 통신용어에서, 네트워크 통신과정에서 출발지와 도착지 간에 경유하는 네트워크 인터페이스 
  • 프록시 서버는 클라이언트와 서버, 혹은 서버와 서버 통신간에 요청이 경유하는 서버
  • 일반적인 용도는 네트워크 요청들을 1차적으로 보안검사하고 걸러내는 게이트웨이 역할이나 로드 벨런싱, 혹은 클라이언트에게 백엔드의 쿼리 파라미터나 헤더 등 동작 방식을 은폐하는 것이다.

2. 프론트엔드 개발과 프록시 서버의 관계

  • 브라우저는 보안상의 이유로 SOP를 준수한다.
    • SOP란, same-origin(동일 출처)간에만 요청을 허용하는 정책이다. 여기서 origin은 " 프로토콜 + 호스트 + 포트"를 의미하며, 이 중 하나라도 요청 측과 응답 측이 다르다면 cross-origin이라 부른다.
    • cross-origin 요청은 SOP에 따라 기본적으로 브라우저 측에서 해당 요청을 읽기 못하도록 막는다. 하지만 클라이언트는 로컬 개발 프론트엔드에서 실제 배포된 백엔드에 요청을 한다던가 OAuth같은 외부 API를 이용하는 경우가 있는데, 이 때 SOP 정책을 우회하기 위한 설정을 CORS라고 부른다.  
  • CORS를 설정하기 위해서는 두 가지 방법이 있는데, 하나는 서버 측에서 응답 헤더에 access-control-allow-origin : *. 즉, 모든 origin에 대한 허용을 함으로써 브라우저의 cors에러를 피할 수 있다.
  • 하지만, 이 방식은 cross-site 간에 쿠키와 같은 인증 정보 전송을 불가능하게 만든다. 따라서, 로그인 등의 인증 로직에서 타도메인에 쿠키를 보내야 하는 경우, cors에러가 다시 발생한다.
  • 이 문제를 피하기 위한 방법 중 하나는 서버에서 로컬 개발 포트를 전부 열어주는 것인데, 이 경우에는 쿠키 보안 관련 문제가 생긴다.
    • 쿠키는 CSRF공격, 즉 타 도메인에서 유저의 쿠키를 탈취하여 해커의 서버로 보내는 걸 막기 위해 브라우저에서 여러 제한 옵션을 걸 수 있다. 대표적으로 secure, httpOnly, same-site가 있다.
      • secure은 https프로토콜에만 쿠키를 넣을 수 있는 것으로, 암호화되지 않은 http 요청에서 쿠키 정보를 탈취하는 걸 막는다.(로컬 호스트에는 적용되지 않으므로 개발에 영향을 주지 않는다.)
      • httpOnly는 자바스크립트 코드에서 도메인의 쿠키에 접근하지 못하도록 만는다.(원래 쿠키는 document.cookies로 접근가능하나, 이 옵션이 설정되면 빈 데이터를 읽어온다)
      • same-site는 타도메인에 쿠키를 전송할 수 있는지 여부를 설정한다.
        • none | 타도메인 쿠키 전송을 허용(csrf 공격 등에 취약함)
        • strict | 타도메인 쿠키 전송을 엄격히 제한함.
        • lax | 경우에 따라 타도메인에 쿠키 전송을 허용함
          • 안전한 요청 메소드인 GET, HEAD 이어야 함
          • 그 이외의 메소드인 경우, 사용자의 상호작용(링크 클릭, 브라우저 리디렉션)이 있어야 쿠키 전송가능
    • 이처럼 cors 에러 해결과 cross-site간 쿠키 전송, 그리고 쿠키 관련 보안, 세 가지를 해결하기 위해서 프록시 서버를 사용한다.
      • 프론트엔드 측에서 백엔드의 origin과 동일한 프록시 서버를 생성해서 모든 요청을 해당 프록시를 경유하도록 한다.
      • 이러면 cors 에러를 피할 수 있고 cross-site간 안전한 쿠키 전송이 가능하다.

 

웹팩 설정하기


프론트엔드에서 로컬 서버에 프록시를 설정하는 방법은 일반적으로 3가지이다. 하나는 package.json에서 proxy 속성을 이용하는 것이고, 두번째는 웹팩의 개발 서버 모드의 옵션에서 proxy를 이용하는 것, 마지막은 http-proxy-middleware 라이브러리를 이용하는 것이다.

첫번째는 api 요청 경로에 따라 여러 개의 프록시 서버 처리를 하는 등 복잡한 처리가 어렵고, 세번째는 두번째에 내장되어 있으므로, 두번째 방식인 웹팩을 이용하자.

 

1. webpack.config.js

웹팩 설정 파일에서 개발 서버를 띄우기 위한 devServer속성이 있을 것이다. 거기에 proxy속성을 추가한다.

아래는 프론트 로컬 서버 " localhost:4000"에서 두api 요청인 "http://localhost:5000/getjson", "http://echo.jsontest.com/echo"를 프록시 서버로 경유하는 설정이다.

   proxy: [
        {
          context: ["/getjson"],
          target: "http://localhost:5000",
          secure: false,
          changeOrigin: true,
    
        },
        {
          context: ["/echo"],
          target: "http://echo.jsontest.com",
          secure: false,
          changeOrigin: true,
        },
      ],

 

각 속성에 대한 설명

  • context | 프록시 서버를 이용할 pathname이다. 예컨대, "getjson"이 있으면, 해당 path를 포함하는 모든 요청은 프록시 서버를 경유한다.
  • target | 프록시 서버가 사용할 origin이다. 백엔드와의 origin 일치를 위해서 백엔드의 도메인과 동일하게 설정하는 것이 일반적이다.
  • secure | 프록시 서버가 목적지 서버에 https 설정을 확인할지 여부이다. false로 되어 있으면 https 여부 상관없이 통신한다.
  • changeOrigin | 호스트인 프론트 로컬 서버의 헤더를 프록시의 origin으로 덮어쓸지 결정한다. 외부 도메인과의 통신을 위해 true로 설정하는 것이 일반적이다.

2. 요청 방법

이제 프론트 로컬 서버인 localhost:4000으로 두 요청을 보내자.

(이 때 주의할 점은)

그러면 프록시 설정에 따라 각각 localhost:4000/getjson은 http://localhost:5000/getjson으로,  localhost:4000/echo는 http://echo.jsontest.com/echo로 서버에 전송된다.

 

3. 콜백 설정

해당 프록시 요청에다가 추가적인 콜백 설정을 하려면 아래처럼 추가한다.

   {
          context: ["/getjson", "/getjson2", "/setAnotherCookie"],
          target: "http://localhost:5000",
          secure: false,
          changeOrigin: true,
          
          // 동적 작업용
          router: function (req) {},
          onProxyReq: (proxyReq, req, res) => {},
          onProxyRes: (proxyRes, req, res) => {
            /* handle proxyRes */
            // console.log("proxyRes", proxyRes);
            // console.log("proxyRes.cookie", proxyRes.header);
          },
          onError: (err, req, res) => {
            /* handle error */
          },
        },

각 속성에 대한 설명

  • router | 요청할 target을 동적으로 재설정한다.
  • onProxyReq, onProxyRes | 프록시 요청에 동적인 콜백을 추가한다.

 

4. 추가적인 설정방법

위에서 서술한 속성들은 웹팩 공식문서에서 다루나, 그 이외의 속성들은 다루지 않는다.

대신, 웹팩의 프록시 설정은 webpack-devServer 라이브러리를 사용하고, 이 라이브러리는 http-proxy-middleware의 설정을 사용하므로, 해당 라이브러리의 공식문서에 있는 옵션들을 webpack.config.js의 devServer.proxy에서 그대로 사용하면 된다.

 

http-proxy-middleware의 공식문서

https://www.npmjs.com/package/http-proxy-middleware#http-proxy-options

 

http-proxy-middleware

The one-liner node.js proxy middleware for connect, express, next.js and more. Latest version: 3.0.3, last published: a month ago. Start using http-proxy-middleware in your project by running `npm i http-proxy-middleware`. There are 4138 other projects in

www.npmjs.com

 

테스트용 프로젝트의 github 

https://github.com/charchar111/test-proxy-webpack

 

GitHub - charchar111/test-proxy-webpack: this project is test for dev proxy server(webpack-dev-server) in react+webpack architec

this project is test for dev proxy server(webpack-dev-server) in react+webpack architecture - charchar111/test-proxy-webpack

github.com