React에 Express 연동하는 방법

mhlog·2023년 4월 11일
1

React

목록 보기
2/10
post-thumbnail

Intro

React로 사이드 프로젝트를 진행하려는 와중에 servernode+express를 사용하려고 한다. 좋은 포스팅들이 많았지만 왜 이런식으로 구현해야하는지 이해가 잘 되지 않아서 찾아보면서 내가 이해한 방법으로 포스팅하려고 한다.

서버와 React의 존재 이유

서버란?

  • 서버는 클라이언트에게 여러 가지 서비스를 제공하는 것을 뜻한다.
  • 평소에 우리는 웹 브라우저를 사용해 웹 사이트에 액세스하고 있을 것이다. 이때 웹 브라우저가 '클라이언트'이며, 웹 사이트의 콘텐츠가 있는 컴퓨터가 '서버'이다.
  • 그렇다면, 웹서버는 유저가 웹 문서를 요청하면 웹 문서를 보내주는 프로그램을 웹서버라고 한다.

React의 존재 이유

  • ReactHTML을 예쁘게 만들어주는 툴입니다.
  • 앱처럼 부드럽게 동작하는 SPA(Single Page Application)을 만들 때 사용합니다.

React는 yarn run build라는 명령어를 사용하면 하나의 HTML 파일을 만들어준다.
따라서, 어떤 서버를 사용하건 간에 유저가 메인 페이지로 접속하면 React로 만든 HTML 파일을 보내주면 연동이 끝입니다.

server와 client를 설치

server 설치 (node + express)

// 프로젝트 폴더에 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

client 설치 (CRA)

// 프로젝트 폴더로 이동해서 React 설치
yarn create react-app client --template typescript

설치가 완료 되었으면 다음과 같은 폴더 구조가 됩니다.

React에 Express 연동

리액트로 개발을 다 마친 후 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로 이동하면 에러가 발생합니다.

궁금했던 점 😒

build 작업

server에서 build 된 html 파일을 보여주기 때문에 리액트 프로젝트 코드 수정할 때마다 build 작업을 해야될까? 그럴 필요는 없다. 나중에 사이트를 aws, heroku 등에 배포할 때 한 번만 해주면 된다. 평소에 개발할 때는 리액트도 localhost로 미리보기 띄워놓고, 서버도 localhost로 미리보기 띄워놓고 개발 진행하면 별 문제 없다.

리액트와 서버를 동시에 띄우려면 어떻게 해야될까?

concurrently

// 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란에 아무거나 입력하면 리액트 프로젝트를 보내줘 라우팅하는 방식이다. 가장 하단에 놓아야 잘 동작합니다.

React에서 DB 데이터 보여주고 싶으면?

리액트는 보통 client-side-rendering을 합니다. 그래서 DB에 있는 상품목록을 가져와서 리액트에서 보여주고 싶으면 다음과 같은 방식으로 구현한다.

  1. 서버는 누군가 /product로 GET 요청을 하면 DB에서 데이터를 꺼내서 보여주라고 API를 설계해놓는다.
  2. 리액트는 상품목록을 보여주고 싶을 땐 서버 /product 주소로 GET 요청을 날리면 된다.
  3. 받아와진 데이터를 가지고 html에 넣는 방식으로 개발한다.

리액트에서 서버와의 통신은 거의 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

0개의 댓글