티스토리 뷰

코드스테이츠(SEB_FE_42)

[Deploy] Proxy

codeyun2 2023. 2. 6. 11:52

CORS(Cross-Origin Resource Sharing)

CORS 요청

1. React 앱: 브라우저에 요청 보냄

2. 브라우저: 서버에 리소스 요청

3. 서버: 접근 권한(출처 동일 여부, 요청 헤더) 확인 후 응답

4. 브라우저: 출처가 같다면 React 앱으로 응답 보냄, 다르면 CORS 에러

 

교차 출처 리소스 공유.

기본적으로는 브라우저의 현재 주소와 API의 도메인이 일치해야 데이터에 접근할 수 있음

HTTP 헤더를 사용하여 한 출처에서 실행 중인 웹 애플리케이션이

다른 출처(서버)의 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제

 

만약 서비스 및 프로젝트가 모든 출처의 접근을 허락한다면 보안성이 낮아지고 해킹의 위험에 노출될 수 있음

프론트엔드 개발자는 백엔드 개발자에게 프론트엔드 개발 서버 도메인을 허용해달라고 요청하고,

백엔드 개발자는 응답 헤더에 필요한 값들을 담아서 전달(라이브 데이터 보호 목적)

- 브라우저가 적절한 응답 헤더를 받지 못하면 CORS 에러 발생

 

출처(Origin)

URL의 스킴(프로토콜), 호스트(도메인), 포트

-> 스킴, 호스트, 포트가 동일해야 같은 출처

 

라이브 데이터(live data)

실제 서비스되고 있는 앱의 데이터베이스(DB. 서버와 연결됨)에 적재되고 있는 데이터

유저, 상품, 결제 등 민감성 높은 데이터이기 때문에 보안이 중요함

 

Proxy

보안, 캐시, 우회

(포워드 프록시, 리버스 프록시)

 

CORS 설정 대신에

Webpack Dev Server 혹은 React 라이브러리에서 제공하는 proxy 기능을 사용하여 CORS 정책을 우회할 수 있음

 

브라우저는 React 앱(3000포트)으로 요청하고, 해당 요청을 백엔드로 전달

React 앱이 서버(8000포트)로부터 받은 응답 데이터를 다시 브라우저로 전달하기 때문에

브라우저는 CORS 정책을 위반한지 모르게 됨

-> proxy 기능으로 브라우저를 속이는 것(실제로 8000 포트 요청이지만 3000 포트로 요청 보낸 것으로 인식되도록)

 

proxy 적용

1, 2. React 앱: 브라우저를 통해 API 요청할 때 proxy를 통해 백엔드 서버로 요청을 우회하여 보냄

3. 백엔드 서버: 응답을 React 앱으로 보냄

4. React 앱: 응답을 브라우저에 전달

=> 브라우저는 동일 출처라고 인식하게 됨

 

 

Proxy 사용법

1. Webpack dev server proxy

브라우저에서 API를 요청할 때 백엔드 서버에 직접 요청하지 않고

현재 개발 서버의 주소로 우회 요청

 

브라우저 요청

웹팩 개발 서버에서 해당 요청을 받아 백엔드 서버에 전달

백엔드 서버에서 응답한 내용을 다시 브라우저로 반환

 

웹팩 개발 서버 proxy 설정 방법(전역)

- 웹팩 설정을 통해 적용

- CRA로 만든 프로젝트의 경우 packge.json에 "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 주소"
}

 

CRA(create-react-app)로 만들어진 프로젝트 package.json에 proxy를 객체로 설정할 경우

proxy를 문자열로 설정하라는 오류 발생

더보기
// 오류 발생
"proxy" : {
  "/api" : {
    "target" : "http://localhost:3080"
  },
  "/api2" : {
    "target" : "http://localhost:3070"
  }
}

 

- 기존 fetch, axios 요청의 도메인 부분 제거

// 기존
export async function getAllfetch() {
    const response = await fetch('우회할 api주소/params');
    .then(() => {
			...
		})
}

// proxy 이용
export async function getAllfetch() {
    const response = await fetch('/params');
    .then(() => {
			...
		})
}

 

2. React Proxy

1.webpack dev server가 제공하는 proxy는 전역적인 설정이기 때문에

해당 방법이 충분히 적용되지 않는 경우가 생기기도 함

-> http-proxy-middleware 라이브러리를 사용하여 수동으로 proxy 적용

 

설치

npm install http-proxy-middleware --save

 

React App의 src 폴더에 setupProxy.js 생성

(파일 이름 고정)

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

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

// 요청 시(fetch, axios) /params(path parameter)도 써줘야함

 

여러 api 사용(배열)

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

module.exports = function(app) {
  app.use(
    ['/api', '/api2', '/api3'],
    createProxyMiddleware({ 
      target: 'http://localhost:5000', // 배열의 0번째 요소와 매치
      changeOrigin: true, // 대상 서버 구성에 따라 호스트 헤더가 변경되도록 설정
      router: {
        'api2' : 'http://localhost:3070', // 배열의 1번째 요소와 매치
        'api3' : 'http://localhost:3080', // 배열의 2번째 요소와 매치
      }
    })
  );
};

 

여러 api 사용 시 각각 나눠주기

- 엔드포인트를 제대로 인식하지 못하는 경우도 있어 위의 방식(배열) 사용을 추천

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

module.exports = function(app) {
  app.use(
    '/api',
    createProxyMiddleware({
      target: 'http://localhost:5000',
      changeOrigin: true,
    })
  );
  app.use(
    '/api2',
    createProxyMiddleware({
      target: 'http://localhost:3070',
      changeOrigin: true,
    })
  );
};

 

- Webpack dev server와 마찬가지로 기존 fetch, axios 요청의 도메인 부분 제거

// 기존
export async function getAllfetch() {
    const response = await fetch('우회할 api주소/params');
    .then(() => {
			...
		})
}

// proxy 적용
export async function getAllfetch() {
    const response = await fetch('/params');
    .then(() => {
			...
		})
}

 

 

 

 

 

23.02.06

S4U10 Proxy

댓글
공지사항