본문 바로가기
IT/React

[React] 서버리스 메모앱-1

by 밤톨엽 2022. 4. 17.

해당 글은 [AWS] 서버리스 스택-4와 이어집니다.

이번 글에서는 리액트 프론트엔드 구성 대해서 작성을 하였습니다.


우리는 React.js를 사용하여 SPA 웹 애플리케이션을 생성할 계획이다. Create React App 프로젝트를 사용하여 기초적인 설정이 되어있는 상태에서 진행한다.

Create React App은 React팀이 공식적으로 지원하며, React.js 프로젝트의 모든 의존성을 편리하게 미리 패키징 해준다.


터미널에서 프로젝트의 최상위 경로에서 아래 명령어를 실행하여 Create React App(CRA) 프로젝트를 생성해주자.

npx create-react-app frontend --scripts-version 4.0.3 --template typescript --use npm
cd frontend
Javascript 로 리액트 구성을 진행할 수 있지만 백엔드에서 이미 Typescript 언어로 구성을 진행했기 때문에 리엑트 관련 구성도 Typescript 로 진행해보자.

React 18 -> 17 다운그레이드

글을 작성하는 시점에 Create React App 프로젝트에서 React 18 버전으로 적용되서 현재 프로젝트 진행 시 문제가 되는 점이 있다.

17버전으로 낮추는 작업을 진행하자.

frontend/package.json 파일에서 아래 패키지들의 버전을 변경해주자.

"dependencies": {
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-scripts": "4.0.3",
    "@testing-library/jest-dom": "^5.16.4",
    "@testing-library/react": "^12.1.5",
    "@testing-library/user-event": "^13.5.0",
    "@types/jest": "^27.4.1",
    "@types/node": "^14.14.31",
    "@types/react": "^17.0.2",
    "@types/react-dom": "^17.0.2",
 },

그리고 frontend/node_modules 폴더를 삭제 후 터미널에서 아래 명령어로 패키지를 재설치하자.
(터미널에서 frontend/ 경로에서 진행해야 한다.)

npn run install

frontend/.env 파일을 추가 후 아래 내용을 구성해주자.

SKIP_PREFLIGHT_CHECK=true

마지막으로 src/index.tsx에 있는 코드를 아래처럼 변경해주면 다운그레이드 완료.

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

ReactDOM.render(
  <React.StrictMode>
  	<App />
  </React.StrictMode>,
  document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

SST 환경 변수 로드

또한 우리가 서버리스 스택 백엔드에서 사용 중인 주요한 값들을 환경 변수로 로드해야 한다.
이를 위해 @serverless-stack/static-site-env 패키지 사용해보자.
(SST 앱에서 환경 변수를 찾아 React 개발 환경을 시작하는 동안 로드를 도와주는 패키지)

터미널에서 cd frontend 명령어로 경로가 frontend/ 에서 시작하는지 반드시 확인하고 아래 명령어를 실행해주자.

 

npm install @serverless-stack/static-site-env --save-dev

frontend/package.json 경로에 있는 파일에서 scripts 명령어 중 start 명령어를 아래처럼 변경해주자.

"start": "sst-env -- react-scripts start",

SST에 React 앱 추가

React 앱을 AWS에 배포할 예정이다. 여기에서 우리는 SST ReactStaticSite 구조를 활용한다.

stacks/FrontendStack.ts 경로로 파일을 생성하고 아래 코드를 추가하자.

import * as sst from "@serverless-stack/resources";

export default class FrontendStack extends sst.Stack {
  constructor(scope: sst.App, id: string, props?: any) {
    super(scope, id, props);

    const { api, auth, bucket } = props;

    // React App 정의
    const site = new sst.ReactStaticSite(this, "ReactSite", {
      path: "frontend",
      // 환경변수 값 전달(주요 key값들)
      environment: {
        REACT_APP_API_URL: api.url,
        REACT_APP_REGION: scope.region,
        REACT_APP_BUCKET: bucket.bucketName,
        REACT_APP_USER_POOL_ID: auth.cognitoUserPool.userPoolId,
        REACT_APP_IDENTITY_POOL_ID: auth.cognitoCfnIdentityPool.ref,
        REACT_APP_USER_POOL_CLIENT_ID:
          auth.cognitoUserPoolClient.userPoolClientId,
      },
    });

    // 사이트 주소 노출
    this.addOutputs({
      SiteUrl: site.url,
    });
  }
}

위에 코드를 살펴보자

  1. React 앱이 서버리스 스택의 ReactStaticSite에서 frontend/ 디렉터리를 경로 구조를 가리키도록 설정한다.
  2. 다른 스택의 출력을 React의 환경 변수로 전달한다.즉, React 앱에서 관련 키값을 위해 하드 코딩할 필요가 없다.
    (
    이에 대한 자세한 내용은 React 앱에서 서버리스 환경 변수 설정 챕터에서 확인할 수 있다.)
  3. 마지막으로 React 앱의 URL을 출력한다.

stack/index.ts 경로에 있는 파일을 아래처럼 수정해주자.

import * as sst from '@serverless-stack/resources';
import StorageStack from './StorageStack';
import ApiStack from './ApiStack';
import AuthStack from './AuthStack';
import FrontendStack from "./FrontendStack";

export default function main(app: sst.App): void {
  // 두번째 인자에 본인 이름이나 이니셜로 생성해주자
  // ex) storage-sykim
  const storageStack = new StorageStack(app, 'storage-sykim');

  // 두번째 인자에 본인 이름이나 이니셜로 생성해주자
  // ex) api-sykim
  const apiStack = new ApiStack(app, 'api-sykim', {
    table: storageStack.table,
  });

  // 두번째 인자에 본인 이름이나 이니셜로 생성해주자
  // ex) auth-sykim
  const authStack = new AuthStack(app, 'auth-sykim', {
    api: apiStack.api,
    bucket: storageStack.bucket,
  });

  // React 관련 스택 추가
  new FrontendStack(app, "frontend", {
    api: apiStack.api,
    auth: authStack.auth,
    bucket: storageStack.bucket,
  });
}

이제 완성된 리소스를 npx sst start --stage stage 명령어를 통해 배포하자.

터미널에서 frontend/ 경로가 아닌 프로젝트 루트 경로에서 명령어를 진행해야 한다.
Stack dev-notes-frontend
  Status: deployed
  Outputs:
    SiteUrl: https://d3j4c16hczgtjw.cloudfront.net
  ReactSite:
    REACT_APP_API_URL: https://5bv7x0iuga.execute-api.us-east-1.amazonaws.com
    REACT_APP_BUCKET: dev-notes-storage-uploadsbucketc4b27cc7-xmqzx69e5bpt
    REACT_APP_IDENTITY_POOL_ID: us-east-1:2d7b425d-eb44-4c42-afbd-645018b37a27
    REACT_APP_REGION: us-east-1
    REACT_APP_USER_POOL_CLIENT_ID: jbf2qe4h17tl2u94fntkjii7n
    REACT_APP_USER_POOL_ID: us-east-1_gll8EbWrr

배포된 후 리소스는 위와 비슷한 모양으로 나와야 한다.

React App 시작

이제 React앱을 구성하는 동안은 터미널 명령어 경로나 기본 루트 경로가 frontend/ 경로로 시작한다.

터미널에서 항상 frontend/ 경로로 시작하도록 설정해두자

우선 public/index.html 경로에 있는 <title> 태그를 아래처럼 수정하자.

<title>Scratch - 심플한 메모 앱</title>

아래 명령어를 터미널에서 실행시켜 React App을 실행시키자

npm run start

React App
React App

Create React App에는 매우 편리하면서 최소한의 개발 환경이 미리 구축되어있다. 여기에는 라이브 리로드, 테스트 프레임워크, ES6 지원 등이 포함된다.

Favicon 추가

Create React App은 앱에 대한 간단한 favicon을 생성하여 앱에 배치해준다. public/favicon.ico
하지만, favicon이 모든 브라우저와 모바일 플랫폼에서 작동하기 위해서 추가적인 작업이 필요하다.

오른쪽 링크로 이동하여 해당 이미지를 다운로드한다. — https://serverless-stack.com/assets/scratch-icon.png

아이콘을 여러 플랫폼에서 잘 나오게 하기 위해 Favicon Generator(링크 클릭) 서비스를 사용한다.

realfavicongenerator
realfavicongenerator

Select your Favicon picture를 클릭하여아이콘을 업로드하자.


realfavicongenerator-generate
realfavicongenerator-generate

아이콘을 업로드하면 다양한 플랫폼의 아이콘의 미리보기가 표시된다. 페이지를 맨 아래로 스크롤하여Generate your Favicons and HTML code 버튼을 클릭하자.


realfavicongenerator-completed
realfavicongenerator-completed

Favicon Package 버튼을 클릭하여 생성된 파비콘을 다운로드해서 모든 파일을 public/ 디렉토리에 복사한다.
(기존에 있던 public/logo192.png, public/logo512.png 파일은 삭제한다.)


public/manifest.json 경로에 있는 파일을 아래처럼 수정해주자.

{
  "short_name": "Scratch",
  "name": "Scratch 메모 앱",
  "icons": [
    {
      "src": "android-chrome-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "android-chrome-256x256.png",
      "sizes": "256x256",
      "type": "image/png"
    }
  ],
  "start_url": ".",
  "display": "standalone",
  "theme_color": "#ffffff",
  "background_color": "#ffffff"
}

public/index.html 파일에서 아래 리소스들을 추가해주자.

<link
  rel="apple-touch-icon"
  sizes="180x180"
  href="%PUBLIC_URL%/apple-touch-icon.png"
/>
<link
  rel="icon"
  type="image/png"
  href="%PUBLIC_URL%/favicon-32x32.png"
  sizes="32x32"
/>
<link
  rel="icon"
  type="image/png"
  href="%PUBLIC_URL%/favicon-16x16.png"
  sizes="16x16"
/>
<link
  rel="mask-icon"
  href="%PUBLIC_URL%/safari-pinned-tab.svg"
  color="#5bbad5"
/>
<meta name="description" content="심플한 메모 앱" />
<meta name="theme-color" content="#ffffff" />

기존에 있던 아래 태그들은 삭제해주자.

<meta name="theme-color" content="#000000">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<link rel="apple-touch-icon" href="logo192.png" />
<meta
  name="description"
  content="Web site created using create-react-app"
/>

마지막으로 리액트 앱이 실행 중인 실제 브라우저에서 /favicon-32x32.png 이미지가 잘 보이나 확인해보자.

잘보이네요
잘보이네요

글꼴 설정

Google Fonts를 사용하여 전체적인 앱 글꼴을 설정하자.

프로젝트에서 Serif( PT Serif )와 Sans-Serif( Open Sans ) 서체의 조합을 사용하도록 하겠다. 해당 폰트는 Google Fonts를 통해 제공되어 링크를 통해 바로 사용할 수 있다.

public/index.html 파일에서 <head> 태그 안에 아래의 폰트 링크를 추가해주자.

<link
  rel="stylesheet"
  type="text/css"
  href="https://fonts.googleapis.com/css?family=PT+Serif|Open+Sans:300,400,600,700,800"
/>

스타일에 글꼴 추가

이제 새로 추가된 글꼴을 전체 스타일시트에 추가하기 위해 src/index.css 파일을 아래처럼 수정하자.
(Create React App은 각 컴포넌트의 구성 요소마다 스타일을 분리해서 사용하는 것도 가능하다.)

body {
  margin: 0;
  padding: 0;
  color: #333;
  font-size: 16px;
  -moz-osx-font-smoothing: grayscale;
  -webkit-font-smoothing: antialiased;
  font-family: "Open Sans", sans-serif;
}

h1, h2, h3, h4, h5, h6 {
  font-family: "PT Serif", serif;
}

custom-fonts-updated
custom-fonts-updated

부트스트랩 설정

디자인 및 UI를 모두 직접 구현할 수도 있겠지만 좀 더 완성도 있는 디자인과 시간 절약을 위해 부트스트랩을 사용할 것이며 React Bootstrap 패키지를 사용해서 UI를 구성해보도록 하자.
(또한 아이콘이 필요한 부분이 있어 React Icons 패키지도 같이 설치한다.)

터미널에서 아래 명령어를 통해 react-bootstarpreact-icon 패키지를 설치해주자.
(터미널 경로는 당연히 frontend/ 에서 실행해야 한다.)

npm install react-bootstrap@1.6.1 react-icons@4.2.0 --save

부트스트랩 스타일 추가

React Bootstrap은 표준 Bootstrap v4 스타일을 사용한다.

public/index.html 파일에서 <head> 태그 안에 아래의 스타일 관련 링크를 추가해주자.

<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css"
  integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2"
  crossorigin="anonymous"
/>

모바일 브라우저에서 포커스가 있을 때 확대되지 않도록 양식 필드의 스타일을 조정하자. 16px 확대/축소를 방지하기 위해 최소 글꼴 크기가 요구된다.

src/index.css 파일에 아래 스타일을 추가해주자.

select.form-control,
textarea.form-control,
input.form-control {
  font-size: 1rem;
}
input[type=file] {
  width: 100%;
}

브라우저를 확인해보면 스타일이 조금 변할 수 있다. 이것은 Bootstrap 에 기본적으로 Normalize.css가 포함되어 있어 브라우저 간 일관된 스타일을 유지해준다.

기본적인 React App 스타일 설정을 마치며 Github에 소스를 올려주자

[React] 서버리스 메모앱-1

  • Create React App 생성
  • 환경변수 설정
  • Favicon 설정
  • 글꼴 설정
  • 부트스트랩, 아이콘 패키지 설정

이번 문서에서는 위와 같이 React App을 생성하고 구성에 필요한 기본적인 내용을 추가해보았습니다.

다음 파트부터는 리액트 라우터에, AWS Amplify, 로그인 폼에 대해 다루게 되며 [React] 서버리스 메모앱-2 파트에서 정리하도록 하겠습니다.

'IT > React' 카테고리의 다른 글

[React] 서버리스 메모앱-5  (0) 2022.05.10
[React] 서버리스 메모앱-4  (0) 2022.05.07
[React] 서버리스 메모앱-3  (0) 2022.04.24
[React] 서버리스 메모앱-2  (3) 2022.04.18