React + Express >> Heroku 배포하기

Kyungs·2022년 2월 1일
0

React

목록 보기
5/8
post-custom-banner


React를 연동한 프로젝트를 진행하며 서비스를 배포하기로 결정하여 어떻게 배포할 지 고민하였다. 간편하게 배포만 하는 것이 목표였기 때문에 처음에는 Github Pages를 이용하여 배포했다. 그런데 React 프로젝트 내에서 사용하는 공공데이터포털의 Open API가 http 프로토콜밖에 제공하지 않았고, Github Pageshttps를 enforce하기 때문에 Mixed Content 오류가 나와 데이터를 가져오지 못하는 이슈가 생겼다.

Mixed Content

일반적으로 브라우저는 HTTPS로 접속한 사이트에서 HTTP 통신을 통해 가져온 데이터를 사용하는 것을 허용하지 않는다. SSL이 적용되지 않아 보안상 안전하지 않기 때문이다. 이 문제를 해결하기 위해 가비아 등의 사이트에서 도메인을 구입하여 Github Pages에 custom domain을 적용하여 https를 해제할 수도 있지만, client 단에서 HTTPS를 적용하여 배포를 하고싶었다.

결론적으로 Node.js + Express 서버를 생성하여 문제 해결을 시도했다. React에서는 Heroku에서 배포한 HTTPS 프로토콜을 통해 서버로 fetch 요청을 하여 Mixed Content 이슈를 해결하고, 서버에서는 HTTP 통신을 통해 공공데이터포털에 데이터를 요청 및 가져온 후 client에 데이터를 보내주는 방식인 것이다. Heroku에는 React 프로젝트를 빌드 및 배포하여 Express가 빌드된 index.html 파일을 제공하도록 했다.

이 포스트를 읽으시는 분들께: 아래 예시 및 내용들이 정확하지 않을 수 있고, 보다 더 간편하고 효율적인 방법이 있을 수 있습니다. 오류가 있을 시 지적해주시면 감사드리겠습니다.

Express 코드 예시

import express from 'express';
import cors from 'cors';
import path from 'path';
// ... body-parser, router 등 필요한 모듈 import

const PORT = process.env.PORT || 5000;
const corsOptions = {
  // origin, credentials 등 필요한 경우 cors 옵션을 등록할 수 있다.
};

app.use(cors(corsOptions));
app.use(express.static(path.join(__dirname, '../build')));
app.get('/*', (req, res) => {
  res.sendFile(paht.join(__dirname, '../build/index.html'));
});
app.listen(PORT, () => console.log(`listening on port ${PORT}`));

다른 출처에서 데이터나 파일을 요청하는게 아닌 이상 cors 등록이 필요하지 않다. path를 위와 같이 지정하여 빌드된 React 프로젝트를 제공하도록 할 수 있다. 또한, Heroku 서버의 환경 변수에 의해 정해지는 포트 번호를 할당하기 위해 Node의 환경 변수 값을 담고 있는 process.env를 이용하여 포트 번호를 지정할 수 있다.

Express에서 공공데이터포털의 데이터는 axios, xhr2 등의 라이브러리를 사용하면 간편하게 요청할 수 있다.

React 데이터 요청 예시

아래는 React 컴포넌트에서 fetch()를 이용하여 Express에 데이터를 요청하는 예시이다. Express/data/person 이라는 라우팅이 지정되어 있다고 가정했다.

import { useEffect } from 'react';

const App = () => {
  const FETCH_PATH = 'data/person';
  
  const getData = async () => {
    try {
      const data = await (await fetch(FETCH_PATH)).json();
      // data에 대한 처리 로직
    } catch (error) {
      console.log(error);
      // 에러 처리 코드 추가
    };
  };
  
  useEffect(() => {
    getData();
  }, []);
};

Heroku 배포

로컬 환경에서 프로젝트를 배포하려 한다면 프로젝트를 빌드한 후에 Heroku에 푸시하여 배포를 진행할 수 있다. 먼저 Heroku에 가입하고, 터미널에서 로그인 및 헤로쿠 프로젝트를 생성한다.

heroku login
heroku create 프로젝트이름

root 단에 있는 package.json 파일 내 "scripts" 코드에 아래와 같이 추가하면 배포 준비가 완료된다.

  "scripts": {
    "start": "npm run dev:server",
    "build": "react-scripts build",
    "heroku-postbuild": "cd server && npm install",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "dev:server": "ts-node server/index.ts",
    "dev:client": "react-scripts start"
  },

기존 헤로쿠 서버에서는 Procfile이라는 파일을 생성하여 명령어를 입력해주어야 서버가 실행되었지만, 최근에는 Procfile이라는 파일이 없으면 npm start 명령으로 자동 실행된다.
참고: Procfile no longer required for Node.js apps

dev:serverdev:client는 로컬 개발 환경에서 사용하고자 나눈 것이며, 실제 헤로쿠 서버에서는 dev:client 명령을 사용할 일은 없다. Express가 빌드 파일을 제공하기 때문에 npm run dev:server 명령만 주어 서버만 실행시키면 된다.

server 폴더 내에 Express를 구성하였기 때문에 ts-node server/index.ts를 실행시켰다. 또한, heroku-postbuild 명령을 통해 server 폴더 내에 있는 npm 패키지들도 설치하도록 했다.

배포하기 전에 먼저 터미널에 npm run build를 입력하여 프로젝트를 빌드한다. 그런 다음, github 레포지토리에 올리듯이 헤로쿠 프로젝트에 푸시한다.

git add .
git commit -m '커밋 메시지'
git push heroku main

푸시를 하면 배포 진행 상황을 알려주며, 헤로쿠 서버 내 로그는 아래 명령으로 확인할 수 있다.

heroku logs --tail

참고 자료

Heroku Dev Center
[HTTP] HTTPS 사용시 혼합 콘텐츠(Mixed Content) 및 안전하지 않은 콘텐츠에 대한 설명
Node.js 사이트 Heroku(헤로쿠)로 인터넷에 올리기

post-custom-banner

0개의 댓글