๋ฆฐํ , ํฌ๋งทํ , ํ ์คํธ, ์ ์ ๋ถ์ ๋ฐ ์ง์์ ํตํฉ์ ๋ค๋ฃจ๋ฉฐ, ๊ธ๋ก๋ฒ ํ์ ์ํ ๊ฒฌ๊ณ ํ JavaScript ํ์ง ์ธํ๋ผ ๊ตฌ์ถ์ ๋ํ ํฌ๊ด์ ์ธ ๊ฐ์ด๋์ ๋๋ค.
JavaScript ํ์ง ์ธํ๋ผ: ์๋ฒฝํ ๊ตฌํ ๊ฐ์ด๋
๋์์์ด ์งํํ๋ ์น ๊ฐ๋ฐ ํ๊ฒฝ์์ JavaScript๋ ์ฌ์ ํ ํต์ฌ ๊ธฐ์ ์ ๋๋ค. ํ๋ก์ ํธ์ ๋ณต์ก์ฑ์ด ์ฆ๊ฐํ๊ณ ํ์ด ์ ์ธ๊ณ์ ์ผ๋ก ๋ถ์ฐ๋จ์ ๋ฐ๋ผ ์ฝ๋ ํ์ง์ ๋ณด์ฅํ๋ ๊ฒ์ด ๋ฌด์๋ณด๋ค ์ค์ํด์ก์ต๋๋ค. ์ ์ ์๋๊ณ ๊ตฌํ๋ JavaScript ํ์ง ์ธํ๋ผ๋ ๋ ์ด์ ์ฌ์น๊ฐ ์๋, ์ ๋ขฐํ ์ ์๊ณ ์ ์ง๋ณด์ ๊ฐ๋ฅํ๋ฉฐ ํ์ฅ ๊ฐ๋ฅํ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๊ธฐ ์ํ ํ์ ์์์ ๋๋ค. ์ด ํฌ๊ด์ ์ธ ๊ฐ์ด๋๋ ๊ตญ์ ์ ์ธ ํ๊ณผ ๋ค์ํ ๊ฐ๋ฐ ํ๊ฒฝ์ ๋ง์ถฐ JavaScript ํ๋ก์ ํธ๋ฅผ ์ํ ๊ฒฌ๊ณ ํ ํ์ง ์ธํ๋ผ๋ฅผ ๊ตฌ์ถํ๋ ๋จ๊ณ๋ณ ์ ๊ทผ ๋ฐฉ์์ ์ ๊ณตํฉ๋๋ค.
JavaScript ํ์ง ์ธํ๋ผ์ ํฌ์ํด์ผ ํ๋ ์ด์
๊ฒฌ๊ณ ํ ํ์ง ์ธํ๋ผ์ ํฌ์ํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ์๋ง์ ์ด์ ์ ์ป์ ์ ์์ต๋๋ค:
- ํฅ์๋ ์ฝ๋ ์ผ๊ด์ฑ: ์ ์ฒด ์ฝ๋๋ฒ ์ด์ค์ ์ผ๊ด๋ ์ฝ๋ฉ ์คํ์ผ์ ์ ์ฉํ์ฌ ๊ฐ๋ฐ์๊ฐ ์ฝ๋๋ฅผ ๋ ์ฝ๊ฒ ์ดํดํ๊ณ ์ ์ง๋ณด์ํ ์ ์๋๋ก ํฉ๋๋ค. ํ์ ๋ชจ๋ ๊ตฌ์ฑ์์ด ์ ์ฐฝํ๊ฒ ๊ตฌ์ฌํ๋ ๊ณต์ฉ์ด๋ฅผ ํ๋ฆฝํ๋ ๊ฒ๊ณผ ๊ฐ์ต๋๋ค.
- ์ค๋ฅ ๋ฐ ๋ฒ๊ทธ ๊ฐ์: ๊ฐ๋ฐ ์ฃผ๊ธฐ ์ด๊ธฐ์ ์ ์ฌ์ ์ค๋ฅ๋ฅผ ์๋ณํ์ฌ ํ๋ก๋์ ํ๊ฒฝ์ ๋๋ฌํ๋ ๊ฒ์ ๋ฐฉ์งํฉ๋๋ค. ์ด๋ ๋ฌธ์๊ฐ ์ถํ๋๊ธฐ ์ ์ ๊ต์ ์๊ฐ ์ค์๋ฅผ ์ก์๋ด๋ ๊ฒ๊ณผ ๊ฐ์ต๋๋ค.
- ์์ฐ์ฑ ํฅ์: ํฌ๋งทํ ๋ฐ ๋ฆฐํ ๊ณผ ๊ฐ์ ๋ฐ๋ณต์ ์ธ ์์ ์ ์๋ํํ์ฌ ๊ฐ๋ฐ์๊ฐ ๋ ๋ณต์กํ ๋ฌธ์ ํด๊ฒฐ์ ์ง์คํ ์ ์๋๋ก ํฉ๋๋ค. ์์ฐ์ ๊ฐ์ํํ๋ ์๋ํ๋ ์กฐ๋ฆฝ ๋ผ์ธ์ ์์ํด ๋ณด์ญ์์ค.
- ํ์ ๊ฐํ: ์ฝ๋ ๋ฆฌ๋ทฐ์ ํ ๋ก ์ ์ํ ๊ณตํต ๊ธฐ๋ฐ์ ์ ๊ณตํ์ฌ ๋ง์ฐฐ์ ์ค์ด๊ณ ํ ํ์ ์ ๊ฐ์ ํฉ๋๋ค. ํนํ ๋ถ์ฐ๋ ํ์์ ํจ๊ณผ์ ์ ๋๋ค.
- ๋จ์ํ๋ ์ ์ง๋ณด์: ์ฝ๋ ๋ฆฌํฉํ ๋ง ๋ฐ ์ ๋ฐ์ดํธ๋ฅผ ๋ ์ฝ๊ฒ ๋ง๋ค์ด ์๋ก์ด ๋ฒ๊ทธ ๋ฐ์ ์ํ์ ์ค์ ๋๋ค. ์ ์ ๋ฆฌ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ํ์ํ๊ณ ์ ์ง๋ณด์ํ๊ธฐ๊ฐ ๋ ์ฝ์ต๋๋ค.
- ๊ธฐ์ ๋ถ์ฑ ๊ฐ์: ์ ์ฌ์ ์ธ ๋ฌธ์ ๋ฅผ ์ฌ์ ์ ํด๊ฒฐํ์ฌ ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ๊ธฐ์ ๋ถ์ฑ๊ฐ ์ถ์ ๋๋ ๊ฒ์ ๋ฐฉ์งํฉ๋๋ค. ์กฐ๊ธฐ ์ ์ง๋ณด์๋ ๋์ค์ ๋ฐ์ํ ์ ์๋ ๊ฐ๋น์ผ ์๋ฆฌ๋ฅผ ์๋ฐฉํฉ๋๋ค.
๊ธ๋ก๋ฒ ํ์ ๊ฒฝ์ฐ, ์ด๋ฌํ ์ด์ ์ ๋์ฑ ์ฆํญ๋ฉ๋๋ค. ํ์คํ๋ ์ฝ๋ฉ ๊ดํ์ ๋ฌธํ์ , ์ธ์ด์ ์ฐจ์ด๋ฅผ ํด์ํ์ฌ ๋ ์ํํ ํ์ ๊ณผ ์ง์ ๊ณต์ ๋ฅผ ์ด์งํฉ๋๋ค. ๋ถ๋ฏธ, ์ ๋ฝ, ์์์์ ๊ฑธ์ณ ์๋ ํ์ ์๊ฐํด ๋ณด์ญ์์ค. ๊ณต์ ๋ ํ์ง ์ธํ๋ผ๋ ์์น๋ ๋ฐฐ๊ฒฝ์ ๊ด๊ณ์์ด ๋ชจ๋ ๊ตฌ์ฑ์์ด ๋์ผํ ์ดํด๋ฅผ ๊ฐ๋๋ก ๋ณด์ฅํฉ๋๋ค.
JavaScript ํ์ง ์ธํ๋ผ์ ์ฃผ์ ๊ตฌ์ฑ ์์
ํฌ๊ด์ ์ธ JavaScript ํ์ง ์ธํ๋ผ๋ ์ฝ๋ ํ์ง์ ๋ณด์ฅํ๋ ๋ฐ ๊ฐ๊ฐ ์ค์ํ ์ญํ ์ ํ๋ ์ฌ๋ฌ ์ฃผ์ ๊ตฌ์ฑ ์์๋ฅผ ํฌํจํฉ๋๋ค:
- ๋ฆฐํ (Linting): ์คํ์ผ ์ค๋ฅ, ์ ์ฌ์ ๋ฒ๊ทธ ๋ฐ ์ฝ๋ฉ ํ์ค ์ค์ ์ฌ๋ถ๋ฅผ ๋ถ์ํฉ๋๋ค.
- ํฌ๋งทํ (Formatting): ์ฝ๋์ ์ผ๊ด์ฑ๊ณผ ๊ฐ๋ ์ฑ์ ๋ณด์ฅํ๊ธฐ ์ํด ์ฝ๋๋ฅผ ์๋์ผ๋ก ํฌ๋งทํ ํฉ๋๋ค.
- ํ ์คํ (Testing): ์ฝ๋์ ๊ธฐ๋ฅ์ฑ์ ๊ฒ์ฆํ๊ธฐ ์ํด ํ ์คํธ๋ฅผ ์์ฑํ๊ณ ์คํํฉ๋๋ค.
- ์ ์ ๋ถ์(Static Analysis): ์ฝ๋๋ฅผ ์คํํ์ง ์๊ณ ์ ์ฌ์ ์ธ ๋ณด์ ์ทจ์ฝ์ ๋ฐ ์ฑ๋ฅ ๋ฌธ์ ๋ฅผ ๋ถ์ํฉ๋๋ค.
- ์ง์์ ํตํฉ(CI): ๋น๋, ํ ์คํธ ๋ฐ ๋ฐฐํฌ ํ๋ก์ธ์ค๋ฅผ ์๋ํํฉ๋๋ค.
1. ESLint๋ฅผ ์ฌ์ฉํ ๋ฆฐํ
ESLint๋ ๊ฐ๋ ฅํ๊ณ ์ค์ ์ด ๋งค์ฐ ์ ์ฐํ JavaScript ๋ฆฐํฐ์ ๋๋ค. ์ฝ๋์ ์คํ์ผ ์ค๋ฅ, ์ ์ฌ์ ๋ฒ๊ทธ, ์ฝ๋ฉ ํ์ค ์ค์ ์ฌ๋ถ๋ฅผ ๋ถ์ํฉ๋๋ค. ESLint๋ ๋ค์ํ ๊ท์น๊ณผ ํ๋ฌ๊ทธ์ธ์ ์ง์ํ์ฌ ํน์ ์๊ตฌ์ ๋ง๊ฒ ์ฌ์ฉ์ ์ ์ํ ์ ์์ต๋๋ค.
์ค์น ๋ฐ ๊ตฌ์ฑ
ESLint๋ฅผ ์ค์นํ๋ ค๋ฉด ๋ค์ ๋ช ๋ น์ ์คํํ์ญ์์ค:
npm install eslint --save-dev
๋ค์์ผ๋ก, ํ๋ก์ ํธ์ ๋ฃจํธ์ ESLint ๊ตฌ์ฑ ํ์ผ(.eslintrc.js, .eslintrc.yml ๋๋ .eslintrc.json)์ ์์ฑํฉ๋๋ค. eslint --init ๋ช
๋ น์ ์ฌ์ฉํ์ฌ ๊ธฐ๋ณธ์ ์ธ ๊ตฌ์ฑ ํ์ผ์ ์์ฑํ ์ ์์ต๋๋ค.
eslint --init
๊ตฌ์ฑ ํ์ผ์ ESLint๊ฐ ์ ์ฉํ ๊ท์น์ ์ง์ ํฉ๋๋ค. ๋ค์ํ ๋ด์ฅ ๊ท์น ์ค์์ ์ ํํ๊ฑฐ๋, ํ์ฌ ํ๋ฌ๊ทธ์ธ์ ์ฌ์ฉํ์ฌ ESLint์ ๊ธฐ๋ฅ์ ํ์ฅํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, eslint-plugin-react ํ๋ฌ๊ทธ์ธ์ ์ฌ์ฉํ์ฌ React ๊ด๋ จ ์ฝ๋ฉ ํ์ค์ ์ ์ฉํ ์ ์์ต๋๋ค. ๋ง์ ์กฐ์ง์์๋ ์ฌ๋ฌ ํ๋ก์ ํธ์์ ์ผ๊ด๋ ์คํ์ผ์ ์ ์งํ๊ธฐ ์ํด ๊ณต์ ๊ฐ๋ฅํ ESLint ๊ตฌ์ฑ์ ๋ง๋ค๊ธฐ๋ ํฉ๋๋ค. AirBnB, Google, StandardJS๋ ๋๋ฆฌ ์ฌ์ฉ๋๋ ์ค์ ์ ์์
๋๋ค. ๊ฒฐ์ ์ ๋ด๋ฆด ๋ ํ์ ํ์ฌ ์คํ์ผ๊ณผ ์ ์ฌ์ ์ธ ํํ์ ์ ๊ณ ๋ คํ์ญ์์ค.
๋ค์์ ๊ฐ๋จํ .eslintrc.js ๊ตฌ์ฑ ํ์ผ์ ์์
๋๋ค:
module.exports = {
env: {
browser: true,
es2021: true,
node: true,
},
extends: [
'eslint:recommended',
'plugin:react/recommended',
],
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 12,
sourceType: 'module',
},
plugins: [
'react',
],
rules: {
'no-unused-vars': 'warn',
'no-console': 'warn',
'react/prop-types': 'off',
},
};
์ด ๊ตฌ์ฑ์ ๊ถ์ฅ ESLint ๊ท์น์ ํ์ฅํ๊ณ , React ์ง์์ ํ์ฑํํ๋ฉฐ, ๋ช ๊ฐ์ง ์ฌ์ฉ์ ์ ์ ๊ท์น์ ์ ์ํฉ๋๋ค. no-unused-vars ๊ท์น์ ์ฌ์ฉ๋์ง ์๋ ๋ณ์์ ๋ํด ๊ฒฝ๊ณ ํ๊ณ , no-console ๊ท์น์ console.log ๋ฌธ์ ๋ํด ๊ฒฝ๊ณ ํฉ๋๋ค. react/prop-types ๊ท์น์ ํ์
๊ฒ์ฌ๋ฅผ ๋ค๋ฅด๊ฒ ์ฒ๋ฆฌํ๋ TypeScript์ ํจ๊ป ์์ฃผ ์ฌ์ฉ๋๊ธฐ ๋๋ฌธ์ ๋นํ์ฑํ๋์์ต๋๋ค.
ESLint๋ฅผ ์ํฌํ๋ก์ฐ์ ํตํฉํ๊ธฐ
๋ค์๊ณผ ๊ฐ์ ์ฌ๋ฌ ๋ฐฉ๋ฒ์ผ๋ก ESLint๋ฅผ ์ํฌํ๋ก์ฐ์ ํตํฉํ ์ ์์ต๋๋ค:
- ๋ช
๋ น์ค:
eslint๋ช ๋ น์ ์ฌ์ฉํ์ฌ ๋ช ๋ น์ค์์ ESLint๋ฅผ ์คํํฉ๋๋ค. - ์๋ํฐ ํตํฉ: ์ฌ์ฉ ์ค์ธ ์ฝ๋ ์๋ํฐ(์: VS Code, Sublime Text, Atom)์ ESLint ํ๋ฌ๊ทธ์ธ์ ์ค์นํฉ๋๋ค.
- ์ง์์ ํตํฉ: CI ํ์ดํ๋ผ์ธ์ ESLint๋ฅผ ํตํฉํ์ฌ ๋ชจ๋ ์ปค๋ฐ์ ๋ํด ์ฝ๋๋ฅผ ์๋์ผ๋ก ๋ฆฐํ ํฉ๋๋ค.
๋ช ๋ น์ค์์ ESLint๋ฅผ ์คํํ๋ ค๋ฉด ๋ค์ ๋ช ๋ น์ ์ฌ์ฉํ์ญ์์ค:
eslint .
์ด ๋ช ๋ น์ ํ์ฌ ๋๋ ํ ๋ฆฌ์ ๊ทธ ํ์ ๋๋ ํ ๋ฆฌ์ ์๋ ๋ชจ๋ JavaScript ํ์ผ์ ๋ฆฐํ ํฉ๋๋ค.
2. Prettier๋ฅผ ์ฌ์ฉํ ํฌ๋งทํ
Prettier๋ ์ฝ๋์ ์ผ๊ด์ฑ๊ณผ ๊ฐ๋ ์ฑ์ ๋ณด์ฅํ๊ธฐ ์ํด ์ฝ๋๋ฅผ ์๋์ผ๋ก ํฌ๋งทํ ํ๋ ๋ ๋จ์ ์ธ(opinionated) ์ฝ๋ ํฌ๋งทํฐ์ ๋๋ค. ์ ์ฌ์ ์ค๋ฅ๋ฅผ ์๋ณํ๋ ๋ฐ ์ค์ ์ ๋๋ ๋ฆฐํฐ์ ๋ฌ๋ฆฌ, Prettier๋ ์ค์ง ์ฝ๋ ํฌ๋งทํ ์๋ง ์ง์คํฉ๋๋ค.
์ค์น ๋ฐ ๊ตฌ์ฑ
Prettier๋ฅผ ์ค์นํ๋ ค๋ฉด ๋ค์ ๋ช ๋ น์ ์คํํ์ญ์์ค:
npm install prettier --save-dev
๋ค์์ผ๋ก, ํ๋ก์ ํธ์ ๋ฃจํธ์ Prettier ๊ตฌ์ฑ ํ์ผ(.prettierrc.js, .prettierrc.yml ๋๋ .prettierrc.json)์ ์์ฑํฉ๋๋ค. ๊ธฐ๋ณธ ๊ตฌ์ฑ์ ์ฌ์ฉํ๊ฑฐ๋ ํน์ ์๊ตฌ์ ๋ง๊ฒ ์ฌ์ฉ์ ์ ์ํ ์ ์์ต๋๋ค.
๋ค์์ ๊ฐ๋จํ .prettierrc.js ๊ตฌ์ฑ ํ์ผ์ ์์
๋๋ค:
module.exports = {
semi: false,
trailingComma: 'all',
singleQuote: true,
printWidth: 120,
};
์ด ๊ตฌ์ฑ์ Prettier๊ฐ ์์๋ฐ์ดํ๋ฅผ ์ฌ์ฉํ๊ณ , ๋ชจ๋ ์ฌ๋ฌ ์ค ๊ตฌ์กฐ์ ํํ ์ผํ๋ฅผ ์ถ๊ฐํ๋ฉฐ, ์ธ๋ฏธ์ฝ๋ก ์ ํผํ๊ณ , ์ต๋ ์ค ๊ธธ์ด๋ฅผ 120์๋ก ์ค์ ํ๋๋ก ์ง์ ํฉ๋๋ค.
Prettier๋ฅผ ์ํฌํ๋ก์ฐ์ ํตํฉํ๊ธฐ
๋ค์๊ณผ ๊ฐ์ ์ฌ๋ฌ ๋ฐฉ๋ฒ์ผ๋ก Prettier๋ฅผ ์ํฌํ๋ก์ฐ์ ํตํฉํ ์ ์์ต๋๋ค:
- ๋ช
๋ น์ค:
prettier๋ช ๋ น์ ์ฌ์ฉํ์ฌ ๋ช ๋ น์ค์์ Prettier๋ฅผ ์คํํฉ๋๋ค. - ์๋ํฐ ํตํฉ: ์ฝ๋ ์๋ํฐ์ Prettier ํ๋ฌ๊ทธ์ธ์ ์ค์นํฉ๋๋ค.
- Git ํ (Hooks): Git ํ ์ ์ฌ์ฉํ์ฌ ์ปค๋ฐํ๊ธฐ ์ ์ ์ฝ๋๋ฅผ ์๋์ผ๋ก ํฌ๋งทํ ํฉ๋๋ค.
- ์ง์์ ํตํฉ: CI ํ์ดํ๋ผ์ธ์ Prettier๋ฅผ ํตํฉํ์ฌ ๋ชจ๋ ์ปค๋ฐ์ ๋ํด ์ฝ๋๋ฅผ ์๋์ผ๋ก ํฌ๋งทํ ํฉ๋๋ค.
๋ช ๋ น์ค์์ Prettier๋ฅผ ์คํํ๋ ค๋ฉด ๋ค์ ๋ช ๋ น์ ์ฌ์ฉํ์ญ์์ค:
prettier --write .
์ด ๋ช ๋ น์ ํ์ฌ ๋๋ ํ ๋ฆฌ์ ๊ทธ ํ์ ๋๋ ํ ๋ฆฌ์ ์๋ ๋ชจ๋ ํ์ผ์ ํฌ๋งทํ ํฉ๋๋ค.
ESLint์ Prettier ํตํฉํ๊ธฐ
ESLint์ Prettier๋ฅผ ํจ๊ป ์ฌ์ฉํ์ฌ ํฌ๊ด์ ์ธ ์ฝ๋ ํ์ง ์๋ฃจ์ ์ ์ ๊ณตํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ถฉ๋์ ํผํ๊ธฐ ์ํด ์ฌ๋ฐ๋ฅด๊ฒ ๊ตฌ์ฑํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ESLint๋ ํฌ๋งทํ ์ ํ์ธํ๋๋ก ๊ตฌ์ฑํ ์ ์๊ธฐ ๋๋ฌธ์ ESLint์ Prettier๋ ์ถฉ๋ํ ์ ์์ต๋๋ค.
ESLint์ Prettier๋ฅผ ํตํฉํ๋ ค๋ฉด ๋ค์ ํจํค์ง๋ฅผ ์ค์นํด์ผ ํฉ๋๋ค:
npm install eslint-config-prettier eslint-plugin-prettier --save-dev
eslint-config-prettier ํจํค์ง๋ Prettier์ ์ถฉ๋ํ๋ ๋ชจ๋ ESLint ๊ท์น์ ๋นํ์ฑํํฉ๋๋ค. eslint-plugin-prettier ํจํค์ง๋ Prettier๋ฅผ ESLint ๊ท์น์ผ๋ก ์คํํ ์ ์๊ฒ ํด์ค๋๋ค.
.eslintrc.js ๊ตฌ์ฑ ํ์ผ์ ์
๋ฐ์ดํธํ์ฌ ์ด๋ฌํ ํจํค์ง๋ฅผ ํฌํจ์ํค์ญ์์ค:
module.exports = {
// ...
extends: [
// ...
'prettier',
'plugin:prettier/recommended',
],
plugins: [
// ...
'prettier',
],
rules: {
// ...
'prettier/prettier': 'error',
},
};
์ด ๊ตฌ์ฑ์ prettier ๊ตฌ์ฑ์ ํ์ฅํ๊ณ , eslint-plugin-prettier ํ๋ฌ๊ทธ์ธ์ ํ์ฑํํ๋ฉฐ, prettier/prettier ๊ท์น์ ๊ตฌ์ฑํ์ฌ ๋ชจ๋ ํฌ๋งทํ
๋ฌธ์ ๋ฅผ ์ค๋ฅ๋ก ๋ณด๊ณ ํ๋๋ก ํฉ๋๋ค.
3. Jest, Mocha, Chai๋ฅผ ์ฌ์ฉํ ํ ์คํ
ํ ์คํ ์ ์ฝ๋ ํ์ง์ ๋ณด์ฅํ๋ ๋ฐ ์ค์ํ ์ธก๋ฉด์ ๋๋ค. JavaScript๋ ๊ฐ๊ฐ์ ๊ฐ์ ๊ณผ ์ฝ์ ์ ๊ฐ์ง ๋ค์ํ ํ ์คํ ํ๋ ์์ํฌ๋ฅผ ์ ๊ณตํฉ๋๋ค. ๊ฐ์ฅ ์ธ๊ธฐ ์๋ ํ ์คํ ํ๋ ์์ํฌ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- Jest: Facebook์์ ๊ฐ๋ฐํ ์ค์ ์ด ํ์ ์๋(zero-configuration) ํ ์คํ ํ๋ ์์ํฌ์ ๋๋ค. Jest๋ ์ฌ์ฉํ๊ธฐ ์ฝ๊ณ , ๋ด์ฅ๋ ๋ชจ์(mocking) ๊ธฐ๋ฅ๊ณผ ๋ฐ์ด๋ ์ฑ๋ฅ์ผ๋ก ์ ๋ช ํฉ๋๋ค.
- Mocha: ๋ค์ํ ๋จ์ธ(assertion) ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ฆฌํฌํฐ๋ฅผ ์ง์ํ๋ ์ ์ฐํ๊ณ ํ์ฅ ๊ฐ๋ฅํ ํ ์คํ ํ๋ ์์ํฌ์ ๋๋ค.
- Chai: Mocha๋ ๋ค๋ฅธ ํ ์คํ ํ๋ ์์ํฌ์ ํจ๊ป ์ฌ์ฉํ ์ ์๋ ๋จ์ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค. Chai๋ BDD(ํ๋ ์ฃผ๋ ๊ฐ๋ฐ) ๋ฐ TDD(ํ ์คํธ ์ฃผ๋ ๊ฐ๋ฐ)๋ฅผ ํฌํจํ ๋ค์ํ ๋จ์ธ ์คํ์ผ์ ์ ๊ณตํฉ๋๋ค.
์ฌ๋ฐ๋ฅธ ํ ์คํ ํ๋ ์์ํฌ๋ฅผ ์ ํํ๋ ๊ฒ์ ํน์ ์๊ตฌ์ฌํญ๊ณผ ์ ํธ๋์ ๋ฐ๋ผ ๋ค๋ฆ ๋๋ค. Jest๋ ์ค์ ์๋ ํ๊ฒฝ๊ณผ ๋ด์ฅ๋ ๋ชจ์ ๊ธฐ๋ฅ์ด ํ์ํ ํ๋ก์ ํธ์ ์ข์ ์ ํ์ ๋๋ค. Mocha์ Chai๋ ๋ ๋ง์ ์ ์ฐ์ฑ๊ณผ ์ฌ์ฉ์ ์ ์๊ฐ ํ์ํ ํ๋ก์ ํธ์ ์ข์ ์ ํ์ ๋๋ค.
Jest ์์
Jest๋ฅผ ์ฌ์ฉํ์ฌ ํ ์คํธํ๋ ๋ฐฉ๋ฒ์ ์์ฐํด ๋ณด๊ฒ ์ต๋๋ค. ๋จผ์ , Jest๋ฅผ ์ค์นํฉ๋๋ค:
npm install jest --save-dev
๊ทธ๋ฐ ๋ค์, ํ
์คํธํ๋ ค๋ ์ฝ๋(์: sum.js)์ ๋์ผํ ๋๋ ํ ๋ฆฌ์ ํ
์คํธ ํ์ผ(์: sum.test.js)์ ์์ฑํฉ๋๋ค.
๋ค์์ sum.js ํ์ผ์ ์์
๋๋ค:
function sum(a, b) {
return a + b;
}
module.exports = sum;
๊ทธ๋ฆฌ๊ณ ๋ค์์ sum.test.js ํ์ผ์ ์์
๋๋ค:
const sum = require('./sum');
describe('sum', () => {
it('should add two numbers correctly', () => {
expect(sum(1, 2)).toBe(3);
});
it('should handle negative numbers correctly', () => {
expect(sum(-1, 2)).toBe(1);
});
});
์ด ํ
์คํธ ํ์ผ์ sum ํจ์์ ๋ํ ๋ ๊ฐ์ ํ
์คํธ ์ผ์ด์ค๋ฅผ ์ ์ํฉ๋๋ค. ์ฒซ ๋ฒ์งธ ํ
์คํธ ์ผ์ด์ค๋ ํจ์๊ฐ ๋ ์์๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ๋ํ๋์ง ํ์ธํฉ๋๋ค. ๋ ๋ฒ์งธ ํ
์คํธ ์ผ์ด์ค๋ ํจ์๊ฐ ์์๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํ๋์ง ํ์ธํฉ๋๋ค.
ํ
์คํธ๋ฅผ ์คํํ๋ ค๋ฉด package.json ํ์ผ์ test ์คํฌ๋ฆฝํธ๋ฅผ ์ถ๊ฐํ์ญ์์ค:
{
// ...
"scripts": {
"test": "jest"
}
// ...
}
๊ทธ๋ฐ ๋ค์ ๋ค์ ๋ช ๋ น์ ์คํํ์ญ์์ค:
npm test
์ด ๋ช ๋ น์ ํ๋ก์ ํธ์ ๋ชจ๋ ํ ์คํธ ํ์ผ์ ์คํํฉ๋๋ค.
4. TypeScript์ Flow๋ฅผ ์ฌ์ฉํ ์ ์ ๋ถ์
์ ์ ๋ถ์์ ์ฝ๋๋ฅผ ์คํํ์ง ์๊ณ ์ ์ฌ์ ์ธ ์ค๋ฅ์ ์ทจ์ฝ์ ์ ๋ถ์ํ๋ ๊ฒ์ ํฌํจํฉ๋๋ค. ์ด๋ ์ ํต์ ์ธ ํ ์คํ ๋ฐฉ๋ฒ์ผ๋ก๋ ๊ฐ์งํ๊ธฐ ์ด๋ ค์ด ๋ฌธ์ ๋ฅผ ์๋ณํ๋ ๋ฐ ๋์์ด ๋ ์ ์์ต๋๋ค. JavaScript์ ์ ์ ๋ถ์์ ์ํ ๋ ๊ฐ์ง ์ธ๊ธฐ ์๋ ๋๊ตฌ๋ TypeScript์ Flow์ ๋๋ค.
TypeScript
TypeScript๋ ์ธ์ด์ ์ ์ ํ์ดํ์ ์ถ๊ฐํ๋ JavaScript์ ์์ ์งํฉ์ ๋๋ค. TypeScript๋ฅผ ์ฌ์ฉํ๋ฉด ๋ณ์, ํจ์ ๋ฐ ๊ฐ์ฒด์ ๋ํ ํ์ ์ ์ ์ํ ์ ์์ผ๋ฉฐ, ์ด๋ ๋ฐํ์์ ํ์ ๊ด๋ จ ์ค๋ฅ๋ฅผ ๋ฐฉ์งํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค. TypeScript๋ ์์ JavaScript๋ก ์ปดํ์ผ๋๋ฏ๋ก ๋ชจ๋ JavaScript ๋ฐํ์ ํ๊ฒฝ์์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
Flow
Flow๋ Facebook์์ ๊ฐ๋ฐํ JavaScript์ฉ ์ ์ ํ์ ๊ฒ์ฌ๊ธฐ์ ๋๋ค. Flow๋ ์ฝ๋์ ํ์ ๊ด๋ จ ์ค๋ฅ๋ฅผ ๋ถ์ํ๊ณ ๊ฐ๋ฐ์์๊ฒ ์ค์๊ฐ์ผ๋ก ํผ๋๋ฐฑ์ ์ ๊ณตํฉ๋๋ค. Flow๋ ๊ธฐ์กด JavaScript ์ฝ๋์ ํจ๊ป ์ฌ์ฉํ ์ ์์ผ๋ฏ๋ก ์ ์ฒด ์ฝ๋๋ฒ ์ด์ค๋ฅผ ๋ค์ ์์ฑํ ํ์๊ฐ ์์ต๋๋ค.
TypeScript์ Flow ์ค์์ ์ ํํ๋ ๊ฒ์ ํน์ ์๊ตฌ์ฌํญ๊ณผ ์ ํธ๋์ ๋ฐ๋ผ ๋ค๋ฆ ๋๋ค. TypeScript๋ ๊ฐ๋ ฅํ ์ ์ ํ์ดํ๊ณผ ๋ ๊ตฌ์กฐํ๋ ๊ฐ๋ฐ ํ๋ก์ธ์ค๊ฐ ํ์ํ ํ๋ก์ ํธ์ ์ข์ ์ ํ์ ๋๋ค. Flow๋ ์๊ฐ๊ณผ ๋ ธ๋ ฅ์ ํฌ๊ฒ ๋ค์ด์ง ์๊ณ ๊ธฐ์กด JavaScript ์ฝ๋์ ์ ์ ํ์ดํ์ ์ถ๊ฐํ๋ ค๋ ํ๋ก์ ํธ์ ์ข์ ์ ํ์ ๋๋ค.
TypeScript ์์
TypeScript๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ ๋ถ์์ ์ํํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ๋๋ฆฌ๊ฒ ์ต๋๋ค. ๋จผ์ TypeScript๋ฅผ ์ค์นํฉ๋๋ค:
npm install typescript --save-dev
๊ทธ๋ฐ ๋ค์ ํ๋ก์ ํธ ๋ฃจํธ์ TypeScript ๊ตฌ์ฑ ํ์ผ(tsconfig.json)์ ๋ง๋ญ๋๋ค.
๋ค์์ ๊ฐ๋จํ tsconfig.json ๊ตฌ์ฑ ํ์ผ์ ์์
๋๋ค:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}
์ด ๊ตฌ์ฑ์ TypeScript๊ฐ ES5๋ก ์ปดํ์ผํ๊ณ , CommonJS ๋ชจ๋ ์์คํ ์ ์ฌ์ฉํ๋ฉฐ, ์๊ฒฉํ ํ์ ๊ฒ์ฌ๋ฅผ ํ์ฑํํ๊ณ , ํ์ผ ์ด๋ฆ์ ์ผ๊ด๋ ๋์๋ฌธ์๋ฅผ ๊ฐ์ ํ๋๋ก ์ง์ ํฉ๋๋ค.
์ด์ TypeScript ์ฝ๋๋ฅผ ์์ฑํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ๊ฐ๋จํ TypeScript ํ์ผ(greeting.ts)์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
function greeting(name: string): string {
return `Hello, ${name}!`;
}
console.log(greeting("World"));
์ด ํ์ผ์ ๋ฌธ์์ด ์ธ์(name)๋ฅผ ๋ฐ์ ๋ฌธ์์ด์ ๋ฐํํ๋ greeting์ด๋ผ๋ ํจ์๋ฅผ ์ ์ํฉ๋๋ค. : string ์ด๋
ธํ
์ด์
์ ํจ์๊ฐ ๋ฌธ์์ด์ ๋ฐํํด์ผ ํจ์ ์ง์ ํฉ๋๋ค. ๋ค๋ฅธ ํ์
์ ๋ฐํํ๋ ค๊ณ ํ๋ฉด TypeScript๊ฐ ์ค๋ฅ๋ฅผ ๋ณด๊ณ ํฉ๋๋ค.
TypeScript ์ฝ๋๋ฅผ ์ปดํ์ผํ๋ ค๋ฉด ๋ค์ ๋ช ๋ น์ ์คํํ์ญ์์ค:
npx tsc
์ด ๋ช ๋ น์ ํ๋ก์ ํธ์ ๋ชจ๋ TypeScript ํ์ผ์ ์ปดํ์ผํ๊ณ ํด๋น JavaScript ํ์ผ์ ์์ฑํฉ๋๋ค.
5. GitHub Actions, GitLab CI, Jenkins๋ฅผ ์ฌ์ฉํ ์ง์์ ํตํฉ(CI)
์ง์์ ํตํฉ(CI)์ ๋น๋, ํ ์คํธ, ๋ฐฐํฌ ํ๋ก์ธ์ค๋ฅผ ์๋ํํ๋ ๊ฐ๋ฐ ๊ดํ์ ๋๋ค. CI๋ ๊ฐ๋ฐ ์ฃผ๊ธฐ ์ด๊ธฐ์ ๋ฌธ์ ๋ฅผ ์๋ณํ๊ณ ํด๊ฒฐํ์ฌ ํ๋ก๋์ ์ ๋ฒ๊ทธ๊ฐ ์ ์ ๋ ์ํ์ ์ค์ด๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค. ๋ค์๊ณผ ๊ฐ์ ์ฌ๋ฌ CI ํ๋ซํผ์ ์ฌ์ฉํ ์ ์์ต๋๋ค:
- GitHub Actions: GitHub์ ์ง์ ํตํฉ๋ CI/CD ํ๋ซํผ์ ๋๋ค. GitHub Actions๋ฅผ ์ฌ์ฉํ๋ฉด GitHub ์ ์ฅ์์์ ์ง์ ์ํฌํ๋ก์ฐ๋ฅผ ์๋ํํ ์ ์์ต๋๋ค.
- GitLab CI: GitLab์ ํตํฉ๋ CI/CD ํ๋ซํผ์ ๋๋ค. GitLab CI๋ฅผ ์ฌ์ฉํ๋ฉด GitLab ์ ์ฅ์์์ ์ง์ ์ํฌํ๋ก์ฐ๋ฅผ ์๋ํํ ์ ์์ต๋๋ค.
- Jenkins: ๋ค์ํ ๋ฒ์ ๊ด๋ฆฌ ์์คํ ๋ฐ ๋ฐฐํฌ ํ๋ซํผ๊ณผ ํจ๊ป ์ฌ์ฉํ ์ ์๋ ์คํ ์์ค CI/CD ์๋ฒ์ ๋๋ค. Jenkins๋ ๋์ ์์ค์ ์ ์ฐ์ฑ๊ณผ ์ฌ์ฉ์ ์ ์๋ฅผ ์ ๊ณตํฉ๋๋ค.
์ฌ๋ฐ๋ฅธ CI ํ๋ซํผ์ ์ ํํ๋ ๊ฒ์ ํน์ ์๊ตฌ์ฌํญ๊ณผ ์ ํธ๋์ ๋ฐ๋ผ ๋ค๋ฆ ๋๋ค. GitHub Actions์ GitLab CI๋ ๊ฐ๊ฐ GitHub ๋๋ GitLab์์ ํธ์คํ ๋๋ ํ๋ก์ ํธ์ ์ข์ ์ ํ์ ๋๋ค. Jenkins๋ ๋ ๋ง์ ์ ์ฐ์ฑ๊ณผ ์ฌ์ฉ์ ์ ์๊ฐ ํ์ํ ํ๋ก์ ํธ์ ์ข์ ์ ํ์ ๋๋ค.
GitHub Actions ์์
GitHub Actions๋ฅผ ์ฌ์ฉํ์ฌ CI๋ฅผ ์ํํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ๋๋ฆฌ๊ฒ ์ต๋๋ค. ๋จผ์ GitHub ์ ์ฅ์์ ์ํฌํ๋ก์ฐ ํ์ผ(์: .github/workflows/ci.yml)์ ๋ง๋ญ๋๋ค.
๋ค์์ ๊ฐ๋จํ .github/workflows/ci.yml ์ํฌํ๋ก์ฐ ํ์ผ์ ์์
๋๋ค:
name: CI
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 ESLint
run: npm run lint
- name: Run Prettier
run: npm run format
- name: Run tests
run: npm test
์ด ์ํฌํ๋ก์ฐ ํ์ผ์ main ๋ธ๋์น์ ๋ํ ๋ชจ๋ ํธ์์ main ๋ธ๋์น๋ฅผ ๋์์ผ๋ก ํ๋ ๋ชจ๋ ํ ๋ฆฌํ์คํธ์์ ์คํ๋ CI ํ์ดํ๋ผ์ธ์ ์ ์ํฉ๋๋ค. ํ์ดํ๋ผ์ธ์ ๋ค์ ๋จ๊ณ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค:
- ์ฝ๋ ์ฒดํฌ์์.
- Node.js ์ค์ .
- ์์กด์ฑ ์ค์น.
- ESLint ์คํ.
- Prettier ์คํ.
- ํ ์คํธ ์คํ.
CI ํ์ดํ๋ผ์ธ์ ํ์ฑํํ๋ ค๋ฉด ์ํฌํ๋ก์ฐ ํ์ผ์ GitHub ์ ์ฅ์์ ์ปค๋ฐํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค. GitHub Actions๋ ์ํฌํ๋ก์ฐ ํ์ผ์ ์๋์ผ๋ก ๊ฐ์งํ๊ณ ๋ชจ๋ ํธ์ ๋ฐ ํ ๋ฆฌํ์คํธ์์ ํ์ดํ๋ผ์ธ์ ์คํํฉ๋๋ค.
์ฝ๋ ๋ฆฌ๋ทฐ์ ํ์
์๋ํ๊ฐ ๊ธฐ๋ฐ์ ์ ๊ณตํ์ง๋ง, ์ฌ๋์ ๋ฆฌ๋ทฐ์ ํ์ ์ ์ฌ์ ํ ํ์ง ์ธํ๋ผ์ ์ค์ํ ๋ถ๋ถ์ ๋๋ค. ์ฝ๋ ๋ฆฌ๋ทฐ๋ ์๋ํ๋ ๋๊ตฌ๊ฐ ๋์น ์ ์๋ ๋ก์ง ์ค๋ฅ, ์ค๊ณ ๊ฒฐํจ ๋ฐ ์ ์ฌ์ ์ธ ๋ณด์ ์ทจ์ฝ์ ์ ๋ฐ๊ฒฌํฉ๋๋ค. ํ์ ๊ฐ์ ์ด๋ฆฐ ์ํต๊ณผ ๊ฑด์ค์ ์ธ ํผ๋๋ฐฑ์ ์ฅ๋ คํ์ญ์์ค. GitHub ํ ๋ฆฌํ์คํธ๋ GitLab ๋จธ์ง ๋ฆฌํ์คํธ์ ๊ฐ์ ๋๊ตฌ๋ ์ด ๊ณผ์ ์ ์ฉ์ดํ๊ฒ ํฉ๋๋ค. ๋น๋๋ณด๋ค๋ ์ฝ๋ ๊ฐ์ ์ ์ด์ ์ ๋ง์ถ ์กด์คํ๊ณ ๊ฐ๊ด์ ์ธ ๋นํ์ ๊ฐ์กฐํด์ผ ํฉ๋๋ค.
๊ธ๋ก๋ฒ ํ ๊ณ ๋ ค์ฌํญ
๊ธ๋ก๋ฒ ํ์ ์ํ JavaScript ํ์ง ์ธํ๋ผ๋ฅผ ๊ตฌํํ ๋ ๋ค์ ์์๋ค์ ๊ณ ๋ คํ์ญ์์ค:
- ์๊ฐ๋: ์ฑ๋ฅ ๋ณ๋ชฉ ํ์์ ํผํ๊ธฐ ์ํด CI ๋น๋์ ๊ฐ์ ์๋ํ๋ ์์ ์ ๋ค๋ฅธ ์๊ฐ๋์ ๋น-ํผํฌ ์๊ฐ์ ์คํ๋๋๋ก ์์ฝํฉ๋๋ค.
- ์ปค๋ฎค๋์ผ์ด์ : ์ฝ๋ ํ์ง ๋ฌธ์ ์ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ ผ์ํ๊ธฐ ์ํ ๋ช ํํ ์ปค๋ฎค๋์ผ์ด์ ์ฑ๋์ ๊ตฌ์ถํฉ๋๋ค. ํ์ ํ์์ ๊ณต์ ๋ฌธ์๋ ์ง๋ฆฌ์ ๊ฒฉ์ฐจ๋ฅผ ํด์ํ ์ ์์ต๋๋ค.
- ๋ฌธํ์ ์ฐจ์ด: ์ปค๋ฎค๋์ผ์ด์ ์คํ์ผ๊ณผ ํผ๋๋ฐฑ ์ ํธ๋์ ์์ด ๋ฌธํ์ ์ฐจ์ด๋ฅผ ์ ๋ ํฉ๋๋ค. ๋ชจ๋ ์ํธ์์ฉ์์ ํฌ์ฉ์ฑ๊ณผ ์กด์ค์ ์ฅ๋ คํฉ๋๋ค.
- ๋๊ตฌ ์ ๊ทผ์ฑ: ๋ชจ๋ ํ์์ด ์์น๋ ์ธํฐ๋ท ์ฐ๊ฒฐ ์ํ์ ๊ด๊ณ์์ด ํ์ํ ๋๊ตฌ์ ๋ฆฌ์์ค์ ์ ๊ทผํ ์ ์๋๋ก ๋ณด์ฅํฉ๋๋ค. ๋ก์ปฌ ์ข ์์ฑ์ ์ต์ํํ๊ธฐ ์ํด ํด๋ผ์ฐ๋ ๊ธฐ๋ฐ ์๋ฃจ์ ์ฌ์ฉ์ ๊ณ ๋ คํฉ๋๋ค.
- ๋ฌธ์ํ: ์ฝ๋ฉ ํ์ค ๋ฐ ํ์ง ์ธํ๋ผ์ ๋ํ ํฌ๊ด์ ์ธ ๋ฌธ์๋ฅผ ์ฝ๊ฒ ๋ฒ์ญํ ์ ์๋ ํ์์ผ๋ก ์ ๊ณตํ์ฌ ํ์๋ค์ด ์กฐ์ง์ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ฐ๋ฅผ ์ ์๋๋ก ํฉ๋๋ค.
๊ฒฐ๋ก
๊ฒฌ๊ณ ํ JavaScript ํ์ง ์ธํ๋ผ๋ฅผ ๊ตฌ์ถํ๋ ๊ฒ์ ์ง์์ ์ธ ๊ฐ์ ๊ณผ ์ ์์ด ํ์ํ ์งํ ์ค์ธ ๊ณผ์ ์ ๋๋ค. ์ด ๊ฐ์ด๋์์ ์ค๋ช ํ ๊ธฐ์ ๊ณผ ๋๊ตฌ๋ฅผ ๊ตฌํํจ์ผ๋ก์จ JavaScript ํ๋ก์ ํธ์ ํ์ง, ์ ์ง๋ณด์์ฑ, ํ์ฅ์ฑ์ ํฌ๊ฒ ํฅ์์ํค๊ณ ๊ธ๋ก๋ฒ ํ์ ์ํ ๋ ์์ฐ์ ์ด๊ณ ํ๋ ฅ์ ์ธ ํ๊ฒฝ์ ์กฐ์ฑํ ์ ์์ต๋๋ค. ํน์ ๋๊ตฌ์ ๊ตฌ์ฑ์ ํ๋ก์ ํธ์ ์๊ตฌ์ฌํญ๊ณผ ํ์ ์ ํธ๋์ ๋ฐ๋ผ ๋ฌ๋ผ์ง ์ ์์์ ๊ธฐ์ตํ์ญ์์ค. ํต์ฌ์ ์์ ์๊ฒ ๋ง๋ ์๋ฃจ์ ์ ์ฐพ๊ณ ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ์ง์์ ์ผ๋ก ๊ฐ์ ํ๋ ๊ฒ์ ๋๋ค.