이번에 우아한테크코스에서 진행한 프로젝트의 개발환경을 처음 세팅할 때,
같은 팀 프론트엔드 크루와 함께 기준으로 삼았던 것은 바로 CRA였다.
'우리가 CRA를 쓰던 때와 비슷하게, 아무런 불편함 없이 코딩할 수 있을 정도'로 세팅을 하자는 것.
그러면 그냥 CRA를 쓰면 되지, 왜 굳이 처음부터 세팅을 하느냐?
CRA를 사용하면 불필요한 기능들까지 한 번에 딸려오기 때문에 가지치기 작업을 해줘야하는데,
그럴바에 차라리 직접 리액트 개발환경을 세팅하면서 공부를 해보자는 것이 공통된 의견이었다.
더불어 CRA를 사용하는 것이 불가능한 조건이었다는 건 비밀.
■ package.json
우선, 당연히 npm init을 통해 package.json을 만드는 것부터 시작된다.
npm init
📦 웹팩(Webpack) 세팅하기
npm install webpack webpack-cli webpack-dev-server --save-dev
바로 웹팩 관련 모듈들을 설치하고, webpack.config.js 파일을 만들어서 웹팩 세팅을 해준다.
설치한 모듈들은 다음과 같다.
1. webpack
웹팩은 여러 개의 파일을 하나의 파일로 합쳐주는 모듈 번들러이다.
하나의 시작점 파일(entry)에서 시작해서 entry와 의존적인 파일을 모두 찾아내 하나의 파일로 합쳐주는 방식.
2. webpack-cli
웹팩을 터미널 명령어로 실행할 수 있게 해주는 패키지이다.
3. webpack-dev-server
webpack-dev-server는 별도의 서버를 구축하지 않고도 간단한 개발용 웹서버를 구동할 수 있게 해준다.
또한 hot-reload를 통해 매번 일일이 브라우저를 새로고침하지 않아도
코드가 변경될 때 자동으로 새로고침되게 만들 수 있다.
원래는 webpack-dev-server라는 명령어로 실행을 시켰지만,
webpack 4, 5 버전부터는 'webpack serve'라는 명령어로 dev-server를 실행시켜야 한다.
그리고 몇 개의 플러그인들을 다운받아줬다.
npm install --save-dev html-webpack-plugin error-overlay-webpack-plugin eslint-webpack-plugin clean-webpack-plugin
1. HtmlWebpackPlugin
HtmlWebpackPlugin은 HTML 파일을 후처리하는 데에 사용된다.
빌드 타임에 동적으로 HTML 파일에 값을 주입하는 것이 가능하며,
웹팩으로 빌드한 JS파일을 자동으로 HTML 파일에 집어넣어준다.
그래서 HTML 파일에 script 태그를 적어줄 필요가 없다.
2. ErrorOverlayWebpackPlugin
CRA에서 사용하고 있는 플러그인인데, 콘솔창을 굳이 열지 않더라도 에러가 발생했을 때
해당 에러를 브라우저 화면에서 직접 눈앞에다 때려박아주기 때문에 상당히 편해진다.
3. EslintWebpackPlugin
웹팩으로 빌드를 했을 때 ESLint 규칙을 만족하지 못하는 코드가 있으면 터미널과 콘솔창에 에러를 발생시킨다.
ESLint를 충실히 지킬 수 있다는 점은 좋지만, ESLint 에러가 발생하는 경우에 hot-reload가 안되기 때문에
가끔 번거로울 때가 있는 플러그인.
물론 hot-reload를 막는 기능은 emitWarning 옵션을 추가해주면 끌 수 있다.
plugins: [
new ESLintPlugin({
options: {
emitWarning: true,
},
}),
],
eslint-loader라는 로더 형태로 불러오는 방법도 있는데, eslint-loader는 곧 deprecated 될 예정이므로
eslint-webpack-plugin을 사용하는 것을 권장하고 있다.
4. CleanWebpackPlugin
웹팩으로 빌드를 하고나면 output 경로에 빌드 결과물들이 생성되는데,
빌드를 새로 하더라도 이전 빌드 결과물들이 여전히 남아있는 경우가 있다.
이러한 경우에 이전 빌드 결과물들을 제거해주는 플러그인.
이 외에도 한 개의 큰 CSS 파일을 받는 것보다 여러 개의 작은 CSS 파일을 받는 것이 더 빠르다 하여
MiniCssExtractPlugin을 사용하는 경우도 많지만, 일단 지금 당장은 그리 와닿지 않아서 설치하지 않았다.
◎ 참고로 loader와 plugin의 차이는,
loader는 번들이 생성되는동안, 또는 번들링 중에 개별 파일 수준에서 작업을 한다.
반면 plugin은 번들링 완료 후, 즉 번들이 생성된 후에 해당 번들 파일 수준에서 작동한다.
플러그인들을 모두 설치했다면, webpack.config.js 파일에
각 플러그인의 사용법에 맞게 plugins 옵션에 나열해주면 된다.
■ webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ErrorOverlayPlugin = require('error-overlay-webpack-plugin');
const ESLintPlugin = require('eslint-webpack-plugin');
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const path = require("path");
module.exports = (env, options) => {
return {
...
plugins: [
new ErrorOverlayPlugin(),
new CleanWebpackPlugin(),
new ESLintPlugin(),
new HtmlWebpackPlugin({
template: 'index.html',
favicon: './assets/favicon.ico',
}),
new WebpackManifestPlugin({
fileName: 'manifest.json',
basePath: './assets/',
}),
],
}
}
이제 webpack.config.js의 나머지 옵션들을 살펴볼 차례.
module.exports = (env, options) => {
return {
entry: './index.js',
output: {
path: path.join(__dirname, '/build'),
publicPath: '/',
filename: 'bundle.js',
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader'],
},
{
test: /\.(css|scss|sass)$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
},
],
},
resolve: {
extensions: ['.js', '.jsx', 'scss'],
},
devServer: {
contentBase: path.join(__dirname, '/build'),
publicPath: '/',
hot: true,
inline: true,
host: 'localhost',
port: 3000,
historyApiFallback: true,
},
devtool: options.mode === 'production' ? false : 'inline-source-map',
... // 위에서 언급한 plugins 생략
target: 'web',
performance: {
hints: false,
},
};
};
맨 위에서부터 차근차근 살펴보도록 하자.
■ entry
entry는 말 그대로 번들링 진입점을 의미한다.
entry 파일부터 타고 들어가서, 의존성이 있는 파일들을 전부 찾아내 하나의 파일로 번들링하게 된다.
■ output
output도 말 그대로 결과물에 관한 옵션이다.
- path: 번들링 결과 파일을 어느 경로에 위치시킬 것인가를 의미한다.
- publicPath: 빌드할 때 플러그인, CSS, HTML 등의 파일 내부의 URL들을 업데이트해주기 위한 옵션이다.
URL들이 상대경로로 표기되어있다면, 앞에 prefix처럼 publicPath가 붙는 방식.
CDN을 사용하는 경우에, 해당 CDN에서 올바르게 파일들이 가져와질 수 있게 해준다.
지금 보니 publicPath를 설정해놓으나 마나한 값으로 설정해놓은 것 같다.
- filename: 번들링 결과물 파일명을 의미한다.
■ module
웹팩은 로더를 이용하는 덕분에 자바스크립트가 아닌 다른 언어들을 자바스크립트 문법으로 변환해줄 수 있다.
Typescript나 CSS 로더가 그 예. 또한, 이미지를 dataURL 문자열로 변환해서 가져오기도 한다.
그 덕분에 CSS, 이미지, 폰트 등의 파일들을 모듈로써 자바스크립트 파일 내에서 직접 import할 수 있는 것.
module 옵션은 이러한 로더를 세팅해주는 옵션이다.
rules는 말 그대로 로더들을 어떤 규칙으로 적용해줄 것인가에 관한 내용.
exclude에 있는 파일들을 제외한, test를 만족하는(주로 특정 확장자로 끝나는) 파일들에
use에 기입된 로더를 적용해주는 식이다.
이번에 사용한 로더들의 종류는 다음과 같다.
npm install --save-dev babel-loader css-loader style-loader sass-loader
1. babel-loader
보통 ES6+의 문법은 구형 브라우저에서 지원되지 않는 경우가 많다.
그래서 구형 브라우저에서 지원되는 ES5의 문법으로 변환해주는 것을 '트랜스파일링'이라고 한다.
babel은 이러한 역할을 해주는 트랜스 컴파일러이다.
그리고 웹팩이 모듈을 번들링할 때 babel을 적용해주기 위해 babel-loader를 사용한다.
2. css-loader
위에서 언급했듯이, 웹팩을 사용하면 CSS 파일 또한 import 구문으로 불러올 수 있다.
이렇게 CSS를 import로 불러오려면 CSS를 자바스크립트 모듈로 변환해야하고, 이를 위해 css-loader가 필요하다.
3. style-loader
css-loader를 설치하면 CSS를 자바스크립트 모듈로 변환해서 import 해올 순 있지만,
DOM에 자동으로 적용되진 않는다. 하지만 당연하게도 스타일이 해석되려면 DOM에 추가되어있어야 한다.
style-loader는 자바스크립트로 변환된 스타일을 DOM에 자동으로 적용시켜주는 역할을 한다.
즉, css-loader 만으로는 스타일을 import해오는 것밖에 안되고, 그 스타일을 적용하려면 style-loader가 있어야 한다.
그래서 보통은 css-loader와 style-loader를 함께 가져가는 경우가 많다.
4. sass-loader
이름에서도 알 수 있다시피, sass 문법을 사용하기위한 로더이다.
sass-loader가 sass 파일을 먼저 css 파일로 변환시켜놓으면, css-loader와 style-loader가 해당 css 파일을 처리하는 식.
추후에 필요에 따라 다른 로더를 더 사용할 수도 있고, 불필요하다고 생각되는 로더를 지울 수도 있다.
■ resolve
resolve는 웹팩이 알아서 특정 경로나 확장자를 처리할 수 있게 도와주는 옵션이다.
extensions에 넣은 확장자들은 웹팩에서 알아서 처리를 해주기때문에
import할 때 해당 확장자를 파일명에 입력할 필요가 없어진다.
참고로 extensions에 적힌 순서대로 확장자를 찾아낸다.
예를 들어, 동일한 파일명을 가진 다른 확장자 파일이 여럿 존재할 경우,
extensions 배열에서 더 앞에 있는 파일을 찾아내고 나머지는 그냥 무시해버린다.
■ devServer
webpack-dev-server와 관련된 설정들이다.
- contentBase: 실행할 HTML파일의 경로라고 생각하면 된다.
웹팩 번들링 결과물이 나오는 경로를 적어주면 된다. 기본값으로 웹팩 결과물이 지정되는 것으로 알고 있다.
- publicPath: 브라우저를 통해 접근하는 경로를 의미한다. 기본값은 '/' 이다.
개발서버를 구동할 때는 보통 localhost의 root 경로에서 동작하는 경우가 많은데,
그러면 그냥 기본값으로 두면 된다.
만약 이 publichPath가 올바르게 적용되어있지 않으면, hot-reload가 되지 않는 문제가 발생한다.
- hot: hot-reload를 사용할 것이냐 하는 옵션.
공식문서에서는 Hot Module Replacement(HMR)라고 부르는 듯.
(CSS의 경우에는 새로고침되지 않고 수정사항이 바로 적용되기 때문에 reload라는 단어가 맞지 않긴 하다)
- inline: 인라인 모드로 HMR을 실행시켜주겠다는 의미.
이 옵션을 적용하지 않으면 iframe 모드로 HMR이 실행되는데,
둘의 차이점은 iframe모드는 말 그대로 iframe 내부에 페이지가 내장되어서 HMR이 실행되기 때문에
앱의 URL 변화가 실제 브라우저창의 URL에 반영되지 않는다.
그래서 실제 앱의 구동과 비슷한 환경으로 HMR을 실행해주려면 inline 모드를 사용하는 편이 나은 듯.
- host: 개발 시에 도메인을 맞추어야 하는 경우에 사용된다.
예를 들면, 쿠키 인증을 사용하는 경우 인증 서버와 동일한 도메인으로 맞춰야 한다.
그래서 위의 파일에서 localhost로 host를 맞춰준 건, 아주 쓰잘데기 없는 행동이었다고 할 수 있다.
- port: 개발 서버의 포트 번호를 의미. 기본값은 8080.
historyApiFallback는 history API를 사용하는 SPA를 개발할 때 사용되는 옵션.
true로 설정될 경우, 404가 발생하면 index.html로 redirect 해준다.
■ devtool
디버깅에 사용되는 'source-map'을 설정하는 옵션이다.
* source-map: 배포용으로 빌드한 파일(암호화된 파일)에서 에러가 발생했을 때,
디버깅을 위해 원본 파일의 어디에서 에러가 발생했는지를 연결시켜주는 기능.
웹팩이 파일을 번들링해서 서버에 배포를 할 때는 성능 최적화를 위해 HTML, CSS, JS 파일들을 압축한다.
그러면 번들링 이후에는 원래 파일의 어떤 부분에서 에러가 발생했는지를 추적하기가 어려워진다.
예를 들어, a.js, b.js, c.js라는 세 개의 파일을 bundle.js 하는 하나의 파일로 번들링했다고 치자.
그러면 a.js, b.js, c.js 중 하나의 파일에 에러가 발생했을 때,
에러 로그는 그저 bundle.js 파일에 에러가 발생했다고만 알려준다.
이렇게 되면 에러가 정확히 어디에서 발생했는지 추적하기가 어려워지기 때문에 source-map을 사용하는 것.
보통 개발용으로는 inline-source-map이 적당한 편이다.
반면, source-map의 용량이 상당히 크기 때문에 배포할 때는 false를 줘서 제거해주는 편이 좋다.
혹시 넣고싶다면 cheap-module-source-map이 적당하다고 함.
■ target
특정 환경을 대상으로 지정하도록 설정해주는 옵션.
webpack-dev-server에서 hot-reload를 사용하고 싶다면 target에다가 web을 추가해줘야 했던 것으로 기억.
■ performance
웹팩의 퍼포먼스는 파일 용량 등으로 인해 저하되는 빌드 파일의 퍼포먼스를 의미한다.
빌드할 때 이 퍼포먼스에 관한 내용이 에러로 나타나게 할 수도, 경고로 나타나게 할 수도 있다.
일단은 파일 용량이 퍼포먼스를 저해할만큼 크게 될 경우가 없다고 생각해서 꺼두었는데,
추후에 파일 용량이 많이 커진다 싶으면 다시 켜서 파일 용량 관리를 해줘야할 듯 하다.
🧱 바벨(Babel) 세팅하기
이제 이 정도면 이번 프로젝트에서 사용한 웹팩 옵션들에 대해 어느정도 알아본 것 같고,
다음은 Babel을 설치할 차례이다.
npm install --save-dev @babel/core @babel/preset-env @babel/preset-react babel-eslint
Babel은 크로스 브라우징 이슈를 해결하기 위한 툴이다.
오래된 브라우저들은 ES6+의 문법을 지원하지 않는 경우가 많은데,
이러한 경우를 위해 ES6+의 문법을 ES5 문법으로 변환해준다. 이를 '트랜스파일'이라고 한다.
더불어, 타입스크립트같은 다른 언어들까지 ES5로 변환해주는 기똥찬 녀석이다.
Babel은 보통 따로 사용하는 경우는 잘 없고, babel-loader를 사용해서 웹팩에 통합시켜 사용한다.
하지만 babel-loader는 위에서 webpack 설정할 때 설치해줬으니, 패스하도록 하자.
1. @babel/core
바벨은 코드를 읽고 추상 구문 트리(AST)로 변환하는 '파싱' 단계,
그리고 이 추상 구문 트리를 변환, 즉 실제로 소스코드를 내가 원하는 문법으로 변환해주는 '변환' 단계,
마지막으로 변환한 코드를 출력해주는 '출력' 단계를 거쳐 트랜스파일링 작업을 한다.
이 중에서 @babel/core, 즉 바벨의 코어가 맡는 역할은 '파싱' 단계와 '출력' 단계이고,
중간 단계인 '변환' 단계는 바벨의 플러그인(plugin)이 맡게 된다.
보통 바벨은, '화살표 함수를 변환해주는 플러그인', 'let, const를 변환해주는 플러그인' 처럼
고쳐야 할 문법들 하나하나마다 일일이 플러그인이 따로 존재한다.
이러한 플러그인들을 전부 다운받는 것은 상당히 귀찮은 일이다.
그래서 바벨에서는 목적에 맞는 플러그인들을 전부 모아서 프리셋(preset)이라는 것들 만들었다.
바벨에서 공식적으로 지원하는 프리셋은 @babel/preset-env, @babel/preset-react, @babel/preset-flow, @babel/preset-typescript 등이 있다.
이 중에서 우리는 react 개발 환경을 구축하는 데에 필요한 preset-env와 preset-react를 다운받았다.
2. @babel/preset-env
preset-env는 ES6+의 문법을 변환하는 데에 필요한 플러그인들이 전부 포함되어있는 프리셋이다.
3. @babel/preset-react
preset-react는 react 문법을 변환하는 데에 필요한 프리셋이다.
4. babel-eslint
ESLint가 Babel에 의해 변환된 소스코드에서 실행될 수 있도록 하는 parser이다.
참고로 아직 정식 표준이 아닌, 제안 단계의 자바스크립트 코드의 경우
ESLint가 파싱을 할 수 없기 때문에 에러가 발생한다.
이 경우에 파싱을 정상적으로 하기 위해서는 babel-eslint를 설치해주면 된다고 한다.
■ babelrc.
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": {
"version": 3
}
}
],
"@babel/preset-react"
]
}
presets에다가 설치한 프리셋들을 배열로 넣어주면 된다.
@babel/preset-react는 별도의 옵션 없이 그냥 넣어주는 편이므로, preset-env 관련 옵션만 살펴보자.
1. preset-env 관련 옵션 중 가장 많이 사용되는 건 target 옵션이다. (상단의 코드에는 없지만..)
targets 옵션에다가 { chrome: "79" } 와 같은 식으로 브라우저 버젼명을 지정해주면
해당 버젼에 맞게 코드를 변환해준다.
2. 상단의 useBuiltIns와 corejs는 폴리필에 관한 옵션이다.
폴리필은, ES6+의 문법을 대체할 만한 ES5 문법이 없는 경우에 ES5 방식으로 별도로 구현하는 것을 의미한다.
useBuiltIns는 "entry", "usage", false의 값을 가질 수 있고, "entry"나 "usage"로 지정해야 폴리필이 가능.
"entry"는 따로 import도 해줘야 하고, 사용법이 조금 복잡해보여 그냥 보편적인 "usage"를 사용했다.
core-js는 폴리필에 사용되는 core-js의 버전을 의미하는데, version 2는 이제 더 이상 업데이트 되지 않는다고 하고, version 3도 어느 정도 안정기에 접어들었다고 판단하여 version 3를 사용하였다.
default 버전은 version 2이다.
참고로 폴리필을 사용하기 위해선 core-js도 따로 설치를 해줘야 한다.
npm install core-js@3 --save
🎓 ESLint & Prettier 세팅하기
다음은 ESLint와 Prettier를 설정해 줄 차례이다.
ESLint와 Prettier를 함께 사용할 때는 옵션이 충돌할 수 있기 때문에 추가적으로 설치해줘야 할 것들이 있다.
npm install --save-dev eslint prettier eslint-config-prettier eslint-plugin-prettier eslint-plugin-react
ESLint는 자바스크립트 코드를 포맷팅, 즉 더 가독성 좋게 만들어주는 역할도 하고
작성한 코드에 숨어있는 잠재적인 오류나 버그를 경고해주는 역할도 한다.
예를 들면 전역 변수를 사용하지 않게끔 감시한다거나, 사용하지 않는 변수가 있다면 경고해주는 식이다.
Prettier는 코드 포맷팅에 좀 더 집중한 도구이다.
코드 포맷팅 부분에 있어서 ESLint보다 품질이 좋기 때문에(가독성이 더 좋기 때문에)
보통 코드 품질 검사는 ESLint를 사용하고, 코드 포맷팅용으로는 Prettier를 더 선호하는 추세이다.
이 둘을 함께 사용하면 위에서 언급했듯이 충돌이 발생하는데, 이런 경우를 대비해
Prettier에서는 ESLint와 함께 사용할 수 있게끔 추가적인 도구들을 제공하고 있다.
그 중 eslint-config-prettier는 Prettier와 충돌하는 ESLint의 규칙을 비활성화하는 역할을 하고,
eslint-plugin-prettier는 Prettier의 규칙을 ESLint의 규칙으로 통합해주는 역할을 한다.
Prettier가 ESLint로 통합되기 때문에 ESLint만 실행해주면 된다는 장점이 있다.
이러한 것들을 설정해주기 위해, .eslintrc 파일을 작성해보자.
■ .eslintrc
{
"env": {
"browser": true,
"es2020": true,
"node": true
},
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"plugin:prettier/recommended"
],
"settings": {
"react": {
"version": "latest"
}
},
"parser": "babel-eslint",
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"ignorePatterns": ["dist/", "node_modules/"],
"plugins": ["react", "prettier"],
"rules": {
"prettier/prettier": "error"
}
}
■ env
env는 사전 정의된 전역 변수의 사용을 정의한다.
예를 들면, browser를 true로 하지 않으면 console.log를 사용할 수 없거나
node를 true로 하지 않으면 require를 사용할 수 없는 식이다.
■ plugins
plugins는 서드 파티 플러그인을 추가해주는 역할을 한다. 물론 플러그인 패키지를 설치해줘야 한다.
여기서는 eslint-plugin-prettier와 eslint-plugin-react를 설치해줬기 때문에 둘을 배열 안에 적어줬다.
위에서도 볼 수 있듯이, 앞의 'eslint-plugin-'은 생략이 가능하다.
■ extends
extends는 plugins에서 추가한 플러그인에서 사용할 규칙들을 설정한다.
참고로 플러그인(plugin)은 일련의 규칙의 집합이며, 플러그인만 추가해준다고 해서 규칙이 적용되는 게 아니다.
규칙을 적용하기 위해서는 plugins에 추가한 플러그인들 중에서 어떤 규칙을 사용할지를 직접 추가해줘야 한다.
그리고 그 규칙을 추가해주는 곳이 바로 이 extends이다.
eslint:recommended 는 ESLint에서 제공하는 기본 규칙 집합이다.
eslint:recommended 외에도 airbnb, google, standard 등 여러 가지 선택지가 존재한다.
plugin:react/recommended 는 이름에서도 알 수 있듯이 react를 사용할 때 필요한 기본 규칙을 설정한다.
plugin:prettier/recommended 는 eslint와 prettier를 함께 사용하기 위한 설정이다.
■ rules
ESLint에 적용되는 규칙들을 수정할 수 있다.
규칙들은 다음과 같이 설정할 수 있다.
- 0 또는 "off": 규칙을 사용하지 않음.
- 1 또는 "warn": 규칙을 사용하되, 경고만 띄운다.
- 2 또는 "error": 규칙을 사용하고, 에러를 띄운다.
만약 해당 규칙에 이 설정 외에 설정할 것들이 존재하면, 배열 리터럴로 설정을 추가해주면 된다.
{
"rules": {
"eqeqeq": "off",
"quotes": ["error", "double"]
}
}
위에 설정해 준 "prettier/prettier": "error"는 prettier의 규칙을 지키지 않을 경우 ESLint 에러를 띄우겠단 의미.
■ settings
settings는 모든 rule들에 적용되는 공통된 세팅을 의미한다.
여기서는 모든 규칙들이 react 최신 버전을 기준으로 적용된다는 의미.
참고로 이렇게 settings에 react의 버전을 명시해주지 않으면, 아래와 같은 에러가 발생하는 경우가 있다.
Warning: React version not specified in eslint-plugin-react settings.
■ parser
어떤 파서를 사용할지를 적어주면 된다.
ESLint가 구문 분석을 위해 기본으로 사용하는 파서는 Espree 파서.
Babel과 함께 사용하려면 babel-eslint를 사용해줘야 하며
Typescript의 구문 분석을 위해서는 @typescript-eslint/parser를 사용해주면 된다.
■ parserOptions
ESLint을 적용해 줄 자바스크립트의 언어 옵션을 지정할 수 있다.
- ecmaVersion: 사용할 ECMAScript의 버전을 설정
- sourceType: parser의 export 형태를 설정
- ecmaFeatures: 언어 확장 기능을 설정. 여기서는 JSX를 사용할 수 있게 하겠단 뜻.
■ ignorePatterns
언뜻 봐도 알 수 있듯이, ESLint를 적용하지 않을 파일 혹은 폴더들을 배열로 나열해주면 된다.
사용한 Prettier의 옵션들에 관해서도 간략히 설명을 하려고 했지만, 생각보다 글이 너무 길어져서 생략.
어차피 공식 문서에 상세히 설명되어 있으니깐.
📚 스토리북(Storybook) 세팅하기
리액트 하면 또 컴포넌트 주도 개발을 빼놓을 수가 없다. (물론 내 생각)
이를 위해서 컴포넌트 주도 개발의 대명사격인 스토리북을 설치해보자.
스토리북은 UI 컴포넌트와 페이지 등을 각각 독립적으로 개발할 수 있게 해주는 툴이다.
컴포넌트 마크업만 해놓으면 props를 모킹해서 해당 컴포넌트가 뷰에 어떻게 반영되는지 바로바로 볼 수 있다.
가끔 스토리북과 실제 페이지에서 보이는 뷰가 살짝 다른 경우가 있다는 점은 비밀.
스토리북을 Webpack5와 함께 이용하기 위해서는 다음의 CLI 명령어로 설치를 해줘야 한다.
npx sb init --builder webpack5
그리고 스토리북을 scss와 함께 사용하기 위한 프리셋도 설치해주자.
npm install --save-dev @storybook/preset-scss
스토리북을 설치하면 .storybook 폴더가 생성될텐데, 그 안에 있는 main.js 파일에 다음과 같이 작성해주면 된다.
■ main.js
module.exports = {
stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
addons: [
'@storybook/preset-scss',
],
core: {
builder: 'webpack5',
},
};
addons에 우리가 설치한 애드온을 추가해주고, 현재 빌더로 웹팩을 사용하고 있는 상황이므로
core의 builder에 'webpack5'를 적어주면 된다.
스토리북 파일은 보통 *.stories.js 의 파일명을 가지는데,
걔네들을 찾아내서 스토리북을 적용하겠다는 규칙을 stories에 언급해주면 된다.
참고로 CRA를 사용하지 않고 이렇게 웹팩 환경을 직접 구성해서 스토리북을 통합해주면
'Cannot GET /' 문제가 발생하는 경우가 종종 있다.
스토리북을 실행하고 스토리북 페이지를 열었는데,
'Cannot GET /'이라는 문자열만 화면에 보이고 아무것도 뜨지 않는 현상이다.
스토리북은 보통 실행에 캐시를 활용한다.
Cannot GET 에러는 이 캐싱 기능에 문제가 생겨서 발생하는 에러라고 한다.
그래서 이러한 상황에서 스토리북을 정상적으로 실행하기 위해서는,
'Manager caching mechanism' 을 비활성화시키고 다시 실행시켜야한다.
해결법은 다음과 같다.
1. node_modules 폴더를 삭제한다.
2. npm install을 통해 node_modules를 재설치한다.
3. 스토리북을 --no-manager-cache 옵션과 함께 실행한다.
npm run storybook --no-manager-cache
가장 많이 도움이 된 글.
김정환 개발자님의 '프론트엔드 개발환경의 이해' 시리즈.
'빌드 및 배포' 카테고리의 다른 글
Reverse Proxy를 거치기전의 IP를 WAS에서 알아내기 (0) | 2021.10.03 |
---|---|
프론트엔드 배포 일지 (0) | 2021.08.24 |
프론트 배포를 위한 잡다한 사전 지식 (2) | 2021.08.23 |
React S3, CloudFront에 배포하기 (0) | 2021.08.19 |
댓글