์ฌ๋ฐ๋ฅธ ๋๊ตฌ์ ์๋ํ ๊ธฐ์ ๋ก ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ ์ํฌํ๋ก์ฐ๋ฅผ ์ต์ ํํ์ธ์. ํจ์จ์ ์ด๊ณ ์ ๋ขฐํ ์ ์๋ ์ฝ๋๋ฅผ ์ํด ๋ฆฐํฐ, ํฌ๋งทํฐ, ๋ฒ๋ค๋ฌ, ํ์คํฌ ๋ฌ๋, ํ ์คํธ ํ๋ ์์ํฌ์ ๋ํด ์์๋ณด์ธ์.
์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ ์ํฌํ๋ก์ฐ: ํด๋ง ์ค์ ๋ฐ ์๋ํ
์ค๋๋ ๋น ๋ฅด๊ฒ ๋ณํํ๋ ์ํํธ์จ์ด ๊ฐ๋ฐ ํ๊ฒฝ์์ ์ ์ ์๋๊ณ ์๋ํ๋ ์ํฌํ๋ก์ฐ๋ ๊ณ ํ์ง ์๋ฐ์คํฌ๋ฆฝํธ ์ ํ๋ฆฌ์ผ์ด์ ์ ํจ์จ์ ์ผ๋ก ๊ตฌ์ถํ๋ ๋ฐ ๋งค์ฐ ์ค์ํฉ๋๋ค. ๊ฐ์ํ๋ ์ํฌํ๋ก์ฐ๋ ๊ฐ๋ฐ์ ์์ฐ์ฑ์ ํฅ์์ํฌ ๋ฟ๋ง ์๋๋ผ ์ฝ๋ ์ผ๊ด์ฑ์ ๋ณด์ฅํ๊ณ , ์ค๋ฅ๋ฅผ ์ค์ด๋ฉฐ, ํ ๋ด ํ์ ์ ๋จ์ํํฉ๋๋ค. ์ด ๊ฐ์ด๋์์๋ ์ฝ๋ ๋ฆฐํ ๋ฐ ํฌ๋งทํ ๋ถํฐ ํ ์คํธ ๋ฐ ๋ฐฐํฌ์ ์ด๋ฅด๊ธฐ๊น์ง ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ ํ๋ก์ธ์ค๋ฅผ ์ต์ ํํ๊ธฐ ์ํ ํ์ ๋๊ตฌ์ ์๋ํ ๊ธฐ์ ์ ์ดํด๋ด ๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ ์ํฌํ๋ก์ฐ๋ฅผ ์ต์ ํํด์ผ ํ๋ ์ด์
๊ฒฌ๊ณ ํ ๊ฐ๋ฐ ์ํฌํ๋ก์ฐ๋ฅผ ์ค์ ํ๋ ๋ฐ ์๊ฐ์ ํฌ์ํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ์๋ง์ ์ด์ ์ ์ป์ ์ ์์ต๋๋ค:
- ์์ฐ์ฑ ํฅ์: ๋ฐ๋ณต์ ์ธ ์์ ์ ์๋ํํ์ฌ ๊ฐ๋ฐ์๊ฐ ์ฝ๋ ์์ฑ ๋ฐ ๋ณต์กํ ๋ฌธ์ ํด๊ฒฐ์ ์ง์คํ ์ ์๋๋ก ํฉ๋๋ค.
- ์ฝ๋ ํ์ง ๊ฐ์ : ๋ฆฐํฐ์ ํฌ๋งทํฐ๊ฐ ์ฝ๋ฉ ํ์ค์ ๊ฐ์ ํ์ฌ ๋ ์ผ๊ด์ฑ ์๊ณ ์ ์ง๋ณด์ํ๊ธฐ ์ฌ์ด ์ฝ๋๋ฅผ ๋ง๋ญ๋๋ค.
- ์ค๋ฅ ๊ฐ์: ์ ์ ๋ถ์ ๋ฐ ํ ์คํธ๋ฅผ ํตํด ์ ์ฌ์ ์ธ ๋ฌธ์ ๋ฅผ ์กฐ๊ธฐ์ ๋ฐ๊ฒฌํ์ฌ ํ๋ก๋์ ํ๊ฒฝ์ ๋ฒ๊ทธ๋ฅผ ์ต์ํํฉ๋๋ค.
- ํ์ ๋จ์ํ: ์ผ๊ด๋ ์ฝ๋ฉ ์คํ์ผ๊ณผ ์๋ํ๋ ํ ์คํธ๋ ํ์ ๊ฐ์ ์ํํ ํ์ ์ ์ด์งํฉ๋๋ค.
- ์์ฅ ์ถ์ ์๊ฐ ๋จ์ถ: ๊ฐ์ํ๋ ํ๋ก์ธ์ค๋ ๊ฐ๋ฐ ์๋ช ์ฃผ๊ธฐ๋ฅผ ๊ฐ์ํํ์ฌ ๋ ๋น ๋ฅธ ๋ฆด๋ฆฌ์ค์ ๋ฐ๋ณต์ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค.
ํ๋์ ์ธ ์๋ฐ์คํฌ๋ฆฝํธ ์ํฌํ๋ก์ฐ๋ฅผ ์ํ ํ์ ๋๊ตฌ
ํ๋์ ์ธ ์๋ฐ์คํฌ๋ฆฝํธ ์ํฌํ๋ก์ฐ๋ ์ผ๋ฐ์ ์ผ๋ก ๋ฆฐํ , ํฌ๋งทํ , ๋ฒ๋ค๋ง, ํ์คํฌ ๋ฌ๋, ํ ์คํธ๋ฅผ ์ํ ๋๊ตฌ๋ค์ ์กฐํฉ์ ํฌํจํฉ๋๋ค. ๊ฐ์ฅ ์ธ๊ธฐ ์๊ณ ํจ๊ณผ์ ์ธ ๋ช ๊ฐ์ง ์ต์ ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค:
1. ESLint๋ฅผ ์ฌ์ฉํ ์ฝ๋ ๋ฆฐํ
ESLint๋ ์ ์ฌ์ ์ธ ์ค๋ฅ, ์คํ์ผ ๋ฌธ์ , ์ฝ๋ฉ ํ์ค ์ค์ ์ฌ๋ถ๋ฅผ ๋ถ์ํ๋ ๊ฐ๋ ฅํ๊ณ ๊ตฌ์ฑ ๊ฐ๋ฅํ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฆฐํฐ์ ๋๋ค. ๋ง์ ์ผ๋ฐ์ ์ธ ๋ฌธ์ ๋ฅผ ์๋์ผ๋ก ์์ ํ์ฌ ์ฝ๋๋ฅผ ๋ ๊นจ๋ํ๊ณ ์ผ๊ด์ฑ ์๊ฒ ๋ง๋ค์ด ์ค๋๋ค.
ESLint ์ค์ ํ๊ธฐ
ESLint๋ฅผ ๊ฐ๋ฐ ์์กด์ฑ(development dependency)์ผ๋ก ์ค์นํฉ๋๋ค:
npm install --save-dev eslint
ํ๋ก์ ํธ ๋ฃจํธ์ .eslintrc.js
๋๋ .eslintrc.json
ํ์ผ์ ์์ฑํ์ฌ ESLint๋ฅผ ๊ตฌ์ฑํฉ๋๋ค. eslint:recommended
์ ๊ฐ์ ๊ธฐ์กด ๊ตฌ์ฑ์ ํ์ฅํ๊ฑฐ๋ Airbnb ๋๋ Google๊ณผ ๊ฐ์ ์ธ๊ธฐ ์๋ ์คํ์ผ ๊ฐ์ด๋๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
// .eslintrc.js
module.exports = {
"extends": "eslint:recommended",
"env": {
"node": true,
"browser": true,
"es6": true
},
"rules": {
"no-console": "warn",
"indent": ["error", 2]
}
};
์ด ๊ตฌ์ฑ์ ๊ถ์ฅ ESLint ๊ท์น์ ํ์ฅํ๊ณ , Node.js ๋ฐ ๋ธ๋ผ์ฐ์ ํ๊ฒฝ์ ํ์ฑํํ๋ฉฐ, ๋ค์ฌ์ฐ๊ธฐ ๊ท์น์ 2์นธ์ผ๋ก ์ค์ ํฉ๋๋ค. no-console
๊ท์น์ `console.log` ๋ฌธ์ด ์ฌ์ฉ๋ ๋ ๊ฒฝ๊ณ ๋ฅผ ํ์ํฉ๋๋ค.
์ํฌํ๋ก์ฐ์ ESLint ํตํฉํ๊ธฐ
๋ช ๋ น์ค์์ ESLint๋ฅผ ์คํํ๊ฑฐ๋ ์ค์๊ฐ ํผ๋๋ฐฑ์ ์ํด ์๋ํฐ๋ IDE์ ํตํฉํ ์ ์์ต๋๋ค. ๋๋ถ๋ถ์ ์ธ๊ธฐ ์๋ ์๋ํฐ์๋ ์ฝ๋์์ ์ง์ ์ค๋ฅ์ ๊ฒฝ๊ณ ๋ฅผ ๊ฐ์กฐ ํ์ํ๋ ESLint ํ๋ฌ๊ทธ์ธ์ด ์์ต๋๋ค.
package.json
์ ESLint ์คํฌ๋ฆฝํธ๋ฅผ ์ถ๊ฐํฉ๋๋ค:
{
"scripts": {
"lint": "eslint ."
}
}
์ด์ npm run lint
๋ฅผ ์คํํ์ฌ ์ ์ฒด ํ๋ก์ ํธ์ ๋ฆฐํ
์ค๋ฅ๋ฅผ ๋ถ์ํ ์ ์์ต๋๋ค.
2. Prettier๋ฅผ ์ฌ์ฉํ ์ฝ๋ ํฌ๋งทํ
Prettier๋ ์ผ๊ด๋ ์คํ์ผ์ ๋ฐ๋ผ ์ฝ๋๋ฅผ ์๋์ผ๋ก ํฌ๋งทํ ํ๋ ๋ ๋จ์ ์ธ(opinionated) ์ฝ๋ ํฌ๋งทํฐ์ ๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ, ํ์ ์คํฌ๋ฆฝํธ, JSX, CSS ๋ฐ ๊ธฐํ ์ธ์ด๋ฅผ ์ง์ํฉ๋๋ค. Prettier๋ ์ ์ฒด ์ฝ๋๋ฒ ์ด์ค์ ์ผ๊ด๋ ํ์์ ์ ์ฉํ์ฌ ์ฝ๋ ์คํ์ผ์ ๋ํ ๋ ผ์์ ์์ ์ค๋๋ค.
Prettier ์ค์ ํ๊ธฐ
Prettier๋ฅผ ๊ฐ๋ฐ ์์กด์ฑ์ผ๋ก ์ค์นํฉ๋๋ค:
npm install --save-dev prettier
.prettierrc.js
๋๋ .prettierrc.json
ํ์ผ์ ์์ฑํ์ฌ Prettier์ ๋์์ ์ฌ์ฉ์ ์ ์ํฉ๋๋ค(์ ํ ์ฌํญ). ๊ตฌ์ฑ ํ์ผ์ด ์ ๊ณต๋์ง ์์ผ๋ฉด Prettier๋ ๊ธฐ๋ณธ ์ค์ ์ ์ฌ์ฉํฉ๋๋ค.
// .prettierrc.js
module.exports = {
semi: false,
singleQuote: true,
trailingComma: "all",
printWidth: 100
};
์ด ๊ตฌ์ฑ์ ์ธ๋ฏธ์ฝ๋ก ์ ๋นํ์ฑํํ๊ณ , ์์๋ฐ์ดํ๋ฅผ ์ฌ์ฉํ๋ฉฐ, ๊ฐ๋ฅํ ๊ฒฝ์ฐ ํํ ์ผํ๋ฅผ ์ถ๊ฐํ๊ณ , ์ถ๋ ฅ ๋๋น๋ฅผ 100์๋ก ์ค์ ํฉ๋๋ค.
์ํฌํ๋ก์ฐ์ Prettier ํตํฉํ๊ธฐ
ESLint์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ช ๋ น์ค์์ Prettier๋ฅผ ์คํํ๊ฑฐ๋ ์๋ํฐ ๋๋ IDE์ ํตํฉํ ์ ์์ต๋๋ค. ๋ง์ ์๋ํฐ์๋ ์ ์ฅ ์ ์ฝ๋๋ฅผ ์๋์ผ๋ก ํฌ๋งทํ ํ๋ Prettier ํ๋ฌ๊ทธ์ธ์ด ์์ต๋๋ค.
package.json
์ Prettier ์คํฌ๋ฆฝํธ๋ฅผ ์ถ๊ฐํฉ๋๋ค:
{
"scripts": {
"format": "prettier --write ."
}
}
์ด์ npm run format
์ ์คํํ์ฌ Prettier๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ฒด ํ๋ก์ ํธ๋ฅผ ์๋์ผ๋ก ํฌ๋งทํ
ํ ์ ์์ต๋๋ค.
ESLint์ Prettier ๊ฒฐํฉํ๊ธฐ
ESLint์ Prettier๋ ํจ๊ป ์ํํ๊ฒ ์๋ํ์ฌ ์ฝ๋ฉ ํ์ค์ ์ ์ฉํ๊ณ ์ฝ๋๋ฅผ ์๋์ผ๋ก ํฌ๋งทํ
ํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ ๋๊ตฌ ๋ชจ๋ ๋์ผํ ๊ท์น ์ค ์ผ๋ถ๋ฅผ ์ฒ๋ฆฌํ ์ ์์ผ๋ฏ๋ก ๋๋๋ก ์ถฉ๋ํ ์ ์์ต๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด Prettier์ ์ถฉ๋ํ ์ ์๋ ๋ชจ๋ ESLint ๊ท์น์ ๋นํ์ฑํํ๋ eslint-config-prettier
ํจํค์ง๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
ํ์ํ ํจํค์ง๋ฅผ ์ค์นํฉ๋๋ค:
npm install --save-dev eslint-config-prettier eslint-plugin-prettier
.eslintrc.js
ํ์ผ์ ์
๋ฐ์ดํธํ์ฌ eslint-config-prettier
๋ฅผ ํ์ฅํ๊ณ eslint-plugin-prettier
ํ๋ฌ๊ทธ์ธ์ ์ถ๊ฐํฉ๋๋ค:
// .eslintrc.js
module.exports = {
"extends": ["eslint:recommended", "prettier"],
"plugins": ["prettier"],
"env": {
"node": true,
"browser": true,
"es6": true
},
"rules": {
"no-console": "warn",
"indent": ["error", 2],
"prettier/prettier": "error"
}
};
์ด ๊ตฌ์ฑ์ ์ฌ์ฉํ๋ฉด ์ด์ ESLint๊ฐ Prettier๋ฅผ ์ฌ์ฉํ์ฌ ์ฝ๋๋ฅผ ํฌ๋งทํ ํ๊ณ ๋ชจ๋ ํฌ๋งทํ ๋ฌธ์ ๋ ESLint ์ค๋ฅ๋ก ๋ณด๊ณ ๋ฉ๋๋ค.
3. Webpack, Parcel, ๋๋ Rollup์ ์ฌ์ฉํ ๋ชจ๋ ๋ฒ๋ค๋ง
๋ชจ๋ ๋ฒ๋ค๋ฌ๋ ํ๋ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ์ ํ์์ ์ธ ๋๊ตฌ์ ๋๋ค. ๋ชจ๋ ์๋ฐ์คํฌ๋ฆฝํธ ๋ชจ๋๊ณผ ๊ทธ ์์กด์ฑ์ ๊ฐ์ ธ์ ๋ธ๋ผ์ฐ์ ๋ ์๋ฒ์ ์ฝ๊ฒ ๋ฐฐํฌํ ์ ์๋ ํ๋ ์ด์์ ํ์ผ๋ก ๋ฌถ์ด์ค๋๋ค. ๋ฒ๋ค๋ฌ๋ ์ฝ๋ ๋ถํ , ํธ๋ฆฌ ์์ดํน, ์ ์ ์ต์ ํ์ ๊ฐ์ ๊ธฐ๋ฅ๋ ์ ๊ณตํฉ๋๋ค.
Webpack
Webpack์ ๊ตฌ์ฑ ๊ฐ๋ฅ์ฑ์ด ๋๊ณ ๋ค์ฌ๋ค๋ฅํ ๋ชจ๋ ๋ฒ๋ค๋ฌ์ ๋๋ค. ๋ค์ํ ๋ก๋์ ํ๋ฌ๊ทธ์ธ์ ์ง์ํ์ฌ ํน์ ์๊ตฌ์ ๋ง๊ฒ ๋ฒ๋ค๋ง ํ๋ก์ธ์ค๋ฅผ ์ฌ์ฉ์ ์ ์ํ ์ ์์ต๋๋ค. Webpack์ ๊ณ ๊ธ ์๊ตฌ ์ฌํญ์ด ์๋ ๋ณต์กํ ํ๋ก์ ํธ์ ์์ฃผ ์ฌ์ฉ๋ฉ๋๋ค.
Parcel
Parcel์ ๊ฐ๋จํ๊ณ ์ง๊ด์ ์ธ ๊ฐ๋ฐ ๊ฒฝํ์ ์ ๊ณตํ๋ ๊ฒ์ ๋ชฉํ๋ก ํ๋ ์ ๋ก ๊ตฌ์ฑ(zero-configuration) ๋ชจ๋ ๋ฒ๋ค๋ฌ์ ๋๋ค. ํ๋ก์ ํธ์ ์์กด์ฑ๊ณผ ๊ตฌ์ฑ์ ์๋์ผ๋ก ๊ฐ์งํ๋ฏ๋ก ๋ณต์กํ ๊ตฌ์ฑ ํ์ผ์ ์์ฑํ์ง ์๊ณ ๋ ์ฝ๊ฒ ์์ํ ์ ์์ต๋๋ค. Parcel์ ์๊ท๋ชจ ํ๋ก์ ํธ๋ ๋น ๋ฅด๊ณ ์ฌ์ด ๋ฒ๋ค๋ง ์๋ฃจ์ ์ ์ํ ๋ ์ข์ ์ ํ์ ๋๋ค.
Rollup
Rollup์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํ๋ ์์ํฌ๋ฅผ ์ํ ์๊ณ ํจ์จ์ ์ธ ๋ฒ๋ค์ ๋ง๋๋ ๋ฐ ์ค์ ์ ๋ ๋ชจ๋ ๋ฒ๋ค๋ฌ์ ๋๋ค. ์ฌ์ฉํ์ง ์๋ ์ฝ๋๋ฅผ ๋ฒ๋ค์์ ์ ๊ฑฐํ์ฌ ํ์ผ ํฌ๊ธฐ๋ฅผ ์ค์ด๋ ํธ๋ฆฌ ์์ดํน์ ํ์ํฉ๋๋ค. Rollup์ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ปดํฌ๋ํธ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋น๋ํ๋ ๋ฐ ์์ฃผ ์ฌ์ฉ๋ฉ๋๋ค.
์์: Webpack ์ค์ ํ๊ธฐ
Webpack๊ณผ Webpack CLI๋ฅผ ๊ฐ๋ฐ ์์กด์ฑ์ผ๋ก ์ค์นํฉ๋๋ค:
npm install --save-dev webpack webpack-cli
ํ๋ก์ ํธ ๋ฃจํธ์ webpack.config.js
ํ์ผ์ ์์ฑํ์ฌ Webpack์ ๊ตฌ์ฑํฉ๋๋ค:
// webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
],
},
};
์ด ๊ตฌ์ฑ์ Webpack์ src/index.js
ํ์ผ์ ๋ฒ๋ค๋งํ๊ณ ๊ฒฐ๊ณผ๋ฅผ dist/bundle.js
๋ก ์ถ๋ ฅํ๋๋ก ์ง์ํฉ๋๋ค. ๋ํ Babel ๋ก๋๋ฅผ ์ฌ์ฉํ์ฌ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๋ฅผ ํธ๋์คํ์ผํฉ๋๋ค.
package.json
์ Webpack ์คํฌ๋ฆฝํธ๋ฅผ ์ถ๊ฐํฉ๋๋ค:
{
"scripts": {
"build": "webpack"
}
}
์ด์ npm run build
๋ฅผ ์คํํ์ฌ Webpack์ ์ฌ์ฉํ์ฌ ํ๋ก์ ํธ๋ฅผ ๋ฒ๋ค๋งํ ์ ์์ต๋๋ค.
4. npm Scripts, Gulp, ๋๋ Grunt๋ฅผ ์ฌ์ฉํ ํ์คํฌ ๋ฌ๋
ํ์คํฌ ๋ฌ๋๋ ์ ํ๋ฆฌ์ผ์ด์ ๋น๋, ํ ์คํธ, ๋ฐฐํฌ์ ๊ฐ์ ๋ฐ๋ณต์ ์ธ ์์ ์ ์๋ํํฉ๋๋ค. ์ผ๋ จ์ ์์ ์ ์ ์ํ๊ณ ๋จ์ผ ๋ช ๋ น์ผ๋ก ์คํํ ์ ์์ต๋๋ค.
npm Scripts
npm ์คํฌ๋ฆฝํธ๋ package.json
ํ์ผ์์ ์ง์ ์์
์ ์ ์ํ๊ณ ์คํํ๋ ๊ฐ๋จํ๊ณ ํธ๋ฆฌํ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. Gulp๋ Grunt์ ๊ฐ์ ๋ ๋ณต์กํ ํ์คํฌ ๋ฌ๋์ ๋ํ ๊ฒฝ๋ ๋์์
๋๋ค.
Gulp
Gulp๋ Node.js๋ฅผ ์ฌ์ฉํ์ฌ ์์ ์ ์๋ํํ๋ ์คํธ๋ฆฌ๋ฐ ๋น๋ ์์คํ ์ ๋๋ค. ์์ ์ ์ผ๋ จ์ ํ์ดํ๋ก ์ ์ํ ์ ์์ผ๋ฉฐ, ๊ฐ ํ์ดํ๋ ํ์ผ์ ๋ํด ํน์ ์์ ์ ์ํํฉ๋๋ค. Gulp๋ ๋ค์ํ ์์ ์ด ์๋ ๋ณต์กํ ํ๋ก์ ํธ์ ๋๋ฆฌ ์ฌ์ฉ๋ฉ๋๋ค.
Grunt
Grunt๋ ๋ ๋ค๋ฅธ ์ธ๊ธฐ ์๋ ์๋ฐ์คํฌ๋ฆฝํธ ํ์คํฌ ๋ฌ๋์
๋๋ค. Gruntfile.js
ํ์ผ์ ์์
์ ์ ์ํ๋ ๊ตฌ์ฑ ๊ธฐ๋ฐ ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํฉ๋๋ค. Grunt๋ ๋ค์ํ ์์
์ ์ํํ๋ ๋ฐ ์ฌ์ฉํ ์ ์๋ ํฐ ํ๋ฌ๊ทธ์ธ ์ํ๊ณ๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค.
์์: npm Scripts ์ฌ์ฉํ๊ธฐ
package.json
ํ์ผ์ scripts
์น์
์์ ์ง์ ์์
์ ์ ์ํ ์ ์์ต๋๋ค:
{
"scripts": {
"lint": "eslint .",
"format": "prettier --write .",
"build": "webpack",
"test": "jest",
"deploy": "npm run build && firebase deploy"
}
}
์ด์ npm run lint
, npm run format
, npm run build
, npm run test
, ๋๋ npm run deploy
๋ฅผ ์คํํ์ฌ ํด๋น ์์
์ ์คํํ ์ ์์ต๋๋ค.
5. Jest, Mocha, ๋๋ Cypress๋ฅผ ์ฌ์ฉํ ํ ์คํธ ํ๋ ์์ํฌ
ํ ์คํธ๋ ๋ชจ๋ ์ํํธ์จ์ด ๊ฐ๋ฐ ์ํฌํ๋ก์ฐ์ ํ์์ ์ธ ๋ถ๋ถ์ ๋๋ค. ํ ์คํธ ํ๋ ์์ํฌ๋ ์๋ํ๋ ํ ์คํธ๋ฅผ ์์ฑํ๊ณ ์คํํ๊ธฐ ์ํ ๋๊ตฌ์ API๋ฅผ ์ ๊ณตํ์ฌ ์ฝ๋๊ฐ ์์๋๋ก ์๋ํ๋์ง ํ์ธํ๊ณ ํ๊ท(regression)๋ฅผ ๋ฐฉ์งํฉ๋๋ค.
Jest
Jest๋ ํ์ด์ค๋ถ์์ ๊ฐ๋ฐํ ์ ๋ก ๊ตฌ์ฑ ํ ์คํธ ํ๋ ์์ํฌ์ ๋๋ค. ํ ์คํธ ๋ฌ๋, ๋จ์ธ(assertion) ๋ผ์ด๋ธ๋ฌ๋ฆฌ, ๋ชจ์(mocking) ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํฌํจํ์ฌ ํ ์คํธ๋ฅผ ์์ฑํ๊ณ ์คํํ๋ ๋ฐ ํ์ํ ๋ชจ๋ ๊ฒ์ ์ ๊ณตํฉ๋๋ค. Jest๋ React ์ ํ๋ฆฌ์ผ์ด์ ์ ๋๋ฆฌ ์ฌ์ฉ๋ฉ๋๋ค.
Mocha
Mocha๋ ๋ค์ํ ๋จ์ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ชจ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ง์ํ๋ ์ ์ฐํ๊ณ ํ์ฅ ๊ฐ๋ฅํ ํ ์คํธ ํ๋ ์์ํฌ์ ๋๋ค. ํ์์ ๊ฐ์ฅ ์ ํฉํ ๋๊ตฌ๋ฅผ ์ ํํ ์ ์์ต๋๋ค. Mocha๋ Node.js ์ ํ๋ฆฌ์ผ์ด์ ํ ์คํธ์ ์์ฃผ ์ฌ์ฉ๋ฉ๋๋ค.
Cypress
Cypress๋ ์ ํ๋ฆฌ์ผ์ด์ ๊ณผ์ ์ฌ์ฉ์ ์ํธ ์์ฉ์ ์๋ฎฌ๋ ์ด์ ํ๋ ํ ์คํธ๋ฅผ ์์ฑํ๊ณ ์คํํ ์ ์๋ ์๋ ํฌ ์๋(end-to-end) ํ ์คํธ ํ๋ ์์ํฌ์ ๋๋ค. ์ฝ๊ณ ์ ์ง ๊ด๋ฆฌํ๊ธฐ ์ฌ์ด ํ ์คํธ๋ฅผ ์์ฑํ๊ธฐ ์ํ ๊ฐ๋ ฅํ๊ณ ์ง๊ด์ ์ธ API๋ฅผ ์ ๊ณตํฉ๋๋ค. Cypress๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ํ ์คํธ์ ๋๋ฆฌ ์ฌ์ฉ๋ฉ๋๋ค.
์์: Jest ์ค์ ํ๊ธฐ
Jest๋ฅผ ๊ฐ๋ฐ ์์กด์ฑ์ผ๋ก ์ค์นํฉ๋๋ค:
npm install --save-dev jest
ํ๋ก์ ํธ ๋ฃจํธ์ jest.config.js
ํ์ผ์ ์์ฑํ์ฌ Jest๋ฅผ ๊ตฌ์ฑํฉ๋๋ค(์ ํ ์ฌํญ). ๊ตฌ์ฑ ํ์ผ์ด ์ ๊ณต๋์ง ์์ผ๋ฉด Jest๋ ๊ธฐ๋ณธ ์ค์ ์ ์ฌ์ฉํฉ๋๋ค.
// jest.config.js
module.exports = {
testEnvironment: 'node',
};
์ด ๊ตฌ์ฑ์ Jest์ Node.js ํ ์คํธ ํ๊ฒฝ์ ์ฌ์ฉํ๋๋ก ์ง์ํฉ๋๋ค.
package.json
์ Jest ์คํฌ๋ฆฝํธ๋ฅผ ์ถ๊ฐํฉ๋๋ค:
{
"scripts": {
"test": "jest"
}
}
์ด์ npm run test
๋ฅผ ์คํํ์ฌ Jest๋ฅผ ์ฌ์ฉํ์ฌ ํ
์คํธ๋ฅผ ์คํํ ์ ์์ต๋๋ค.
์ง์์ ํตํฉ(CI/CD)์ผ๋ก ์ํฌํ๋ก์ฐ ์๋ํํ๊ธฐ
์ง์์ ํตํฉ(CI) ๋ฐ ์ง์์ ์ ๋ฌ/๋ฐฐํฌ(CD)๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋น๋, ํ ์คํธ, ๋ฐฐํฌ ํ๋ก์ธ์ค๋ฅผ ์๋ํํ๋ ๊ดํ์ ๋๋ค. CI/CD ํ์ดํ๋ผ์ธ์ ์ฝ๋ ๋ณ๊ฒฝ์ ์ํด ํธ๋ฆฌ๊ฑฐ๋ ์ ์์ผ๋ฉฐ, ์ด๋ฅผ ํตํด ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ค์ํ ํ๊ฒฝ์ ์๋์ผ๋ก ํ ์คํธํ๊ณ ๋ฐฐํฌํ ์ ์์ต๋๋ค.
์ธ๊ธฐ ์๋ CI/CD ํ๋ซํผ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- GitHub Actions: GitHub์ ์ง์ ํตํฉ๋ CI/CD ํ๋ซํผ์ ๋๋ค.
- GitLab CI/CD: GitLab์ ํตํฉ๋ CI/CD ํ๋ซํผ์ ๋๋ค.
- Jenkins: CI/CD์ ์ฌ์ฉํ ์ ์๋ ์คํ ์์ค ์๋ํ ์๋ฒ์ ๋๋ค.
- Travis CI: ํด๋ผ์ฐ๋ ๊ธฐ๋ฐ CI/CD ํ๋ซํผ์ ๋๋ค.
- CircleCI: ํด๋ผ์ฐ๋ ๊ธฐ๋ฐ CI/CD ํ๋ซํผ์ ๋๋ค.
์์: GitHub Actions ์ค์ ํ๊ธฐ
ํ๋ก์ ํธ ์ ์ฅ์์ .github/workflows/main.yml
ํ์ผ์ ์์ฑํ์ฌ GitHub Actions ์ํฌํ๋ก์ฐ๋ฅผ ์ ์ํฉ๋๋ค:
# .github/workflows/main.yml
name: CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js 16
uses: actions/setup-node@v2
with:
node-version: '16.x'
- name: Install Dependencies
run: npm install
- name: Run Lint
run: npm run lint
- name: Run Tests
run: npm run test
- name: Build
run: npm run build
- name: Deploy
if: github.ref == 'refs/heads/main'
run: |
echo "Deploying to production..."
# Add deployment commands here
echo "Deployment complete!"
์ด ์ํฌํ๋ก์ฐ๋ main
๋ธ๋์น์ ๋ํ ๋ชจ๋ ํธ์์ main
๋ธ๋์น๋ฅผ ๋์์ผ๋ก ํ๋ ๋ชจ๋ ํ ๋ฆฌํ์คํธ์์ ํธ๋ฆฌ๊ฑฐ๋ฉ๋๋ค. ์์กด์ฑ์ ์ค์นํ๊ณ , ๋ฆฐํ
์ ์คํํ๊ณ , ํ
์คํธ๋ฅผ ์คํํ๊ณ , ์ ํ๋ฆฌ์ผ์ด์
์ ๋น๋ํ ํ ํ๋ก๋์
์ ๋ฐฐํฌํฉ๋๋ค(๋ณ๊ฒฝ ์ฌํญ์ด main
๋ธ๋์น์ ์๋ ๊ฒฝ์ฐ).
์ฑ๊ณต์ ์ธ ์๋ฐ์คํฌ๋ฆฝํธ ์ํฌํ๋ก์ฐ๋ฅผ ์ํ ๋ชจ๋ฒ ์ฌ๋ก
- ์ฝ๋ฉ ํ์ค ์๋ฆฝ: ํ์ ์ํ ๋ช ํํ ์ฝ๋ฉ ํ์ค์ ์ ์ํ๊ณ ๋ฆฐํฐ์ ํฌ๋งทํฐ๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฅผ ๊ฐ์ ํฉ๋๋ค. ์ด๋ ์ฝ๋์ ์ผ๊ด์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ ๋ณด์ฅํฉ๋๋ค. ์๋ฅผ ๋ค์ด Airbnb ์๋ฐ์คํฌ๋ฆฝํธ ์คํ์ผ ๊ฐ์ด๋, Google ์๋ฐ์คํฌ๋ฆฝํธ ์คํ์ผ ๊ฐ์ด๋๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ ํ์ ํ์์ ๋ง๋ ๋ง์ถคํ ์คํ์ผ ๊ฐ์ด๋๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
- ๋ชจ๋ ๊ฒ์ ์๋ํ: ์ ํ๋ฆฌ์ผ์ด์ ๋น๋, ํ ์คํธ, ๋ฐฐํฌ์ ๊ฐ์ ๋ฐ๋ณต์ ์ธ ์์ ์ ์๋ํํฉ๋๋ค. ์ด๋ ์๊ฐ์ ์ ์ฝํ๊ณ ์ธ์ ์ค๋ฅ์ ์ํ์ ์ค์ ๋๋ค. ์ด๋ฌํ ์๋ํ๋ npm ์คํฌ๋ฆฝํธ, Gulp์ ๊ฐ์ ์ ์ฉ ํ์คํฌ ๋ฌ๋ ๋๋ CI/CD ํ์ดํ๋ผ์ธ์ ํตํด ์ด๋ฃจ์ด์ง ์ ์์ต๋๋ค.
- ๋จ์ ํ ์คํธ ์์ฑ: ์ฝ๋๊ฐ ์์๋๋ก ์๋ํ๋์ง ํ์ธํ๊ธฐ ์ํด ๋จ์ ํ ์คํธ๋ฅผ ์์ฑํฉ๋๋ค. ์ด๋ ํ๊ท๋ฅผ ๋ฐฉ์งํ๊ณ ์ฝ๋ ๋ฆฌํฉํ ๋ง์ ๋ ์ฝ๊ฒ ๋ง๋ญ๋๋ค. ๋์ ํ ์คํธ ์ปค๋ฒ๋ฆฌ์ง๋ฅผ ๋ชฉํ๋ก ํ๊ณ ํ ์คํธ๋ฅผ ์ ์ง ๊ด๋ฆฌํ๊ธฐ ์ฝ๊ฒ ๋ง๋์ธ์.
- ๋ฒ์ ๊ด๋ฆฌ ์ฌ์ฉ: ๋ฒ์ ๊ด๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ฝ๋ ๋ณ๊ฒฝ ์ฌํญ์ ์ถ์ ํฉ๋๋ค. ์ด๋ ๋ค๋ฅธ ๊ฐ๋ฐ์์์ ํ์ ๋ฐ ํ์ํ ๊ฒฝ์ฐ ์ด์ ๋ฒ์ ์ ์ฝ๋๋ก ๋๋๋ฆฌ๊ธฐ๋ฅผ ๋ ์ฝ๊ฒ ๋ง๋ญ๋๋ค. Git์ ๊ฐ์ฅ ๋๋ฆฌ ์ฌ์ฉ๋๋ ๋ฒ์ ๊ด๋ฆฌ ์์คํ ์ ๋๋ค.
- ์ฝ๋ ๋ฆฌ๋ทฐ: ์ ๊ธฐ์ ์ธ ์ฝ๋ ๋ฆฌ๋ทฐ๋ฅผ ์ํํ์ฌ ์ ์ฌ์ ์ธ ๋ฌธ์ ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ์ฝ๋๊ฐ ์ฝ๋ฉ ํ์ค์ ์ถฉ์กฑํ๋์ง ํ์ธํฉ๋๋ค. ๋๋ฃ ๋ฆฌ๋ทฐ๋ ์ฝ๋ ํ์ง์ ์ ์งํ๋ ๋ฐ ์ค์ํ ๋ถ๋ถ์ ๋๋ค.
- ์ง์์ ์ธ ๊ฐ์ : ๊ฐ๋ฐ ์ํฌํ๋ก์ฐ๋ฅผ ์ง์์ ์ผ๋ก ํ๊ฐํ๊ณ ๊ฐ์ ํฉ๋๋ค. ํ๋ก์ธ์ค๋ฅผ ๊ฐ์ํํ๊ณ ์๋ก์ด ๋๊ตฌ์ ๊ธฐ์ ์ ์ฑํํ ์ ์๋ ์์ญ์ ์๋ณํฉ๋๋ค. ์ ๊ธฐ์ ์ผ๋ก ํ์๋ค์ ํผ๋๋ฐฑ์ ์๋ ดํ์ฌ ๋ณ๋ชฉ ํ์๊ณผ ๊ฐ์ ์์ญ์ ํ์ ํฉ๋๋ค.
- ๋ฒ๋ค ์ต์ ํ: ์ฝ๋ ๋ถํ ๋ฐ ํธ๋ฆฌ ์์ดํน ๊ธฐ์ ์ ์ฌ์ฉํ์ฌ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฒ๋ค์ ํฌ๊ธฐ๋ฅผ ์ค์ ๋๋ค. ๋ ์์ ๋ฒ๋ค์ ๋ ๋นจ๋ฆฌ ๋ก๋๋์ด ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฑ๋ฅ์ ํฅ์์ํต๋๋ค. Webpack ๋ฐ Parcel๊ณผ ๊ฐ์ ๋๊ตฌ๋ ์ด๋ฌํ ์ต์ ํ๋ฅผ ์๋ํํ ์ ์์ต๋๋ค.
- ์ฑ๋ฅ ๋ชจ๋ํฐ๋ง: ํ๋ก๋์ ํ๊ฒฝ์์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฑ๋ฅ์ ๋ชจ๋ํฐ๋งํฉ๋๋ค. ์ด๋ ์ฑ๋ฅ ๋ณ๋ชฉ ํ์์ ์๋ณํ๊ณ ์์ ํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค. ์น์ฌ์ดํธ ์ฑ๋ฅ์ ๋ชจ๋ํฐ๋งํ๊ธฐ ์ํด Google PageSpeed Insights, WebPageTest ๋๋ New Relic๊ณผ ๊ฐ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ณ ๋ คํ์ธ์.
- ์ผ๊ด๋ ํ๊ฒฝ ์ฌ์ฉ: Docker ๋๋ ๊ฐ์ ๋จธ์ ๊ณผ ๊ฐ์ ๋๊ตฌ๋ฅผ ํ์ฉํ์ฌ ํ์ ๊ฐ์ ์ผ๊ด๋ ๊ฐ๋ฐ ํ๊ฒฝ์ ๋ณด์ฅํฉ๋๋ค. ์ผ๊ด๋ ํ๊ฒฝ์ "๋ด ์ปดํจํฐ์์๋ ๋๋๋ฐ" ๋ฌธ์ ๋ฅผ ํผํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
๊ฒฐ๋ก
์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ ์ํฌํ๋ก์ฐ๋ฅผ ์ต์ ํํ๋ ๊ฒ์ ์ ์คํ ๊ณํ๊ณผ ์คํ์ด ํ์ํ ์ง์์ ์ธ ํ๋ก์ธ์ค์ ๋๋ค. ์ฌ๋ฐ๋ฅธ ๋๊ตฌ์ ์๋ํ ๊ธฐ์ ์ ์ฑํํจ์ผ๋ก์จ ๊ฐ๋ฐ์ ์์ฐ์ฑ, ์ฝ๋ ํ์ง, ์์ฅ ์ถ์ ์๊ฐ์ ํฌ๊ฒ ํฅ์์ํฌ ์ ์์ต๋๋ค. ๋์์์ด ์งํํ๋ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ ์ธ๊ณ์์ ์์ ๋๊ฐ๊ธฐ ์ํด ์ํฌํ๋ก์ฐ๋ฅผ ์ง์์ ์ผ๋ก ํ๊ฐํ๊ณ ๊ฐ์ ํ๋ ๊ฒ์ ์์ง ๋ง์ญ์์ค.
์์ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๋ ๋๊ท๋ชจ ์ํฐํ๋ผ์ด์ฆ ์์คํ ์ ๊ตฌ์ถํ๋ , ์ ์ ์๋๊ณ ์๋ํ๋ ์๋ฐ์คํฌ๋ฆฝํธ ์ํฌํ๋ก์ฐ๋ ์ฑ๊ณต์ ํ์์ ์ ๋๋ค. ์ด ๊ฐ์ด๋์์ ๋ ผ์๋ ๋๊ตฌ์ ๊ธฐ์ ์ ๋ฐ์๋ค์ด๋ฉด ๊ณ ํ์ง์ ์ ๋ขฐํ ์ ์๊ณ ์ ์ง๋ณด์ ๊ฐ๋ฅํ ์๋ฐ์คํฌ๋ฆฝํธ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๋ ๊ธธ์ ๋ค์ด์๊ฒ ๋ ๊ฒ์ ๋๋ค.