Proxy

지은·2022년 12월 8일
2

네트워크

목록 보기
14/17
post-custom-banner

Proxy 서버

: 클라이언트와 서버 사이에서 대리로 통신을 수행해주는 서버
즉, Proxy 서버는 클라이언트와 서버 사이에서 요청과 응답을 처리해준다.

Proxy 서버를 사용하는 이유

Proxy를 사용하면 CORS 정책을 우회할 수 있게 된다.

CORS 에러를 해결하는 정석적인 방법은 프론트엔드 개발자가 백엔드 개발자에게 프론트엔드 개발 서버 도메인을 허용 해달라고 요청을 하면,
백엔드 개발자가 응답 헤더에 필요한 값들을 담아서 전달을 해주는 것이다.
➡️ 즉, 개발 과정에서 CORS 에러를 쉽게 해결하기 위해 Proxy를 사용할 수 있다.

CORS(Cross Origin Resources Sharing)

: 교차 출처 리소스 공유
추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 자원에 접근할 수 있는 권한을 부여하도록 브라우저에게 알려주는 체제
*출처(origin) : URL의 프로토콜, 도메인, 포트

일반적인 요청과 응답의 흐름

  1. React 앱이 브라우저에게 요청을 보낸다.
  2. 브라우저는 서버에게 리소스를 요청한다.
  3. 이때 서버는 접근 권한이 있는지(출처가 같은지) 확인하고, 200 OK 응답을 보낸다.
  4. 브라우저는 받은 리소스의 출처가 같은지 아닌지 확인하고,
    출처가 같다면 프론트엔드에게 응답을 보내주고,
    출처가 다르다면 응답을 파기한다. (CORS Error)

프록시 사용 후

  1. 브라우저가 서버가 아닌, React 앱으로 데이터를 요청하고
  2. React 앱은 해당 요청을 서버로 전달한다.
  3. 서버로부터 받은 응답 데이터를 다시 브라우저로 전달한다.
    ➡️ 이 방법을 이용하면 브라우저는 CORS 정책을 위반하여도 이 사실을 눈치채지 못하고 허용하게 된다.

Proxy 사용법

Webpack dev server Proxy

webpack dev server에서 제공하는 proxy 기능을 이용할 수 있다.

  1. 이 기능을 이용하면 브라우저가 API를 요청할 때 백엔드 서버에 직접적으로 요청하지 않고, 현재 개발 서버의 주소로 우회 요청을 하게 된다.
  2. 그러면 webpack dev server에서 해당 요청을 받아 그대로 백엔드 서버에 전달하고,
  3. 백엔드 서버에서 받은 응답을 다시 브라우저쪽으로 반환한다.

CRA로 만든 React 프로젝트에서는 package.json 파일에 "proxy" 값을 설정하여, 프록시를 쉽게 설정할 수 있다.

// ...
"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(() => {
    ...
  })
}

React Proxy

http-proxy-middleware 라이브러리를 이용해서 수동으로 proxy를 적용해줄 수도 있다.

http-proxy-middleware 설치

npm install http-proxy-middleware

setupProxy.js 파일

React 앱의 src 파일 안에 setupProxy.js 파일을 생성하고, 안에서 설치한 라이브러리를 불러온다.

// src/setupProxy.js
const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
  app.use(
    '/api', // proxy가 필요한 path parameter를 입력한다.
    createProxyMiddleware({
      target: 'http://localhost:5000', // 우회할 API 주소(서버 주소)
      changeOrigin: true, // 대상 서버 구성에 따라 호스트 헤더가 변경되도록 설정하는 부분이다.
    })
  );
};

기존의 fetch/axios로 요청하는 부분에서 도메인 부분을 제거한다.

export async function getAllFetch() {
  const response = await fetch('우회할 API 주소/params');
  .then(() => {
    ...
  })
}
                        ⬇️
        
export async function getAllFetch() {
  const response = await fetch('/params'); // 도메인 제거
  .then(() => {
    ...
  })
}

프록시 서버 여러 개 열기(Multi-Proxy)

// src/setupProxy.js
const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function (app) {
	app.use(
		'/api1', // 이름이 겹쳐서 api → api1로 변경
		createProxyMiddleware({
			target: 'http://localhost:3080',
			changeOrigin: true,
		})
	);

	app.use(

		'/api2',
		createProxyMiddleware({
			target: 'http://localhost:3070',
			changeOrigin: true,
		})
	);
};

혹은 아래처럼 더 간단하게 작성할 수도 있다.

// src/setupProxy.js
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'
      } 
    })
  );
};
profile
블로그 이전 -> https://janechun.tistory.com
post-custom-banner

0개의 댓글