🔍 배경 및 궁금증Q. CRA를 사용하지 않고 리액트를 세팅하는 방법? (with Webpack + emotion + storybook + postcss + scss)📢 해결 방법PrerequisitesStep#01 프로젝트 세팅 하기Step#02 웹팩 설치하기Step#03 ESLint 설치 및 설정하기 + Prettier 포맷팅Step#04 리액트 설치하기Step#05 이모션 설치하기Step#06 바벨 설치 및 설정하기Step#07 웹팩 관련 패키지 설치 및 설정하기Step#08 스토리북 설치하기Step#09 디렉토리 구조 잡기
🔍 배경 및 궁금증
Q. CRA를 사용하지 않고 리액트를 세팅하는 방법? (with Webpack + emotion + storybook + postcss + scss)
📢 해결 방법
스텝 바이 스텝으로 진행합니다
Prerequisites
yarn init yarn add yarn add -D # dev dependencies yarn remove
Step#01 프로젝트 세팅 하기
yarn init -y
파일 생성하기:
.gitignore
:- gitignore.io 사이트에서 다음 항목 체크
- macOS, Windows, Node, yarn, react, dotenv
/index.html
:<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>ReactSetting</title> </head> <body> <div id="app"></div> </body> </html>
/src/index.js
:아래 코드는 현재 실행되지 않는다. 개발환경 세팅을 진행하면서 세팅이 잘 진행되는지 확인하기 위한 용도로 미리 작성한다.
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; ReactDOM.render(<App />, document.getElementById('app'));
/src/App.js
:import React from 'react'; import styled from '@emotion/styled'; const AppContainer = styled.div` color: #777; `; const App = () => ( <AppContainer> <h1>HELLO REACT!</h1> </AppContainer> ); export default App;
현재까지 작성된 파일:
❯ tree -I node_modules . ├── index.html ├── package.json ├── src │ ├── App.js │ └── index.js └── yarn.lock
Step#02 웹팩 설치하기
리액트로 작성된 코드를 브라우저에서 실행할 수 있도록 번들러인 웹팩을 사용할 것이다. 개발 서버를 위해 웹팩 데브 서버도 함께 설치한다.
yarn add -D webpack webpack-cli webpack-dev-server
package.json
:{ "scripts": { "start": "webpack serve --open --env=development", "build": "webpack serve --env=production" } }
Step#03 ESLint 설치 및 설정하기 + Prettier 포맷팅
효율적인 협업을 위해 코드 오류를 잡아내는 ESLint와 동일한 포맷팅을 해주는 Prettier를 설치한다
yarn add -D eslint
yarn run eslint --init
? How would you like to use ESLint? … ❯ To check syntax, find problems, and enforce code style ? What type of modules does your project use? … ❯ JavaScript modules (import/export) ? Which framework does your project use? … ❯ React ? Does your project use TypeScript? ❯ No ? Where does your code run? … ✔ Browser ? How would you like to define a style for your project? … ❯ Use a popular style guide ? Which style guide do you want to follow? … ❯ Airbnb: https://github.com/airbnb/javascript ? What format do you want your config file to be in? … ❯ JavaScript ? Would you like to install them now with npm? › Yes
eslint init 과정에서 8.0.1에 대한 오류가 발생할 수 있다.
이때 package.json에 가보면 eslint의 버전이 7 버전대로 다운그레이드 되어 있다. 즉 선택한 인터랙티브 옵션이 8.0.1 버전대와 호환되지 않아서 오류가 발생하는 것으로 추측된다. 해결 방법은 이미 package.json에 7 버전대로 다운그레이드 되어 있으니 다시 eslint init 명령어를 실행하면 성공한다.
ESLint Issue
vscode 익스텐션으로 린트나 포매터 설치 이후에는 해당 익스텍션들이 정상적으로 로드 되지 않는 경우가 있기 때문에 그럴 때마다 vscode를 재시작 해준다.
현재
index.js
파일을 보면 린트 에러가 뜬다:
prettier와 eslint에서 포맷팅 규칙이 충돌할 때 prettier의 규칙을 우선하고(
eslint-config-prettier
), prettier에서 인식하는 코드 포맷팅 오류를 ESLint 오류로 출력(eslint-plugin-prettier
)시켜주기 위해 설치:yarn add -D prettier eslint-config-prettier eslint-plugin-prettier
.eslintrc.js
:module.exports = { env: { browser: true, es2021: true, }, extends: [ 'plugin:react/recommended', 'airbnb', 'plugin:prettier/recommended', ], parserOptions: { ecmaFeatures: { jsx: true, }, ecmaVersion: 12, sourceType: 'module', }, plugins: ['react', 'prettier'], rules: { 'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx'] }], }, };
.prettierrc.json
:{ "trailingComma": "es5", "tabWidth": 2, "semi": true, "singleQuote": true }
vscode에서 저장하면 자동으로 고쳐주도록 설정하기
- extension: eslint 설치
- command palette > settings.json > Preferences: Open Settings (JSON)
"editor.codeActionsOnSave": { "source.fixAll.eslint": true }, "[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.formatOnSave": true, }
pacakge.json
:{ "scripts": { "lint": "eslint --fix --ext js ./src/*.js" } }
아직까지는 에러가 발생한다

리액트 라이브러리를 설치하지 않았기 때문에 발생하는 오류와 App 파일의 확장자를 사용하지 않아 발생하는 린트 오류를 추후 모두 해결할 것이다
TODO 스타일린트 설치:
Step#04 리액트 설치하기
yarn add react react-dom react-router-dom
라이브러리 설치 이후
index.js
의 린트 에러가 줄어들었다
Step#05 이모션 설치하기
yarn add @emotion/react @emotion/styled
# 이모션 이용하려면 babel 플러그인 설치 yarn add -D @emotion/babel-plugin
emotion 관련 바벨 설정은 바벨 설치할 때 한다
Step#06 바벨 설치 및 설정하기
yarn add -D @babel/core @babel/preset-env @babel/preset-react
.babelrc
:{ "presets": [ "@babel/preset-env", "@babel/preset-react" ], "plugins": [ [ "@babel/plugin-transform-runtime", { "corejs": 3 } ], "@emotion" ] }
Step#07 웹팩 관련 패키지 설치 및 설정하기
yarn add dotenv
yarn add -D babel-loader css-loader sass-loader style-loader \ postcss postcss-loader \ html-webpack-plugin mini-css-extract-plugin
yarn add autoprefixer
webpack.config.js
:require('dotenv').config(); const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); module.exports = (webpackEnv) => { const isEnvDevelopment = !!webpackEnv.development; const isEnvProduction = !!webpackEnv.production; return { mode: isEnvProduction ? 'production' : isEnvDevelopment && 'development', resolve: { extensions: ['.js', '.jsx'], alias: { '@': path.resolve(__dirname, 'src'), }, }, entry: path.resolve(__dirname, 'src/index.js'), output: { path: path.resolve(__dirname, 'dist'), filename: '[name].bundle.js', publicPath: '/', clean: true, }, plugins: [ new HtmlWebpackPlugin({ filename: './index.html', template: path.resolve(__dirname, './index.html'), favicon: 'logo.png', }), isEnvProduction && new MiniCssExtractPlugin({ filename: '[name].css', }), ].filter(Boolean), module: { rules: [ { test: /\.(js|mjs|jsx)$/, exclude: /node_modules/, use: { loader: 'babel-loader', }, }, { test: /\.s?css$/i, use: [ isEnvProduction ? MiniCssExtractPlugin.loader : 'style-loader', { loader: 'css-loader', ...(isEnvDevelopment ? { options: { sourceMap: true, }, } : {}), }, 'postcss-loader', { loader: 'sass-loader', ...(isEnvDevelopment ? { options: { sourceMap: true, }, } : {}), }, ], }, { test: /\.(png|jpe?g|gif|mp3)$/i, type: 'asset/resource', }, ], }, ...(isEnvDevelopment ? { devtool: 'source-map', devServer: { historyApiFallback: true, hot: true, compress: true, port: 8000, }, } : {}), }; };
Step#08 스토리북 설치하기
npx -p @storybook/cli sb init
Step#09 디렉토리 구조 잡기
현재 없는 폴더들 (ex. apis, assets, components, ...)은 직접 생성하기
❯ tree -I node_modules -a -C . ├── .babelrc ├── .eslintrc.js ├── .gitignore ├── .prettierrc.json ├── .storybook │ ├── main.js │ └── preview.js ├── index.html ├── package-lock.json ├── package.json ├── src │ ├── App.js │ ├── apis │ ├── assets │ ├── components │ ├── contexts │ ├── hooks │ ├── index.js │ ├── stories │ └── utils ├── webpack.config.js └── yarn.lock