์์ฝ1) create-react-app & Typescripttsconfig.json2) ESLint & Prettier ์ค์ package.json.eslintrc.js.prettierrc3) emotion, styledcraco(create-react-app-config-override)craco.config.jspackage.json4) Storybookstorybook ์ค์น ํ start ์ค๋ฅ5) Axios6) .env์ต์ข
package.json
์์ฝ
create-react-app
,Typescript
ESlint
,Prettier
emotion/styled
storybook
axios
1) create-react-app & Typescript
- ๊ธฐ๋ณธ:
yarn
๊ธฐ๋ฐ ํจํค์ง
- CRA๋ฅผ Typescript ๋ฒ์ ์ผ๋ก ์ค์น.
yarn create react-app yas --template typescript
tsconfig.json
{ "compilerOptions": { "target": "es6", // ๊ธฐ๋ณธ๊ฐ: es5 => es6๋ก ์์ "lib": [ "dom", "dom.iterable", "esnext" ], "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" }, "include": [ "src" ], }
2) ESLint & Prettier ์ค์
yarn add -D eslint prettier yarn add -D @typescript-eslint/eslint-plugin @typescript-eslint/parser // ESLint Rule ์ถ๊ฐ ํ๋ฌ๊ทธ์ธ yarn add -D eslint-config-airbnb // airbnb ESLint ๊ท์น yarn add -D eslint-config-prettier eslint-plugin-prettier // prettier Rule ํ๋ฌ๊ทธ์ธ yarn add -D eslint-plugin-react eslint-plugin-react-hooks // airbnb ESLint ๊ท์น yarn add -D eslint-plugin-jsx-a11y eslint-plugin-import // airbnb ESLint ๊ท์น
package.json
- ์ค์น ์๋ฃ ํ ์๋์
devDependencies
๊ฐ ์ถ๊ฐ๋๋ค.
// ... "devDependencies": { "@typescript-eslint/eslint-plugin": "^5.4.0", "@typescript-eslint/parser": "^5.4.0", "eslint": "^8.3.0", "eslint-config-airbnb": "^19.0.1", "eslint-config-prettier": "^8.3.0", "eslint-plugin-import": "^2.25.3", "eslint-plugin-jsx-a11y": "^6.5.1", "eslint-plugin-prettier": "^4.0.0", "eslint-plugin-react": "^7.27.1", "eslint-plugin-react-hooks": "^4.3.0", "prettier": "^2.5.0" } // ...
.eslintrc.js
- ์๋ ์์ฑ๋
.eslintrc.js
์ฝ๋๋ฅผ ์๋์ ๊ฐ์ด ์์ ํ์ฌ rule์ ์ถ๊ฐํ๋ค.
module.exports = { env: { browser: true, node: true, // node: true, commonjs: true ์ถ๊ฐ commonjs: true, // ์ฌ์ ์ ์๋ static ๋ฉ์๋๋ฅผ ์ธ์ํ ์ ์์ด์ ์๋ฌ ๋ฐ์ํ๋ ๊ฒ์ ๋ํด ESLint ๊ฒฝ๊ณ ๊ฐ ๋ฐ์ํ์ง ์๋๋ก ์ถ๊ฐ es2021: true, }, extends: [ 'airbnb', 'plugin:react/recommended', 'plugin:jsx-a11y/recommended', 'plugin:import/errors', 'plugin:import/warnings', 'plugin:@typescript-eslint/recommended', ], parser: '@typescript-eslint/parser', parserOptions: { ecmaFeatures: { jsx: true, }, ecmaVersion: 2018, sourceType: 'module', }, plugins: ['react', '@typescript-eslint'], rules: { 'linebreak-style': 0, 'import/prefer-default-export': 0, 'import/extensions': 0, 'no-use-before-define': 0, 'import/no-unresolved': 0, 'react/react-in-jsx-scope': 0, 'import/no-extraneous-dependencies': 0, 'no-shadow': 0, 'react/prop-types': 0, 'react/jsx-one-expression-per-line': 0, 'func-names': ['error', 'as-needed'], 'react/jsx-filename-extension': [ 2, { extensions: ['.js', '.jsx', '.ts', '.tsx'], }, ], 'object-curly-newline': [ 'error', { ExportDeclaration: { multiline: true, minProperties: 2, }, }, ], 'jsx-a11y/no-noninteractive-element-interactions': 0, '@typescript-eslint/explicit-module-boundary-types': 0, }, settings: { 'import/resolver': { node: { extensions: ['.js', '.jsx', '.ts', '.tsx'], }, }, }, };
.prettierrc
- ๋ฃจํธ ํด๋์
.prettierrc
ํ์ผ ์์ฑ ํ ์๋ ์ฝ๋๋ฅผ ์์ฑํ๋ค.
{ "singleQuote": true, "semi": true, "useTabs": false, "tabWidth": 2, "trailingComma": "all", "printWidth": 80, "arrowParens": "always", "orderedImports": true, "bracketSpacing": true, "jsxBracketSameLine": false }
3) emotion, styled
- styled component
- javascript ํ์ผ ๋ด๋ถ์์ ์คํ์ผ ์ ์ฉ ํจํค์ง
yarn add @emotion/react // emotion yarn add --dev @emotion/babel-plugin // babel yarn add @emotion/styled // styled
// ... "dependencies": { "@emotion/react": "^11.6.0", "@emotion/styled": "^11.6.0", // ...
craco(create-react-app-config-override)
- ์์ ํจํค์ง 3๊ฐ๋ง ์ถ๊ฐํ๋ฉด styled ํจํค์ง๋ฅผ ์ฌ์ฉํ ๋ ๋ง๋ค
/** @jsxImportSource @emotion/react */
fragma ์ฃผ์์ ์ถ๊ฐํด์ผ ๋๋๋ฐ, ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํดcraco
๋ฅผ ์ค์นํ๋ค.
yarn add -D @craco/craco yarn add -D @emotion/babel-preset-css-prop
craco.config.js
- ๋ฃจํธ ํด๋์ craco.config.js ํ์ผ์ ์์ฑํ์ฌ ์๋์ ๊ฐ์ด ์ถ๊ฐํ๋ค.
module.exports = { babel: { presets: ["@emotion/babel-preset-css-prop"] } }
package.json
- package.json ํ์ผ์์ scripts ๋ถ๋ถ์
react-scripts
์์craco
๋ก ๋ณ๊ฒฝํ๋ค.
// ... "scripts": { "start": "craco start", "build": "craco build", "test": "craco test", "eject": "craco eject" }, // ...
4) Storybook
- UI ์ปดํฌ๋ํธ๋ฅผ ๋ชจ์ ๋ฌธ์ํํ๊ณ ๋ณด์ฌ์ฃผ๋ ์คํ์์ค Tool
npx -p @storybook/cli sb init

storybook ์ค์น ํ start ์ค๋ฅ
- storybook ์ค์น ํ react-scripts์ storybook์ babel-loader ๋ฒ์ ์ด ๋ฌ๋ผ์ yarn start๋ก ๋ก์ปฌ ํ๊ฒฝ Open์ด ๋์ง ์๋ ํ์์ด ๋ฐ์ํ๋ค.
- package.json ํ์ผ์ ์๋ ์ฝ๋๋ฅผ ์ถ๊ฐํ์ฌ ํด๊ฒฐํ ์ ์๋ค.
// package.json // ... "resolutions": { "babel-loader": "8.1.0" } // ...
5) Axios
- ๋ธ๋ผ์ฐ์ , Node.js๋ฅผ ์ํ Promise API๋ฅผ ํ์ฉํ๋ HTTP ๋น๋๊ธฐ ํต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
yarn add axios
6) .env
ESLint
์ค์น ํ package.json๊ณผ yarn.lock์์์ package version ์ฐจ์ด๊ฐ ๋ฐ์ํด์ yarn start ๊ฐ์ ๋ก์ปฌ ํ๊ฒฝ์ด Open๋์ง ์๋๋ค.
- ๋ฃจํธ ํด๋์ .env ํ์ผ์ ์์ฑ ํ ์๋ ์ฝ๋๋ฅผ ์ถ๊ฐํ๋ค.
SKIP_PREFLIGHT_CHECK=true
์ต์ข package.json
{ "name": "yas", "version": "0.1.0", "private": true, "dependencies": { "@emotion/react": "^11.6.0", "@emotion/styled": "^11.6.0", "@testing-library/jest-dom": "^5.11.4", "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", "@types/jest": "^26.0.15", "@types/node": "^12.0.0", "@types/react": "^17.0.0", "@types/react-dom": "^17.0.0", "axios": "^0.24.0", "react": "^17.0.2", "react-dom": "^17.0.2", "react-scripts": "4.0.3", "typescript": "^4.1.2", "web-vitals": "^1.0.1" }, "scripts": { "start": "craco start", "build": "craco build", "test": "craco test", "eject": "craco eject", "storybook": "start-storybook -p 6006 -s public", "build-storybook": "build-storybook -s public" }, "resolutions": { "babel-loader": "8.1.0" }, "eslintConfig": { "extends": [ "react-app", "react-app/jest" ], "overrides": [ { "files": [ "**/*.stories.*" ], "rules": { "import/no-anonymous-default-export": "off" } } ] }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] }, "devDependencies": { "@craco/craco": "^6.4.2", "@emotion/babel-plugin": "^11.3.0", "@emotion/babel-preset-css-prop": "^11.2.0", "@storybook/addon-actions": "^6.3.12", "@storybook/addon-essentials": "^6.3.12", "@storybook/addon-links": "^6.3.12", "@storybook/node-logger": "^6.3.12", "@storybook/preset-create-react-app": "^3.2.0", "@storybook/react": "^6.3.12", "@typescript-eslint/eslint-plugin": "^5.4.0", "@typescript-eslint/parser": "^5.4.0", "eslint": "8.3.0", "eslint-config-airbnb": "^19.0.1", "eslint-config-prettier": "^8.3.0", "eslint-plugin-import": "^2.25.3", "eslint-plugin-jsx-a11y": "^6.5.1", "eslint-plugin-prettier": "^4.0.0", "eslint-plugin-react": "^7.27.1", "eslint-plugin-react-hooks": "^4.3.0", "prettier": "^2.5.0" } }