๊ธ€ ์ž‘์„ฑ์ž: ํƒ์‹œ ์šด์ „์‚ฌ
๋ฐ˜์‘ํ˜•

๐Ÿ‘‹ ๋“ค์–ด๊ฐ€๋ฉฐ

์˜ค๋Š˜์€ ํ•„์ž๊ฐ€ ๊ฐ„๋‹จํ•œ ํ”„๋กœ์ ํŠธ๋ฅผ ์‹œ์ž‘ํ• ๋•Œ๋งˆ๋‹ค ์‚ฌ์šฉํ•˜๋Š” React์™€ TypeScript๋ฅผ ์ด์šฉํ•œ ๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ๋ฅผ ์†Œ๊ฐœํ•˜๊ณ ์žํ•œ๋‹ค. ํ•ด๋‹น ๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ์˜ ๋งํฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

๐Ÿ— ๊ธฐ๋ณธ๊ตฌ์กฐ

๊ธฐ๋ณธ์€ create-react-app์˜ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํ…œํ”Œ๋ฆฟ

๊ธฐ๋ณธ์ ์œผ๋กœ create-react-app์˜ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํ…œํ”Œ๋ฆฟ ๊ธฐ๋ฐ˜์ด๋‹ค. ํ•ด๋‹น ํ…œํ”Œ๋ฆฟ์€ ๋‹ค์Œ ์ปค๋งจ๋“œ๋กœ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

npx create-react-app my-app --template typescript
# or
yarn create react-app my-app --template typescript

global-styles.ts

์ „์—ญ์œผ๋กœ ์“ฐ์ด๋Š” CSS ํŒŒ์ผ์€ global-styles.ts๋ผ๋Š” ํŒŒ์ผ๋กœ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ๋‹ค. ํ•ด๋‹น ํŒŒ์ผ์—๋Š” ๊ฐ์ข… ์ „์—ญ์Šคํƒ€์ผ๊ณผ ์›น์ƒ์˜ CDN ํŒŒ์ผ์„ ๋ถˆ๋Ÿฌ์˜จ๋‹ค. ๋ถˆ๋Ÿฌ์˜ค๋Š” CDN ์ข…๋ฅ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • `normalize.css - ์ „์—ญ CSS๋ฅผ normalizeํ•œ๋‹ค. (โš ๏ธ reset๊ณผ ๋‹ค๋ฅธ ์—ญํ• ์ด๋‹ค.)
  • Font Awesome - ๊ฐ์ข… ์•„์ด์ฝ˜์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค..
  • ๊ฐ์ข… ์›น ํฐํŠธ - ๊ตฌ๊ธ€ ์›นํฐํŠธ์—์„œ ๊ฐ€์ ธ์˜ค๋ฉฐ ํ˜„์žฌ ๋ฐฐ๋‹ฌ์˜๋ฏผ์กฑ ๋„ํ˜„, ์†ก๋ช…, ๋‚˜๋ˆ”๊ณ ๋”•, ๋‚˜๋ˆ”๋ช…์กฐ, ๋‚˜๋ˆ”์†๊ธ€์”จ ํŽœ, ๊ฒ€์€๊ณ ๋”•๋ฅผ ์‚ฌ์šฉ์ค‘์ด๋‹ค.
import { createGlobalStyle } from './typed-components';
import { fontSize, color, media } from './config/_mixin';
export const GlobalStyle = createGlobalStyle`
  /*
    normalize.css - https://necolas.github.io/normalize.css/
  */
  @import url("https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.css");
  /*
    Fontawesome - https://fontawesome.com/
  */
  @import url("https://use.fontawesome.com/releases/v5.11.2/css/all.css");
  /*
    Web Fonts from Google Fonts

    ๋ฐฐ๋‹ฌ์˜๋ฏผ์กฑ ๋„ํ˜„ - https://fonts.google.com/specimen/Do+Hyeon
    ์†ก๋ช… - https://fonts.google.com/specimen/Song+Myung
    ๋‚˜๋ˆ” ๊ณ ๋”• - https://fonts.google.com/specimen/Nanum+Gothic
    ๋‚˜๋ˆ” ๋ช…์กฐ - https://fonts.google.com/specimen/Nanum+Myeongjo
    ๋‚˜๋ˆ”์†๊ธ€์”จ ํŽœ - https://fonts.google.com/specimen/Nanum+Pen+Script
    ๊ฒ€์€๊ณ ๋”• - https://fonts.google.com/specimen/Black+Han+Sans

    Use the following CSS rules to specify these families:
    font-family: 'Black Han Sans', sans-serif;
  */
  @import url("https://fonts.googleapis.com/css?family=Nanum+Gothic|Black+Han+Sans|Do+Hyeon|Song+Myung|Nanum+Myeongjo|Nanum+Pen+Script");
  * {
      box-sizing: border-box;
  }

  body{
    font-family: 'Nanum Gothic', sans-serif;
    font-size: ${fontSize.normalFontSize};
    /* background-color: ${color.default.bgColor};
    color: ${color.default.fontColor}; */
    background-color: ${color.darkmode.bgColor};
    color: ${color.darkmode.fontColor};
    ${media.giant} {
      /* Giant View */
    }
    ${media.desktop} {
      /* Desktop View */
    }
    ${media.tablet} {
      /* Tablet View */
    }
    ${media.phone} {
      /* Phone View */
    }
  }

  a{
    text-decoration: none !important;
    &:hover{
        color: ${color.default.mainColor};
        color: ${color.darkmode.mainColor};
    }
  }

  button{
    cursor: pointer;
    background-color: white;
    outline: none;
    border: none;
    &:active {
      outline: none;
      border: none;
    }
  }

  /* animations */
  @keyframes spin {
    0% {
      transform: rotate(0deg);
    }
    100% {
      transform: rotate(360deg);
    }
  }

  @keyframes fadeIn {
    0%{
      opacity: 0;
    }
    100%{
      opacity: 1;
    }
  }
`;

์ถ”๊ฐ€๋œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

styled-components

๊ฐœ์ธ ์ž‘์—…์„ ํ•  ์‹œ ์Šคํƒ€์ผ๊ณผ ๋กœ์ง์ด ๋ถ„๋ฆฌ๋˜๋ฉด ์ž‘์—…์†๋„๊ฐ€ ํ˜„์ €ํžˆ ์ค„์–ด๋“ ๋‹ค. CSS์ƒ์—์„œ ์ปดํฌ๋„ŒํŠธ์ƒ์˜ state๋ฅผ ์‚ฌ์šฉํ•˜๊ณ ๋„ ์‹ถ๊ธฐ๋„ํ•˜๊ณ , ๊ทธ๋ ‡๋‹ค๋ฉด styled-components๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

๊ฐ์ข… ํฌ๋ฉ”ํ„ฐ

๊ธฐ์กด์— ์‚ฌ์šฉํ•˜๋˜ ํ”„๋กœ์ ํŠธ์™€ ์ฝ”๋”ฉ ๊ฒฝํ—˜์„ ๋™์ผํ•˜๊ฒŒ ์œ ์ง€ํ•˜๊ธฐ์œ„ํ•ด 2๊ฐœ์˜ ํฌ๋ฉ”ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

eslint

๊ฐ์ข… eslint์™€ ๊ด€๋ จ๋œ ํŒจํ‚ค์ง€๋ฅผ ๊น”๊ณ  ์„ค์ •์„ ํ•˜์—ฌ ์‚ฌ์šฉ์ค‘์ด๋‹ค.

// .eslintrc
{
  "extends": [
    "eslint:recommended",
    "plugin:react/recommended",
    "plugin:@typescript-eslint/recommended",
    "prettier/@typescript-eslint",
    "plugin:prettier/recommended"
  ],
  "plugins": ["react", "@typescript-eslint", "prettier"],
  "env": {
    "browser": true,
    "jasmine": true,
    "jest": true
  },
  "settings": {
    "react": {
      "pragma": "React",
      "version": "detect"
    }
  },
  "parser": "@typescript-eslint/parser"
}

prettier

Visual Studio Code์˜ Prettier ํ™•์žฅํ”„๋กœ๊ทธ๋žจ๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค.

// .prettierrc
{
  "singleQuote": true,
  "semi": true,
  "useTabs": false,
  "tabWidth": 2,
  "trailingComma": "all",
  "printWidth": 80,
  "arrowParens": "always",
  "orderedImports": true
}

๋ฒ„์ „๊ด€๋ฆฌ

.nvmrc

.nvmrcํŒŒ์ผ์„ ์ด์šฉํ•ด ํ•ด๋‹น ํ”„๋กœ์ ํŠธ์˜ ๋…ธ๋“œ ๋ฒ„์ „์„ ํ†ต์ผํ•˜๊ณ  ์žˆ๋‹ค. ์ฃผ๋กœ ๋…ธ๋“œ์˜ LTS ๋ฒ„์ „์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค.

// .nvmrc
13.0.1

package.json

๋ฒ„์ „ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•ด ์—ญ์‹œ package.json์„ ์‚ฌ์šฉํ•œ๋‹ค.

// package.json
{
  "name": "react-typescript-boilerplate",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "react": "^16.11.0",
    "react-dom": "^16.11.0",
    "react-router": "^5.1.2",
    "react-scripts": "^3.3.0",
    "styled-components": "^4.4.0"
  },
  "devDependencies": {
    "@testing-library/react": "^9.3.0",
    "@types/jest": "24.0.20",
    "@types/node": "12.11.7",
    "@types/react": "^16.9.11",
    "@types/react-dom": "16.9.3",
    "@types/react-router": "^5.1.2",
    "@types/styled-components": "^4.1.19",
    "@typescript-eslint/eslint-plugin": "^2.5.0",
    "@typescript-eslint/parser": "^2.5.0",
    "eslint": "^6.8.0",
    "eslint-config-react": "^1.1.7",
    "eslint-loader": "^3.0.2",
    "tslint": "^5.20.0",
    "typescript": "^3.6.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}
๋ฐ˜์‘ํ˜•