매일매일
article thumbnail
Published 2023. 4. 4. 23:35
Proxy React

1. CORS

CORS는 Cross-Origin Resource Sharing의 줄임말로,

추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제이다.

보통 웹 사이트는 동일한 출처의 리소스는 자유롭게 접근할 수 있지만, 다른 출처의 리소스는 보안상의 이유로 접근이 제한된다. 이를 해결하기 위해 웹 서버에서는 Access-Control-Allow-Origin 헤더를 사용하여 허용된 출처의 목록을 설정하고, 웹 브라우저는 이 헤더를 확인하여 해당 출처에서만 리소스에 접근할 수 있도록 제한한다. 이를 통해 보안상의 문제를 예방할 수 있다.

 

출처
웹 콘텐츠의 출처(origin)는 접근할 때 사용하는 URL의 스킴(프로토콜), 호스트(도메인), 포트로 정의된다. 두 객체의 스킴, 호스트, 포트가 모두 일치하는 경우 같은 출처를 가졌다고 말한다.

2. Proxy

그러나 React 라이브러리, 혹은 Webpack Dev Server에서 제공하는 proxy 기능을 사용하면 CORS 정책을 우회할 수 있다.

 

별도의 응답 헤더를 받을 필요 없이 브라우저는 React 앱으로 데이터를 요청하고, 해당 요청을 백엔드로 전달하게 된다. 여기서 React 앱이 서버로부터 받은 응답 데이터를 다시 브라우저로 전달하는 방법을 쓰기 때문에 브라우저는 CORS 정책을 위반한지 모른다.

 

그림과 같이 프로시 서버는 클라이언트와 API 서버 간의 중개를 해준다.

이를 통해 

  1. 캐싱 역할
    프록시 서버가 API 서버에서 응답받은 걸 캐시해둬 불필요한 네트워크 요청같은 걸 줄일 수 있다.
  2. 보안의 역할 
    클라이언트와 api 서버가 서로 직접 연락할 경우 서로의 ip주소를 알게된다
    프록시 서버를 이용하면 클라이언트의 IP 주소와 서버의 IP주소를 감춰주기 때문에 익명의 사용자도 서버에 직접적으로 접근하기 어려워진다(보안성이 높아짐)
  3. 우회(IP주소를 감춰줌)
    인터넷 사용량을 제어할 수 있다.React 개발 서버에 Proxy를 설정해서 CORS Error 해결할 수 있다.

 

3. Proxy 사용법

3-1. webpack dev server proxy

웹팩 개발서버의 proxy 설정은 원래 웹팩 설정을 통해서 적용을 하지만, CRA 를 통해 만든 리액트 프로젝트에서는 package.json 에서 "proxy" 값을 설정하여 쉽게 적용할 수 있도록 구성이 되어 있다.

proxy는 보통 맨 밑에 작성을 해 금방 찾을 수 있도록 한다.

// package.json 

...
"browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
	"proxy" : "우회할 API 주소"
}

그리고 기존의 fetch, 혹은 axios를 통해 요청하던 부분에서 도메인 부분을 제거한다.

export async function getAllfetch() {

    const response = await fetch('우회할 api주소/params');
    .then(() => {
			...
		})
}

// 위에 코드 아래 코드처럼 변경
export async function getAllfetch() {

    const response = await fetch('/params');
    .then(() => {
			...
		})
}

 

만약 API주소가 2개 이상이라면

// package.json 

...
	"proxy" : {
    	"/params1" : {
        	"target" : "우회할 API 주소1"
        },
        "/params2" : {
        	"target" : "우회할 API 주소2"
        }
    }
}

하지만 CRA로 만든 앱인 경우 위와 같이 작성하면 오류가 난다.

왜냐하면 CRA는 Proxy에 string 타입만 작성 가능고 객체는 불가능하기 때문이다.

그러므로 API주소가 2개이상인 경우 미들웨어를 사용해야한다.

3-2. proxy-middleware 

http-proxy-middleware 라이브러리 설치

npm install http-proxy-middleware --save

그리고 React App의 src 파일 안에서 setupProxy.js 파일을 생성하고, 안에서 설치한 라이브러리 파일을 불러온 다음, 아래와 같이 작성한다.  (파일 이름 setupProxy.js 으로 해줘야 자동으로 인식됨)

// setupProxy.js 

const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
  app.use(
    '/api', //proxy가 필요한 path prameter를 입력합니다.
    createProxyMiddleware({
      target: 'http://localhost:3080', //타겟이 되는 api url를 입력합니다.
      changeOrigin: true, //대상 서버 구성에 따라 호스트 헤더가 변경되도록 설정하는 부분입니다.
    }),
   app.use(
    '/api2',
    createProxyMiddleware({
      target: 'http://localhost:3070', 
      changeOrigin: true, 
    })
  );
};

API주소 여러개일 경우, path를 객체로 작성할 수 도 있다.

const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = (app) => {
  app.use(
    ['/api','/api2'],
    createProxyMiddleware({
      target: 'http://localhost:3080',
      changeOrigin: true,
      router: {
        '/api2': 'http://localhost:3070'
      }
    })
  );

그리고 기존의 fetch, 혹은 axios를 통해 요청하던 부분에서 도메인 부분을 제거한다. 

export async function getAllfetch() {

    const response = await fetch('우회할 api주소/params');
    .then(() => {
			...
		})
}

export async function getAllfetch() {

    const response = await fetch('/params');
    .then(() => {
			...
		})
}

 

참고

코드스테이츠 유어클래스

'React' 카테고리의 다른 글

Redux Thunk 미들웨어 사용해보기  (0) 2023.04.11
to do 앱 만들기 후기  (0) 2023.04.09
리액트로 달력만들기  (0) 2023.04.08
Custom Hook  (0) 2023.03.27