이전 포스팅에서 Express와 React를 설치하고 실행까지 해봤습니다. 저번 포스팅에서 해봤듯, React 앱은 localhost:3000에서, Express 서버는 localhost:5000에서 접근할 수 있습니다. 그런데 어떻게 해야 Express 서버로 접속했을 때 React로 개발한 프론트엔드가 나오게 할까요? 이번 포스팅에서 해결해보겠습니다.
React와 Express 서버의 작동방식
그림을 통해 알 수 있듯, 또 접속 포트가 달랐다는 점에서 알 수 있듯, 둘은 각자 개별적으로 동작합니다. 다시 말해서, React는 Express가아닌 자체 서버를 사용하고 있습니다. 물론 이 상태로도 React 앱 개발은 문제 없이 가능합니다. 그런데 이렇게 된다면 React와 Express간의 통신이 굉장히 번거롭게 됩니다. 따라서 Express 서버에서 바로 리액트 앱을 유저에게 보여주는 형태를 만들어 보겠습니다.
React Build 파일을 Express 서버 위에서 돌리기.
/app.js를 다음과 같이 수정하세요.
const express = require("express");
const path = require("path"); // react build 파일에 접근하기 위해 필요함
const port = process.env.PORT || 5000;
// express 객체 생성
const app = express();
app.use(express.static(path.join(__dirname, "client/build")));
app.use("/", function (req, res, next) {
res.sendFile(path.join(__dirname + "/client/build", "index.html"));
});
app.listen(port, function () {
console.log("server works on port :" + port);
});
이후 cd client && yarn build를 통해 /client/build에 React build 파일이 생성합니다. app.js를 수정하고 리액트를 빌드했다면, nodemon app을 통해 express 서버를 실행시킨 후 웹브라우저에 접속해 보면 localhost:5000을 통해 리액트 빌드 파일이 보여지는 것을 확인할 수 있습니다.
매번 yarn build를 수행해야 할까?
이런 식으로 개발을 진행하게 되면 최종 결과물이 Express 서버를 통해 나타나는 장점이 있습니다. 그런데 이렇게 되면 React 개발을 하고 변동사항이 있을 때 마다 yarn build를 해서 빌드한 후에나 React 변경사항을 확인할 수 있습니다. 이 과정이 번거롭고 괜히 시간을 많이 잡아먹기 때문에, concurrently를 통해 Webpack서버와 Express 서버를 동시에 실행시키고, http-proxy-middleware를 통해 두 서버에 프록시를 구성하겠습니다. 결과적으로 개발 단계에서 두 서버가 따로 작동하도록 개발함에도 배포단계와 최대한 비슷한 느낌을 가져올 수 있습니다.
Concurrently & http-proxy-middleware 설치하기
npm i concurrently | /에 concurrently를 설치하세요.
cd client && yarn add http-proxy-middleware | http-proxy-middleware를 설치하세요. npm i 대신 yarn add 를 써도 됩니다. npm 과 yarn은 Play스토어와 Galaxy Store 정도의 관계라 보시면 되겠습니다.
Concurrently
concurrently는 한 개의 터미널에서 두 개의 서버 작동이 가능하도록 해 줍니다. concurrently를 설치했으니 이제 /package.json을 수정해보겠습니다. package.json에는 프로젝트의 이름, 의존성 등이 저장되어 있는 문서입니다. 다음의 내용을 package.json의 scripts 섹션에 다음의 내용을 추가하세요.
"scripts": {
"test": "nodemon app",
"dev": "concurrently \"npm run dev:server\" \"npm run dev:client\"",
"dev:server": "nodemon app",
"dev:client": "cd client && yarn start"
},
이후 터미널에 npm run dev를 실행시키시면 두 서버가 동시에 실행될 수 있는 것을 확인할 수 있습니다.
http-proxy-middleware
http-proxy-middleware는 localhost:3000과 localhost:5000 사이에 프록시를 구성하여 따로 놀고 있는 두 서버가 마치 하나의 서버인 것처럼 작동하게 만들어줍니다. 대부분의 경우 잘 작동하지만 뭔가 하나만 잘못되도 오류 찾느라 상당히 귀찮아지니 글을 잘 따라오세요.
const { createProxyMiddleware } = require("http-proxy-middleware");
module.exports = function (app) {
app.use(
createProxyMiddleware("/api/", {
target: "http://localhost:5000",
changeOrigin: true,
})
);
};
/client/src/setupProxy.js 파일 생성 후 위의 내용을 붙여넣으세요. 이렇게 되면 http-proxy-middleware가 setupProxy.js를 인식합니다.
이제 localhost:3000/api 이하의 경로로 시작되는 요청이 http://localhost:5000/api 에서 처리됩니다.
Done!
npm run dev를 실행해보세요.
다음과 같이 proxy created... 관련 내용과 content not from webpack is not served from ... 문구가 뜬다면 이번 포스팅의 내용을 잘 따라하신 겁니다.
이제 리액트 앱을 기존처럼 localhost:3000으로 접속할 수 있으며, Express 서버 역시 localhost:5000으로 접속할 수 있습니다.
이번 포스팅에서 개선된 점은 다음과 같습니다.
1. 프론트엔드<-> 백엔드 데이터 통신을 간결하게 할 수 있다 | 왜 이렇게 했는지 이후에 설명드리겠습니다. 일단은 간결해졌다는 데 집중하세요. 2. 리액트를 빌드만 하면 Express 서버만 실행시키고도 리액트 앱을 사용할 수 있다. | 추후 배포에 용이하게 되었습니다. |
긴 글 읽어주셔서 감사합니다. 도움이 되셨다면 공감+ 광고 클릭 부탁드립니다. 고마움을 표현하는 가장 쉬운 방법입니다.
궁금하신 점이 있다면 댓글 남겨주세요. 최대한 빨리 답변드리겠습니다.