create-react-app, typescript, emotion으로 React 프로젝트 시작하기

김은진·2021년 7월 12일
18
post-thumbnail

혼자하는 작은 프로젝트지만 처음부터 구성하는건 오랜만이라 하는 김에 과정을 정리해보았다.

CRA와 typescript를 사용할거고, 스타일링은 emotion으로, 코딩 컨벤션을 위해 ESLint와 Prettier를 사용 할 예정이다.

1. create-react-app으로 프로젝트 생성

일단 아래 명령어 중 하나를 사용해서 프로젝트를 생성해준다.

이렇게 생성하면 지금 시점에서는 4 버전 이상이 설치될 것이다.

# npx
npx create-react-app [프로젝트 이름] --template typescript

# yarn
yarn create react-app [프로젝트 이름] --template typescript

2. emotion 추가

아래 명령어 중 하나를 통해 프로젝트에 emotion을 추가해주자.

# npx
npm i @emotion/react

# yarn
yarn add @emotion/react

그리고 매번 파일 상단에 /** @jsx jsx */ pragma를 쓰기 귀찮으니까 typescript 컴파일 옵션에 "jsxImportSource": "@emotion/react"를 추가해준다.

// tsconfig.json

{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "baseUrl": "./src",
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "jsxImportSource": "@emotion/react" // 이거 추가
  },
  "include": ["src"]
}

근데 사실 이렇게 해도 create-react-app 4버전 이상에서는 아래와 같은 오류가 난다. 🤦🏻

You have tried to stringify object returned from css function. It isn't supposed to be used directly (e.g. as value of the className prop), but rather handed to emotion so it can handle it (e.g. as value of css prop).

그래서 이모션을 사용하려는 파일 최상단에 /** @jsx jsx */를 쓰면 또 오류가 난다. 🤷🏻

pragma and pragmaFrag cannot be set when runtime is automatic.

그러면 이렇게 수정해주자. 일단 오류는 사라진다.

/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react'

const Sample = () => {
  return (
    <div css={css`color: dodgerblue`}>sample</div>
  )
}

타입스크립트 컴파일러 옵션에 "jsxImportSource": "@emotion/react"를 추가했는데도 왜 매번 /** @jsxImportSource @emotion/react */ pragma를 파일 상단에 추가하지 않으면 오류가 날까?

현재 설치된 CRA가 사용하고 있는 react-scripts(내가 사용하고 있는 버전은 4.0.3)가 TS의 jsxImportSource 옵션을 무시하고 있기 때문이다. (자세한 내용은 이 이슈를 참고하면 된다.)

아무튼 이 이슈가 수정되기 전까지는 귀찮지만 매번 pragma를 추가해주거나 직접 babel 설정을 수정해주어야 한다.

3. react-app-rewired를 통해 Babel 설정 수정

나같은 경우에는 그래도 매번 파일에 pragma를 추가하는 것 보다는 babel 설정을 한 번 수정하는게 덜 귀찮을 것 같아서 수정을 했다.

babel 설정을 수정하려면 Webpack을 통해 babel이 트랜스파일 되고 있으므로 Webpack 설정을 수정해야 한다. 하지만 eject는 다시 되돌릴 수 없으므로 다른 패키지의 도움을 받아서 수정했다. (하지만 이 방법도 CRA의 안정성은 완벽하게 보장해주지 못한다고 한다. 그래도 eject 보다는 낫겠지...)

다음 명령어를 통해 react-app-rewiredcustomize-cra를 설치하자.

# npx
npm i react-app-rewired customize-cra

# yarn
yarn add react-app-rewired customize-cra

원래는 craco를 사용했었는데 위 조합이 더 많이 쓰이는 것 같다. (이 링크 참고)

babel 설정을 위해 아래 패키지도 추가하자.

# npx
npm i @emotion/babel-plugin-jsx-pragmatic @babel/plugin-transform-react-jsx

# yarn
yarn add @emotion/babel-plugin-jsx-pragmatic @babel/plugin-transform-react-jsx

프로젝트 최상단 루트에 아래 설정파일 2개를 생성해주자.

// config-overrides.js

const {
  useBabelRc,
  removeModuleScopePlugin,
  override,
} = require('customize-cra')

module.exports = override(useBabelRc(), removeModuleScopePlugin())
// .babelrc

{
  "plugins": [
    [
      "@emotion/babel-plugin-jsx-pragmatic",
      {
        "export": "jsx",
        "import": "__to_avoid_prepending_/** @jsxImportSource @emotion/react */",
        "module": "@emotion/react"
      }
    ],
    [
      "@babel/plugin-transform-react-jsx",
      {
        "pragma": "__to_avoid_prepending_/** @jsxImportSource @emotion/react */"
      }
    ]
  ]
}

@emotion/babel-plugin-jsx-pragmaticimport@babel/plugin-transform-react-jsxpragma는 동일해야 한다. 같으면 어떤 내용이 들어가든 상관 없다. 위 두개 플러그인을 사용해서 pragma 없이도 emotion을 사용한 코드가 jsx 문법으로 무사히 변환된다.

그리고 마지막으로 package.json의 스크립트도 react-app-rewired를 사용하도록 아래와 같이 수정해주자.

"scripts": {
  "start": "react-app-rewired start",
  "build": "react-app-rewired build",
  "test": "react-app-rewired test",
},

그럼 이제 아래처럼 pragma 없이 써도 오류 안나고 잘 된다. 😆

import { css } from '@emotion/react'

const Sample = () => {
  return (
    <div css={css`color: dodgerblue`}>sample</div>
  )
}

4. ESLint, Prettier 설정

혼자하는 작은 프로젝트지만 그래도 ESLint, Prettier를 추가해줬다. 어이없는 실수로 시간 낭비 하기는 싫어서.

일단 ESLint와 Prettier 패키지를 추가하자. VS Code에 관련 익스텐션이 없다면 그것도 추가하자.

# npx
npm i eslint prettier

# yarn
yarn add eslint prettier

필요한 설정과 플러그인을 추가한다.

# npx
npm i eslint-config-prettier eslint-config-react-app @typescript-eslint/parser @emotion/eslint-plugin

# yarn
yarn add eslint-config-prettier eslint-config-react-app @typescript-eslint/parser @emotion/eslint-plugin
  • eslint-config-prettier: prettier 설정이랑 충돌나는 것 방지
  • eslint-config-react-app: React 관련 오류 잡아줌
  • @typescript-eslint/parser: typescript 관련 오류 잡아줌
  • @emotion/eslint-plugin: emotion 관련 오류 잡아줌

그리고 프로젝트 루트에 설정파일 두개를 추가하면 된다.

// .eslintrc.json

{
  "env": {
    "es2020": true,
    "node": true
  },
  "extends": ["react-app", "prettier"],
  "plugins": ["@emotion"],
  "parserOptions": {
    "ecmaVersion": 2020
  },
}
// .prettierrc

{
  "singleQuote": true,
  "semi": false,
  "useTabs": false,
  "tabWidth": 2,
  "trailingComma": "all",
  "printWidth": 80,
  "arrowParens": "always",
  "orderedImports": true,
  "bracketSpacing": true,
  "jsxBracketSameLine": false
}

필요한게 있다면 추가하거나 수정해서 쓰면 된다.

휴, 그럼 이제 일을 시작할 수 있다. 🔥

profile
검은 콩 세 개가 세상을 구한다🐾

4개의 댓글

comment-user-thumbnail
2021년 10월 5일

@babel/plugin-transform-react-jsx를 설치하는내용이 빠진것같아요!

1개의 답글
comment-user-thumbnail
2022년 7월 7일

감사합니다. 덕분에 잘 해결되었습니다 😁

답글 달기
comment-user-thumbnail
2023년 10월 18일

config-overrides.js에서 useBabelRc()에 빨간줄 에러가 뜨면서 최상단에서 호출할 수 없다는 에러가 뜨는데, 이 에러는 어떻게 할 수 없는건가요?? 에러가 뜨긴하지만 실행은 정상적으로 됩니다..

답글 달기