리액트 + 노드Js Express 연동 템플릿 만들기

woojin·2021년 4월 28일
2
post-thumbnail

리액트와 노트Js로 웹 애플리케이션 만들기

프론트엔드 개발을 하면서 리액트를 써서 만드는 경우가 많았는데
이 경우 create-react-app을 써서 만들면 바벨과 웹팩이 세팅된 상태로 프로젝트를 만들 수 있었습니다.

그런데 백엔드 API를 만들기 위해 노드Js와 함께 개발을 할 경우 초반에 세팅해야 하는 게 몇가지 있는데 매번 세팅하는 것도 귀찮고 필요할 때마다 바로 쓰고자 템플릿으로 만들려고 합니다.


- 클라이언트 세팅

우선 터미널을 켜준 후

 npx create-react-app react-node-template
 
 ##프로젝트가 만들어지면 아래 명령어로 해당 폴더로 이동합니다.
 cd react-node-template
 
 ##폴더로 이동 후 아래 명령어를 통해 VS code로 열어줍니다.
 code .
 
 ##그리고 프로젝트 시작
 yarn start

yarn start로 프로젝트를 시작하면 localhost 3000번 포트로 프로젝트가 열립니다.

그럼 이런 화면을 볼 수 있는데 src 폴더에서 App.js로 들어가서 다 지워줍니다.

Hello World!

여기까지 완료 되었으면 이제 루트 폴더에 client 폴더를 하나 만들어줍니다.
그리고 .gitignore를 제외한 루트 폴더에 있는 모든 것을 client 폴더에 넣어주어 해당 폴더가 사용자에게 보여지는 클라이언트 부분을 담당하게 합니다.


- 서버 세팅

이제 루트 폴더에서

npm init -y

를 통하여 프로젝트를 초기화하여 package.json을 만들어줍니다.

npm init에서 -y 없이 입력하면

프로젝트 세팅에 관한 여러 질문들이 나오는데 템플릿 용도로 만드는 것이기 때문에 -y를 입력하여 전부 건너뜁니다.

완료되면 package.json이 루트 폴더에 만들어진 것을 볼 수 있습니다.

이게 초기 화면인데 몇 가지를 건드려봅시다.

우리는 서버를 server.js로 만들 것이기 때문에 "main" 부분을 "index.js" -> "server.js"로 바꿔줍니다.

그리고 "script" 부분을 보시면 기존 스크립트에서
start, backend, dev 이렇게 세 줄이 추가 되었는데

"start" -> 서버를 실행시킬 때 작동되는 것입니다.

  • 일반적으로 aws나 gcp에 deploy를 했을 때 npm start가 실행되기 때문에 이 부분이 설정이 제대로 안되어 있으면 나중에 에러가 발생할 수 있습니다.

"backend" -> 개발용으로 만들어놓은 스크립트입니다.

  • node server.js로 서버를 실행할 경우 코드를 수정할 때마다 서버를 껐다가 켜야하기 때문에 nodemon이라는 node.js라이브러리를 사용하여 서버를 실행하면 코드에서 수정사항이 있을 때 서버를 재실행하지 않아도 바로 수정사항이 적용되기 때문에 개발할 때에는 nodemon을 써주도록 합시다.

"dev" -> 클라이언트와 서버를 동시에 실행시키는 스크립트입니다.

  • concurrently라는 라이브러리를 통하여 "backend"스크립트 실행함과 동시에 cilent폴더 내부에서 npm run start를 실행시켜 클라이언트를 실행시켜줍니다.
  • 그래서 보통 개발할 때 터미널에서 yarn dev를 입력하여 서버와 클라이언트를 동시에 실행시켜 개발을 하곤 합니다.

package.json 수정이 끝났으면 이제 위에서 작성했던 라이브러리를 설치해줍니다.

yarn add nodemon
yarn add concurrently

(위 두 줄을 한번에 설치할 때는 yarn add nodemon concurrently)

이제 진짜 서버코드를 작성해봅시다!


루트 폴더에서 server.js 파일을 하나 만들어줍니다.

그리고 다시 터미널에서

yarn add express body-parser

백엔드의 프레임워크로 express를 쓰고자 express를 설치하고
서버에서 json 형식으로 데이터를 받기 위해 이것의 분석을 도와주는 express 미들웨어 body-parser 모듈을 설치합니다.

이제 server.js에서 코드를 작성합니다.

// server.js

const express = require('express'); // express 사용
const app = express();
const bodyParser = require('body-parser'); // body-parser 미들웨어 설정

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));
// parse application/json
app.use(bodyParser.json());

// 포트를 8080으로 지정
const PORT = 8080;

// 해당 포트로 서버를 실행
app.listen(PORT, () => {
  console.log(`Example app listening at http://localhost:${PORT}`);
});

이제 yarn start를 통하여 서버를 실행시켜봅시다.

터미널에 "Example app listening at http://localhost:8080" 문구가 나왔다면 서버가 정상적으로 실행된 것입니다!

서버가 실행되는 것을 확인했다면 이제 클라이언트로 보내줄 api를 작성해줍니다.

// server.js

const express = require('express');
const app = express();
const bodyParser = require('body-parser');

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

app.get('/api/load', (req, res) => {
  res.send({ name: '우진', age:99 });
});

const PORT = 8080;

app.listen(PORT, () => {
  console.log(`Example app listening at http://localhost:${PORT}`);
});

get 요청으로 '/api/load' 경로를 작성하여 클라이언트가 로드되면 해당 get요청이 보내지도록 만들 것입니다.


자 다시 클라이언트로 돌아옵니다.

App.js 파일을 열어서 코드를 작성해줍니다.

//App.js

import React, { useState, useEffect } from 'react';
import axios from 'axios';
import './App.css';

function App() {
  // get요청으로 전송받을 데이터를 담을 state
  const [loadData, setLoadData] = useState();

  // 컴포넌트가 처음 렌더링되었을 때 실행될 useEffect
  useEffect(() => {
    // axios 라이브러리를 사용하여 get요청을 받아옵니다.
    axios
      .get('/api/load')
      .then((res) => {
      	// get요청이 성공하면 콘솔에 데이터를 띄우고 스테이트를 변경
        console.log(res.data);
        setLoadData(res.data);
      })
      .catch((err) => {
      	// get요청이 실패하면 콘솔에 에러 메세지를 띄움
        console.log(err);
      });
  }, []);

  return (
    <div className='App' style={{ marginTop: '5rem' }}>
      {loadData ? (
        <div>
          안녕하세요 {loadData.name}입니다. {loadData.age}살이에요.
        </div>
      ) : null}
    </div>
  );
}

export default App;

axios는 브라우저, Node.js를 위한 Promise API를 활용하는 HTTP 비동기 통신 라이브러리입니다.

코드에 주석을 달아서 데이터를 받아오는 과정을 설명해놓았습니다.

화면에 렌더링하게 되는 return 구문에서 loadData 변수로 삼항연산자를 사용한 이유
리액트의 렌더링 과정을 쉽게 말씀드리면

리액트는 CSR(Client Side Rendering) 클라이언트 사이드 렌더링 방식을 사용하는데
처음 실행되었을 때 스크립트에 작성되어 있는 페이지를 렌더링하고
그 다음 서버로부터 요청된 데이터를 받아와 화면에 채워 다시 렌더링을 합니다.

그런데 이때 삼항연산자를 안걸고

        <div>
          안녕하세요 {loadData.name}입니다. {loadData.age}살이에요.
        </div>

해당 부분을 바로 내보내면 현재의 'loadData' state는 빈 값이기 때문에
loadData.name과 loadData.age를 받아올 수 없어 에러를 띄우게 됩니다.

그리하여

      {loadData ? (
        <div>
          안녕하세요 {loadData.name}입니다. {loadData.age}살이에요.
        </div>
      ) : null}

'loadData'의 값이 있다면 해당 코드를 보여주고 빈 값이면 null을 뱉어내게 작성하였습니다.


아 그럼 서버와 클라이언트 둘 다 작성했으니 끝이네?

네 404가 뜹니다. 개발은 뭐 하나 바로 바로 되는 게 없죠

왜 404가 뜨냐면
클라이언트는 localhost 3000번으로 실행이 되었고
서버는 localhost 8080번으로 실행이 되어있습니다.

이 두개는 엄연히 다른 서버이므로 이 두개를 연결시켜주는 proxy 설정이 필요합니다.

프록시 서버(영어: proxy server)는 클라이언트가 자신을 통해서 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해 주는 컴퓨터 시스템이나 응용 프로그램을 가리킨다. 서버와 클라이언트 사이에 중계기로서 대리로 통신을 수행하는 것을 가리켜 '프록시', 그 중계 기능을 하는 것을 프록시 서버라고 부른다. - wikipedia

그림으로 보자면 대충 이런식입니다.

우리가 만들려는 프로젝트로 예를 들어 쉽게 말하면
3000번 포트가 '아~ 8080번 포트를 타겟으로 잡고 설정해서 연결시켜줘~'라고 하는 것을 그냥 코드로 써주면 되는 것입니다.

그럼 바로 만들게요.

우선 실행 중이던 서버를 잠시 종료하고

yarn add http-proxy-middleware

바로 설치해줍니다.

client폴더 내부에 있는 src폴더 안에 setupProxy.js 라는 파일을 하나 만듭니다.

//setupProxy.js

const proxy = require('http-proxy-middleware');

module.exports = function (app) {
  app.use(
    '/api',
    proxy({
      target: 'http://localhost:8080',
      changeOrigin: true,
    })
  );
};

그냥 공식 사용법입니다. '/api' 경로 쓸거고 타켓을 8080포트로 해줘~ 라고 생각하시면 됩니다.


자 이제 프록시까지 설정 완료했으니깐 실행시켜봅시다.

루트 폴더로 돌아와서 터미널에서 yarn dev를 입력해줍니다.

그럼 서버가 실행됨과 동시에 Proxy created라고 나오면서 프록시가 연결되는 것을 볼 수 있습니다.

localhost 3000번으로 와서 보시면

콘솔창에 데이터가 제대로 출력이 됐고
화면상에도 원하는 데이터가 들어가 렌더링이 잘 된 것을 볼 수 있습니다.

이제 이 템플릿을 토대로 하여

클라이언트 환경을 넓혀가거나 서버에서 API를 추가로 작성하여 활요하시면 됩니다!

완성된 템플릿은 깃허브에도 같이 올려두겠습니다!

download zip으로 받으신 후 루트 폴더와 클라이언트 폴더에서
yarn install 혹은 npm install 하여 node_modules 받으시면 됩니다!

리액트와 노드Js Express 연동 템플릿입니다. ✨ 깃허브 레파지토리
https://github.com/woojin624/react-node-template

profile
개발자를 위한 개발을 하고 싶은

0개의 댓글