🔥 학습목표
- React Proxy를 사용할 수 있다.
- Webpack dev server에서 제공하는 proxy 기능을 사용해본다.
- React 라이브러리 http-proxy-middleware가 제공하는 proxy를 사용해본다.
Proxy에 대해 학습하기 위해선 이전에 공부한 적 있는 CORS 정책을 다시 떠올려 보아야 한다.
CORS란 "교차 출처 리소스 공유" 정책을 뜻한다.
우리가 어떤 웹 앱을 개발하고 나면, 그 안에서 사용되는 여러 리소스를 요청하고 전달받는 일이 일어날텐데, 그때 클라이언트의 출처(origin)와 서버의 출처가 동일해야만 한다.
모든 도메인을 허용한 채 라이브 데이터(live data) 등을 주고받으면 해킹을 당했을 때 사용자가 의도하지 않은 데이터를 불러오게 될 수도 있고, 개인 정보가 담긴 중요한 데이터가 낯선 경로를 통해 유출되버릴 수도 있기 때문이다.
따라서 프론트엔드, 백엔드 개발을 할 때
프론트엔드 개발자→백엔드 개발자에게 개발 서버 도메인을 허용해 달라고 요청을 해야한다.
백엔드 개발자는 응답 헤더에 필요한 값(해당 도메인은 허용하겠다는)들을 담아서 전달해줘야 한다.
위의 복잡한 과정을 거치지 않고도 요청/응답을 주고받을 수 있게 프론트엔드와 백엔드 사이에서 중간자 역할을 해주는 기능이다.
React 라이브러리
Webpack Dev Server
에서 제공하는 프록시 기능을 사용하여 CORS 정책을 우회할 수 있다.
클라이언트가 자신을 통해서 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해 주는 컴퓨터 시스템이나 응용 프로그램.
그 기능을 하는 것을 프록시 서버라 부른다.
클라이언트가 프록시를 바라보면, 프록시가 서버와 같이 동작하게 된다.
서버가 프록시를 바라보면, 프록시가 클라이언트처럼 작동한다.
프론트엔드(리액트 앱) → 브라우저 쪽으로 요청을 보낸다.
브라우저 → 백엔드 쪽으로 리소스를 요청한다.
접근 권한이 있는지(출처가 같은지) 확인한다.
권한이 있다면 200 OK
응답을 브라우저에게 보낸다.
출처가 다르면 브라우저 → 프론트엔드로 전달하기 전에 응답을 파기(CORS Error)한다.
React 앱 → 브라우저 쪽으로 요청을 보낸다.
proxy를 통해 백엔드 서버로 요청을 우회하여 보낸다.
백엔드 → 프론트엔드 쪽으로 응답을 보낸다.
프론트엔드 → 브라우저 쪽으로 응답을 전달한다.
결론적으로 출처가 같아져서 브라우저는 이 사실을 눈치채지 못하고 권한을 허용한 것과 같아진다.
클라이언트와 인터넷 사이에 위치한 프록시 서버
🎁 이미지 출처
같은 내부망에 존재하는 클라이언트의 요청을 받아 대신 인터넷으로 요청한다.
프록시 서버가 외부 서버에서 해당 리소스를 받아와 클라이언트한테 제공한다.
내부망에 속한 클라이언트에게 특정 컨텐츠에 대한 접근을 차단할 수 있다.
프록시 서버에 캐싱이 가능하여 두 번째 요청의 경우 저장된 캐시를 바로 보내준다. 따라서 서버의 부하를 줄이고 캐싱된 페이지의 경우 빠르게 조회가 가능하다.
본 서버에서 클라이언트 IP를 추적해도 프록시 서버 IP만 보이게 된다.
서버와 인터넷 사이에 위치한 프록시 서버
🎁 이미지 출처
클라이언트가 웹 서버에 요청하는 게 아닌 프록시로 요청한다.
프록시 서버가 서버에서 데이터를 가져온다.
클라이언트는 프록시 뒤의 서버의 존재를 알 수 없다.
다중 서버 환경을 구축하는 경우 프록시가 여러 서버에 부하를 분산해준다.
마찬가지로 리버스 프록시 서버에 캐싱 되어있는 데이터를 사용할 수 있다.
서비스를 배포할 때 중단 없이 배포 가능하다. 프록시 서버 뒤에 서버 3대가 있을 경우 한 번에 하나의 서버 컴퓨터만 배포한다.
외부에서 서버 IP를 알 수 없기 때문에 보안에 있어서 안전하다.
브라우저 API를 요청할 때, 백엔드 서버에 직접적으로 요청하지 않고 웹팩 개발 서버의 주소로 우회 요청을 한다.
웹팩 개발 서버는 요청을 받아 그대로 백엔드 서버에게 전달하고, 백엔드에서 응답한 내용을 다시 브라우저 쪽으로 반환한다.
CRA를 통해 만든 리액트 프로젝트에서는 pakage.json
에서 "proxy"
값을 설정하여 적용할 수 있다.
...
"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(() => {
...
})
}
전역적이었던 webpack dev server
와 달리,
http-proxy-middleware
라이브러리를 사용하여 수동으로 proxy를 적용하는 방법도 있다.
가장 먼저 아래 명령어로 라이브러리를 설치한다.
npm install http-proxy-middleware --save
그 다음 React App 의 src 파일 내 setupProxy.js
파일을 생성한다.
파일 안에 설치한 라이브러리를 불러온 뒤 미들웨어를 등록한다.
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/api', //proxy가 필요한 path prameter
createProxyMiddleware({
target: 'http://localhost:5000', //타겟이 되는 api url
changeOrigin: true, //대상 서버 구성에 따라 호스트 헤더가 변경되도록 설정
})
);
};
그 후 webpack와 동일하게 fetch, axios에서 도메인 부분을 제거하면 끝난다.