React
로 사이드 프로젝트를 진행하려는 와중에 server로node+express
를 사용하려고 한다. 좋은 포스팅들이 많았지만 왜 이런식으로 구현해야하는지 이해가 잘 되지 않아서 찾아보면서 내가 이해한 방법으로 포스팅하려고 한다.
서버
는 클라이언트에게 여러 가지 서비스를 제공하는 것을 뜻한다.React
는 HTML
을 예쁘게 만들어주는 툴입니다.
React
는 yarn run build라는 명령어를 사용하면 하나의HTML
파일을 만들어준다.
따라서, 어떤 서버를 사용하건 간에 유저가 메인 페이지로 접속하면 React로 만든 HTML 파일을 보내주면 연동이 끝입니다.
// 프로젝트 폴더에 server 폴더 만들기
mkdir server
// terminal에 node+express에 필요한 패키지 설치
cd server
yarn init -y
yarn add express
// server 폴더로 이동하서 server.js 파일 생성
// server.js
const express = require('express');
const path = require('path');
const app = express();
app.listen(8080, function () {
console.log('listening on 8080')
});
// 미리보기 띄우기
nodemon server.js
// 프로젝트 폴더로 이동해서 React 설치
yarn create react-app client --template typescript
설치가 완료 되었으면 다음과 같은 폴더 구조가 됩니다.
리액트로 개발을 다 마친 후 yarn run build
를 하면 build라는 폴더가 생기고 안에 html css js파일이 생성됩니다. React는 SPA이기 때문에 기본적으로 html 파일이 하나만 있습니다. 따라서 server.js 파일에 유저가 메인페이지로 접속하면 React로 build한 index.html 파일을 보내주기만 하면 React와 Express 연동 끝입니다.
// server.js
const express = require('express');
const app = express();
const path = require('path');
app.listen(8080, function() {
console.log('listening on 8080');
})
app.use(express.static(path.join(__dirname, '../client/build')));
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname, '../client/build/index.html'));
})
express.static을 쓰면 특정 폴더 안의 파일들을 static 파일로 유저에게 잘 보내줄 수 있습니다. 이제 localhost:8080 으로 접속하면 리액트 프로젝트가 나옵니다. 끄읏!
그런데 리액트는 SPA라 리액트 상에서 라우팅을 담당하는 경우가 대부분입니다. 근데 react에서 /test라는 route를 생성하고 localhost:8080/test로 이동하면 에러가 발생합니다.
server에서 build 된 html 파일을 보여주기 때문에 리액트 프로젝트 코드 수정할 때마다 build 작업을 해야될까? 그럴 필요는 없다. 나중에 사이트를 aws, heroku 등에 배포할 때 한 번만 해주면 된다. 평소에 개발할 때는 리액트도 localhost로 미리보기 띄워놓고, 서버도 localhost로 미리보기 띄워놓고 개발 진행하면 별 문제 없다.
리액트와 서버를 동시에 띄우려면 어떻게 해야될까?
// root 디렉토리(프로젝트)로 이동해서 터미널에 설치
yarn add global concurrently
// root 디렉토리에 package.json
{
"scripts": {
"server": "cd server && nodemon server",
"client": "cd client && npm start",
"start": "concurrently --kill-others-on-fail \"npm run server\" \"npm run client\""
},
"devDependencies": {
"nodemon": "^2.0.7"
},
"dependencies": {
"concurrently": "^8.0.1"
}
}
스크립트 부분만 변경해주면 된다.
리액트는 SPA라 리액트 상에서 라우팅을 담당하는 경우가 대부분입니다. 근데 react에서 /test라는 route를 생성하고 localhost:8080/test로 이동하면 에러가 발생합니다. 왜냐하면 브라우저 URL 창에 입력하는건 서버에게 요청하는 것이지 리액트 라우터에게 요청하는 것이 아니기 때문입니다. 따라서 리액트가 라우팅하게 권한을 넘기고 싶으면 server.js에 다음과 같은 코드를 작성하면 됩니다.
// 최하단에 위치 (server.js)
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname, '../client/build/index.html'));
})
유저가 URL란에 아무거나 입력하면 리액트 프로젝트를 보내줘 라우팅하는 방식이다. 가장 하단에 놓아야 잘 동작합니다.
리액트는 보통 client-side-rendering을 합니다. 그래서 DB에 있는 상품목록을 가져와서 리액트에서 보여주고 싶으면 다음과 같은 방식으로 구현한다.
리액트에서 서버와의 통신은 거의 ajax
로 진행한다. POST 요청, 로그인해서 세션만들기 이런것도 보통 ajax
쓴다.
yarn add cors
쓰기 전에 cors
패키지 설치, cors
는 다른 도메인주소끼리 ajax 요청 주고 받을 때 필요하다.
// server.js
// 상단에 있어야함.
app.use(express.json());
var cors = require('cors');
app.use(cors());
app.get('/product', (req, res) => {
// DB에서 받아와서 이런식으로 함
res.json({name: 'black shoes'});
})
react와 node 서버 간에 데이터를 주고 받기 위해서는 프록시 모듈이 필요하다. 프록시 모듈의 사용법에 대해서는 추가적인 포스팅으로 다루어 보도록 하겠다. 이제 react + express 연동도 했으니 DB쪽으로 연결만 한 뒤 사이드 프로젝트에 들어가기만 하면 되겠다..! 😊
https://create-react-app.dev/docs/proxying-api-requests-in-development/
https://velog.io/@autumndr3ams/210802-React-Node.jsexpress-%EC%97%B0%EA%B2%B0%ED%95%98%EA%B8%B0#nodejs-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%95
https://blog.naver.com/sejun3278/221569640649