๊ณ ๊ธ ์๋ฐ์คํฌ๋ฆฝํธ ๋ชจ๋ ํ ํ๋ฆฟ ํจํด๊ณผ ์ฝ๋ ์์ฑ์ ํ์ ํ์ํ์ฌ ๊ฐ๋ฐ์ ์์ฐ์ฑ์ ๋์ด๊ณ , ์ผ๊ด์ฑ์ ์ ์งํ๋ฉฐ, ํ๋ก์ ํธ๋ฅผ ์ ์ธ๊ณ์ ์ผ๋ก ํ์ฅํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์ธ์.
์๋ฐ์คํฌ๋ฆฝํธ ๋ชจ๋ ํ ํ๋ฆฟ ํจํด: ์ฝ๋ ์์ฑ์ผ๋ก ๊ฐ๋ฐ ์์ค ๋์ด๊ธฐ
๋น ๋ฅด๊ฒ ์งํํ๋ ํ๋ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ ํ๊ฒฝ์์ ํ๋ก์ ํธ ์ ๋ฐ์ ๊ฑธ์ณ ํจ์จ์ฑ, ์ผ๊ด์ฑ, ํ์ฅ์ฑ์ ์ ์งํ๋ ๊ฒ, ํนํ ๋ค์ํ ๊ธ๋ก๋ฒ ํ ๋ด์์๋ ๋์์๋ ๋์ ๊ณผ์ ์ ๋๋ค. ๊ฐ๋ฐ์๋ค์ API ํด๋ผ์ด์ธํธ, UI ์ปดํฌ๋ํธ, ์ํ ๊ด๋ฆฌ ์ฌ๋ผ์ด์ค ๋ฑ ๊ณตํต ๋ชจ๋ ๊ตฌ์กฐ์ ๋ํ ๋ฐ๋ณต์ ์ธ ๋ณด์ผ๋ฌํ๋ ์ดํธ ์ฝ๋๋ฅผ ์์ฑํ๋ ์์ ์ ์ข ์ข ๋ฐ๊ฒฌํฉ๋๋ค. ์ด๋ฌํ ์๋์ ์ธ ๋ณต์ ์์ ์ ๊ท์คํ ์๊ฐ์ ์๋ชจํ ๋ฟ๋ง ์๋๋ผ, ๋น์ผ๊ด์ฑ๊ณผ ์ธ์ ์ค๋ฅ์ ๊ฐ๋ฅ์ฑ์ ์ด๋ํ์ฌ ์์ฐ์ฑ๊ณผ ํ๋ก์ ํธ์ ๋ฌด๊ฒฐ์ฑ์ ์ ํดํฉ๋๋ค.
์ด ์ข ํฉ ๊ฐ์ด๋๋ ์๋ฐ์คํฌ๋ฆฝํธ ๋ชจ๋ ํ ํ๋ฆฟ ํจํด์ ์ธ๊ณ์ ์ฝ๋ ์์ฑ์ ๋ณํ์ ์ธ ํ์ ๋ํด ๊น์ด ํ๊ตฌํฉ๋๋ค. ์ฐ๋ฆฌ๋ ์ด๋ฌํ ์๋์ง ํจ๊ณผ๋ฅผ ๋ด๋ ์ ๊ทผ ๋ฐฉ์์ด ์ด๋ป๊ฒ ๊ฐ๋ฐ ์ํฌํ๋ก์ฐ๋ฅผ ๊ฐ์ํํ๊ณ , ์ํคํ ์ฒ ํ์ค์ ๊ฐ์ ํ๋ฉฐ, ๊ธ๋ก๋ฒ ๊ฐ๋ฐํ์ ์์ฐ์ฑ์ ํฌ๊ฒ ํฅ์์ํฌ ์ ์๋์ง ์ดํด๋ณผ ๊ฒ์ ๋๋ค. ํจ๊ณผ์ ์ธ ํ ํ๋ฆฟ ํจํด๊ณผ ๊ฒฌ๊ณ ํ ์ฝ๋ ์์ฑ ์ ๋ต์ ์ดํดํ๊ณ ๊ตฌํํจ์ผ๋ก์จ, ์กฐ์ง์ ๋ ๋์ ์์ค์ ์ฝ๋ ํ์ง์ ๋ฌ์ฑํ๊ณ , ๊ธฐ๋ฅ ์ ๊ณต์ ๊ฐ์ํํ๋ฉฐ, ์ง๋ฆฌ์ ๊ฒฝ๊ณ์ ๋ฌธํ์ ๋ฐฐ๊ฒฝ์ ๋์ด ์์ง๋ ฅ ์๋ ๊ฐ๋ฐ ๊ฒฝํ์ ๋ณด์ฅํ ์ ์์ต๋๋ค.
๊ธฐ์ด: ์๋ฐ์คํฌ๋ฆฝํธ ๋ชจ๋ ์ดํดํ๊ธฐ
ํ ํ๋ฆฟ ํจํด๊ณผ ์ฝ๋ ์์ฑ์ ๋ํด ์์๋ณด๊ธฐ ์ ์, ์๋ฐ์คํฌ๋ฆฝํธ ๋ชจ๋ ์์ฒด์ ๋ํ ํ์คํ ์ดํด๋ฅผ ๊ฐ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ๋ชจ๋์ ํ๋ ์๋ฐ์คํฌ๋ฆฝํธ ์ ํ๋ฆฌ์ผ์ด์ ์ ์กฐ์งํ๊ณ ๊ตฌ์กฐํํ๋ ๋ฐ ๊ธฐ๋ณธ์ด ๋๋ฉฐ, ๊ฐ๋ฐ์๋ค์ด ๋๊ท๋ชจ ์ฝ๋๋ฒ ์ด์ค๋ฅผ ์๊ณ , ๊ด๋ฆฌ ๊ฐ๋ฅํ๋ฉฐ, ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์กฐ๊ฐ์ผ๋ก ๋๋ ์ ์๊ฒ ํด์ค๋๋ค.
๋ชจ๋์ ์งํ
์๋ฐ์คํฌ๋ฆฝํธ์ ๋ชจ๋ํ ๊ฐ๋ ์ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ณต์ก์ฑ์ด ์ฆ๊ฐํ๊ณ ๋ ๋์ ์ฝ๋ ๊ตฌ์ฑ์ ์ํ ํ์์ฑ์ด ๋๋๋๋ฉด์ ์๋ ์ ๊ฑธ์ณ ํฌ๊ฒ ๋ฐ์ ํด์์ต๋๋ค:
- ESM ์ด์ ์๋: ๋ค์ดํฐ๋ธ ๋ชจ๋ ์์คํ ์ด ์๋ ์์ , ๊ฐ๋ฐ์๋ค์ ๋ชจ๋ํ๋ฅผ ๋ฌ์ฑํ๊ธฐ ์ํด ๋ค์ํ ํจํด์ ์์กดํ์ต๋๋ค.
- ์ฆ์ ์คํ ํจ์ ํํ์(IIFE): ์ด ํจํด์ ๋ณ์๋ฅผ ์ํ ๋น๊ณต๊ฐ ์ค์ฝํ๋ฅผ ์์ฑํ์ฌ ์ ์ญ ๋ค์์คํ์ด์ค ์ค์ผ์ ๋ฐฉ์งํ๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํ์ต๋๋ค. IIFE ๋ด๋ถ์ ์ ์๋ ํจ์์ ๋ณ์๋ ๋ช ์์ ์ผ๋ก ๋ ธ์ถ๋์ง ์๋ ํ ์ธ๋ถ์์ ์ ๊ทผํ ์ ์์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ๊ธฐ๋ณธ์ ์ธ IIFE๋ (function() { var privateVar = 'secret'; window.publicFn = function() { console.log(privateVar); }; })();์ ๊ฐ์ด ๋ณด์ผ ์ ์์ต๋๋ค.
- CommonJS: Node.js์ ์ํด ๋์คํ๋ CommonJS๋ ๋ชจ๋์ ๊ฐ์ ธ์ค๊ธฐ ์ํด require()๋ฅผ, ๋ด๋ณด๋ด๊ธฐ ์ํด module.exports ๋๋ exports๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ด๋ ๋๊ธฐ์ ์์คํ ์ผ๋ก, ํ์ผ ์์คํ ์์ ๋ชจ๋์ ๋ก๋ํ๋ ์๋ฒ ์ธก ํ๊ฒฝ์ ์ด์์ ์ ๋๋ค. ์์๋ก๋ const myModule = require('./myModule');๊ฐ ์์ผ๋ฉฐ, myModule.js์์๋ module.exports = { data: 'value' };์ ๊ฐ์ด ์ฌ์ฉํฉ๋๋ค.
- ๋น๋๊ธฐ ๋ชจ๋ ์ ์(AMD): ์ฃผ๋ก RequireJS์ ๊ฐ์ ๋ก๋์ ํจ๊ป ํด๋ผ์ด์ธํธ ์ธก ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ฌ์ฉ๋ AMD๋ ๋ชจ๋์ ๋น๋๊ธฐ ๋ก๋ฉ์ ์ํด ์ค๊ณ๋์์ต๋๋ค. ์ด๋ ๋ธ๋ผ์ฐ์ ํ๊ฒฝ์์ ๋ฉ์ธ ์ค๋ ๋ ์ฐจ๋จ์ ํผํ๊ธฐ ์ํด ํ์์ ์ ๋๋ค. ๋ชจ๋์ ์ํด define() ํจ์๋ฅผ, ์์กด์ฑ์ ์ํด require()๋ฅผ ์ฌ์ฉํฉ๋๋ค.
- ES ๋ชจ๋(ESM): ECMAScript 2015 (ES6)์์ ๋์ ๋ ES ๋ชจ๋์ ์๋ฐ์คํฌ๋ฆฝํธ์ ๋ชจ๋ํ์ ๋ํ ๊ณต์ ํ์ค์ ๋๋ค. ์ฌ๋ฌ ๊ฐ์ง ์ค์ํ ์ด์ ์ ์ ๊ณตํฉ๋๋ค:
- ์ ์ ๋ถ์: ESM์ ์์กด์ฑ์ ์ ์ ๋ถ์์ ํ์ฉํ์ฌ ์ฝ๋๋ฅผ ์คํํ์ง ์๊ณ ๋ ๋ชจ๋ ๊ตฌ์กฐ๋ฅผ ๊ฒฐ์ ํ ์ ์๊ฒ ํฉ๋๋ค. ์ด๋ ๋ฒ๋ค์์ ์ฌ์ฉ๋์ง ์๋ ์ฝ๋๋ฅผ ์ ๊ฑฐํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ํฌ๊ธฐ๋ฅผ ์ค์ด๋ ํธ๋ฆฌ ์์ดํน(tree-shaking)๊ณผ ๊ฐ์ ๊ฐ๋ ฅํ ๋๊ตฌ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค.
- ๋ช ํํ ๊ตฌ๋ฌธ: ESM์ ๊ฐ๋จํ import์ export ๊ตฌ๋ฌธ์ ์ฌ์ฉํ์ฌ ๋ชจ๋ ์์กด์ฑ์ ๋ช ์์ ์ด๊ณ ์ดํดํ๊ธฐ ์ฝ๊ฒ ๋ง๋ญ๋๋ค. ์๋ฅผ ๋ค์ด, import { myFunction } from './myModule';์ export const myFunction = () => {};์ ๊ฐ์ต๋๋ค.
- ๊ธฐ๋ณธ์ ์ผ๋ก ๋น๋๊ธฐ: ESM์ ๋น๋๊ธฐ์ ์ผ๋ก ์ค๊ณ๋์ด ๋ธ๋ผ์ฐ์ ์ Node.js ํ๊ฒฝ ๋ชจ๋์ ์ ํฉํฉ๋๋ค.
- ์ํธ ์ด์ฉ์ฑ: Node.js์์์ ์ด๊ธฐ ๋์ ์ ๋ณต์กํ์ง๋ง, ์ต์ Node.js ๋ฒ์ ์ package.json์ "type": "module"์ด๋ .mjs ํ์ผ ํ์ฅ์์ ๊ฐ์ ๋ฉ์ปค๋์ฆ์ ํตํด CommonJS์ ํจ๊ป ESM์ ๊ฐ๋ ฅํ๊ฒ ์ง์ํฉ๋๋ค. ์ด๋ฌํ ์ํธ ์ด์ฉ์ฑ์ ํ์ด๋ธ๋ฆฌ๋ ์ฝ๋๋ฒ ์ด์ค ๋ฐ ์ ํ ๊ณผ์ ์์ ๋งค์ฐ ์ค์ํฉ๋๋ค.
๋ชจ๋ ํจํด์ด ์ค์ํ ์ด์
๊ฐ์ ธ์ค๊ณ ๋ด๋ณด๋ด๋ ๊ธฐ๋ณธ ๊ตฌ๋ฌธ์ ๋์ด์, ํน์ ๋ชจ๋ ํจํด์ ์ ์ฉํ๋ ๊ฒ์ ๊ฒฌ๊ณ ํ๊ณ , ํ์ฅ ๊ฐ๋ฅํ๋ฉฐ, ์ ์ง๋ณด์ ๊ฐ๋ฅํ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๋ ๋ฐ ํ์์ ์ ๋๋ค:
- ์บก์ํ: ๋ชจ๋์ ๊ด๋ จ๋ ๋ก์ง์ ์บก์ํํ๋ ์์ฐ์ค๋ฌ์ด ๊ฒฝ๊ณ๋ฅผ ์ ๊ณตํ์ฌ ์ ์ญ ์ค์ฝํ์ ์ค์ผ์ ๋ฐฉ์งํ๊ณ ์๋ํ์ง ์์ ๋ถ์์ฉ์ ์ต์ํํฉ๋๋ค.
- ์ฌ์ฌ์ฉ์ฑ: ์ ์ ์๋ ๋ชจ๋์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ค๋ฅธ ๋ถ๋ถ์ด๋ ์ฌ์ง์ด ์์ ํ ๋ค๋ฅธ ํ๋ก์ ํธ์์ ์ฝ๊ฒ ์ฌ์ฌ์ฉ๋ ์ ์์ด ์ค๋ณต์ ์ค์ด๊ณ "๋ฐ๋ณตํ์ง ๋ง๋ผ"(DRY) ์์น์ ์ด์งํฉ๋๋ค.
- ์ ์ง๋ณด์์ฑ: ์๊ณ ์ง์ค๋ ๋ชจ๋์ ์ดํด, ํ ์คํธ, ๋๋ฒ๊น ์ด ๋ ์ฝ์ต๋๋ค. ํ ๋ชจ๋ ๋ด์ ๋ณ๊ฒฝ ์ฌํญ์ด ์์คํ ์ ๋ค๋ฅธ ๋ถ๋ถ์ ์ํฅ์ ๋ฏธ์น ๊ฐ๋ฅ์ฑ์ด ์ ์ด ์ ์ง๋ณด์๊ฐ ๊ฐ๋จํด์ง๋๋ค.
- ์์กด์ฑ ๊ด๋ฆฌ: ๋ชจ๋์ ์์กด์ฑ์ ๋ช ์์ ์ผ๋ก ์ ์ธํ์ฌ ์ด๋ค ์ธ๋ถ ๋ฆฌ์์ค์ ์์กดํ๋์ง ๋ช ํํ๊ฒ ํฉ๋๋ค. ์ด ๋ช ์์ ์ธ ์์กด์ฑ ๊ทธ๋ํ๋ ์์คํ ์ํคํ ์ฒ๋ฅผ ์ดํดํ๊ณ ๋ณต์กํ ์ํธ ์ฐ๊ฒฐ์ ๊ด๋ฆฌํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
- ํ ์คํธ ์ฉ์ด์ฑ: ๊ฒฉ๋ฆฌ๋ ๋ชจ๋์ ๋ณธ์ง์ ์ผ๋ก ๋ ๋ฆฝ์ ์ผ๋ก ํ ์คํธํ๊ธฐ ์ฌ์ ๋ ๊ฒฌ๊ณ ํ๊ณ ์ ๋ขฐํ ์ ์๋ ์ํํธ์จ์ด๋ก ์ด์ด์ง๋๋ค.
๋ชจ๋์ ํ ํ๋ฆฟ์ด ํ์ํ ์ด์
๋ชจ๋์ ๊ธฐ๋ณธ์ ์ ์ดํดํ๊ณ ์๋๋ผ๋, ๊ฐ๋ฐ์๋ค์ ๋ฐ๋ณต์ ์ด๊ณ ์๋์ ์ธ ์์ ์ผ๋ก ์ธํด ๋ชจ๋ํ์ ์ด์ ์ด ์ฝํ๋๋ ์๋๋ฆฌ์ค์ ์ข ์ข ์ง๋ฉดํฉ๋๋ค. ๋ฐ๋ก ์ด ์ง์ ์์ ๋ชจ๋์ ์ํ ํ ํ๋ฆฟ ๊ฐ๋ ์ด ํ์์ ์ด ๋ฉ๋๋ค.
๋ฐ๋ณต์ ์ธ ๋ณด์ผ๋ฌํ๋ ์ดํธ
์๋นํ ๊ท๋ชจ์ ๊ฑฐ์ ๋ชจ๋ ์๋ฐ์คํฌ๋ฆฝํธ ์ ํ๋ฆฌ์ผ์ด์ ์์ ๋ฐ๊ฒฌ๋๋ ๊ณตํต ๊ตฌ์กฐ๋ฅผ ์๊ฐํด๋ณด์ญ์์ค:
- API ํด๋ผ์ด์ธํธ: ๋ชจ๋ ์๋ก์ด ๋ฆฌ์์ค(์ฌ์ฉ์, ์ ํ, ์ฃผ๋ฌธ)์ ๋ํด ์ผ๋ฐ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ณ , ์์ฑํ๊ณ , ์ ๋ฐ์ดํธํ๊ณ , ์ญ์ ํ๋ ๋ฉ์๋๋ฅผ ๊ฐ์ง ์๋ก์ด ๋ชจ๋์ ๋ง๋ญ๋๋ค. ์ฌ๊ธฐ์๋ ๊ธฐ๋ณธ URL, ์์ฒญ ๋ฉ์๋, ์ค๋ฅ ์ฒ๋ฆฌ, ๊ทธ๋ฆฌ๊ณ ์๋ง๋ ์ธ์ฆ ํค๋๋ฅผ ์ ์ํ๋ ์์ ์ด ํฌํจ๋๋ฉฐ, ์ด ๋ชจ๋ ๊ฒ์ ์์ธก ๊ฐ๋ฅํ ํจํด์ ๋ฐ๋ฆ ๋๋ค.
- UI ์ปดํฌ๋ํธ: React, Vue, Angular ์ค ๋ฌด์์ ์ฌ์ฉํ๋ , ์๋ก์ด ์ปดํฌ๋ํธ๋ ์ข ์ข ์ปดํฌ๋ํธ ํ์ผ, ํด๋น ์คํ์ผ์ํธ, ํ ์คํธ ํ์ผ, ๊ทธ๋ฆฌ๊ณ ๋๋ก๋ ๋ฌธ์ํ๋ฅผ ์ํ ์คํ ๋ฆฌ๋ถ ํ์ผ์ ์์ฑํด์ผ ํฉ๋๋ค. ๊ธฐ๋ณธ ๊ตฌ์กฐ(import, ์ปดํฌ๋ํธ ์ ์, props ์ ์ธ, export)๋ ์ด๋ฆ๊ณผ ํน์ ๋ก์ง๋ง ๋ค๋ฅผ ๋ฟ ๋๋ถ๋ถ ๋์ผํฉ๋๋ค.
- ์ํ ๊ด๋ฆฌ ๋ชจ๋: Redux (Redux Toolkit ํฌํจ), Vuex, Zustand์ ๊ฐ์ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ์ ํ๋ฆฌ์ผ์ด์ ์์ ์๋ก์ด "์ฌ๋ผ์ด์ค" ๋๋ "์คํ ์ด"๋ฅผ ๋ง๋๋ ๊ฒ์ ์ด๊ธฐ ์ํ, ๋ฆฌ๋์(๋๋ ์ก์ ), ์ ๋ ํฐ๋ฅผ ์ ์ํ๋ ๊ฒ์ ํฌํจํฉ๋๋ค. ์ด๋ฌํ ๊ตฌ์กฐ๋ฅผ ์ค์ ํ๊ธฐ ์ํ ๋ณด์ผ๋ฌํ๋ ์ดํธ๋ ๋งค์ฐ ํ์คํ๋์ด ์์ต๋๋ค.
- ์ ํธ๋ฆฌํฐ ๋ชจ๋: ๊ฐ๋จํ ํฌํผ ํจ์๋ ์ข ์ข ์ ํธ๋ฆฌํฐ ๋ชจ๋์ ์์นํฉ๋๋ค. ๋ด๋ถ ๋ก์ง์ ๋ค์ํ์ง๋ง, ๋ชจ๋์ export ๊ตฌ์กฐ์ ๊ธฐ๋ณธ ํ์ผ ์ค์ ์ ํ์คํ๋ ์ ์์ต๋๋ค.
- ํ ์คํธ, ๋ฆฐํ , ๋ฌธ์ํ ์ค์ : ํต์ฌ ๋ก์ง ์ธ์๋, ๊ฐ ์๋ก์ด ๋ชจ๋์ด๋ ๊ธฐ๋ฅ์ ์ข ์ข ๊ด๋ จ๋ ํ ์คํธ ํ์ผ, ๋ฆฐํ ์ค์ (๋ชจ๋๋ณ๋ก๋ ๋ ์ผ๋ฐ์ ์ด์ง๋ง ์๋ก์ด ํ๋ก์ ํธ ์ ํ์๋ ์ฌ์ ํ ์ ์ฉ๋จ), ๊ทธ๋ฆฌ๊ณ ๋ฌธ์ ์คํ ์ด ํ์ํ๋ฉฐ, ์ด ๋ชจ๋ ๊ฒ์ ํ ํ๋ฆฟํ์ ์ด์ ์ ๋๋ฆด ์ ์์ต๋๋ค.
์ด๋ฌํ ํ์ผ๋ค์ ์๋์ผ๋ก ๋ง๋ค๊ณ ๊ฐ ์๋ก์ด ๋ชจ๋์ ๋ํ ์ด๊ธฐ ๊ตฌ์กฐ๋ฅผ ํ์ดํํ๋ ๊ฒ์ ์ง๋ฃจํ ๋ฟ๋ง ์๋๋ผ, ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ์ฌ๋ฌ ๊ฐ๋ฐ์์ ๊ฑธ์ณ ๋์ ๋ ์ ์๋ ์ฌ์ํ ์ค๋ฅ์ ์ทจ์ฝํฉ๋๋ค.
์ผ๊ด์ฑ ๋ณด์ฅ
์ผ๊ด์ฑ์ ์ ์ง๋ณด์ ๊ฐ๋ฅํ๊ณ ํ์ฅ ๊ฐ๋ฅํ ์ํํธ์จ์ด ํ๋ก์ ํธ์ ์ด์์ ๋๋ค. ์๋ง์ ๊ธฐ์ฌ์๊ฐ ์๋ ๋๊ท๋ชจ ์กฐ์ง์ด๋ ์คํ ์์ค ํ๋ก์ ํธ์์๋ ๊ท ์ผํ ์ฝ๋ ์คํ์ผ, ์ํคํ ์ฒ ํจํด, ํด๋ ๊ตฌ์กฐ๋ฅผ ์ ์งํ๋ ๊ฒ์ด ๋ฌด์๋ณด๋ค ์ค์ํฉ๋๋ค:
- ์ฝ๋ฉ ํ์ค: ํ ํ๋ฆฟ์ ์๋ก์ด ๋ชจ๋์ด ์์ฑ๋๋ ์์ ๋ถํฐ ์ ํธํ๋ ๋ช ๋ช ๊ท์น, ํ์ผ ๊ตฌ์ฑ ๋ฐ ๊ตฌ์กฐ์ ํจํด์ ๊ฐ์ ํ ์ ์์ต๋๋ค. ์ด๋ ์คํ์ผ๊ณผ ๊ตฌ์กฐ์๋ง ์ด์ ์ ๋ง์ถ ๊ด๋ฒ์ํ ์๋ ์ฝ๋ ๋ฆฌ๋ทฐ์ ํ์์ฑ์ ์ค์ฌ์ค๋๋ค.
- ์ํคํ ์ฒ ํจํด: ํ๋ก์ ํธ๊ฐ ํน์ ์ํคํ ์ฒ ์ ๊ทผ ๋ฐฉ์(์: ๋๋ฉ์ธ ์ฃผ๋ ์ค๊ณ, ๊ธฐ๋ฅ ๋ถํ ์ค๊ณ)์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ, ํ ํ๋ฆฟ์ ๋ชจ๋ ์๋ก์ด ๋ชจ๋์ด ์ด๋ฌํ ํ๋ฆฝ๋ ํจํด์ ์ค์ํ๋๋ก ๋ณด์ฅํ์ฌ "์ํคํ ์ฒ ๋๋ฆฌํํธ"๋ฅผ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
- ์ ๊ท ๊ฐ๋ฐ์ ์จ๋ณด๋ฉ: ์๋ก์ด ํ์์๊ฒ๋ ๋๊ท๋ชจ ์ฝ๋๋ฒ ์ด์ค๋ฅผ ํ์ํ๊ณ ๊ทธ ๊ด๋ก๋ฅผ ์ดํดํ๋ ๊ฒ์ด ์ด๋ ค์ธ ์ ์์ต๋๋ค. ํ ํ๋ฆฟ ๊ธฐ๋ฐ์ ์์ฑ๊ธฐ๋ฅผ ์ ๊ณตํ๋ฉด ์ง์ ์ฅ๋ฒฝ์ ํฌ๊ฒ ๋ฎ์ถ์ด, ๋ชจ๋ ์ธ๋ถ ์ฌํญ์ ์๊ธฐํ ํ์ ์์ด ํ๋ก์ ํธ ํ์ค์ ๋ถํฉํ๋ ์๋ก์ด ๋ชจ๋์ ์ ์ํ๊ฒ ์์ฑํ ์ ์์ต๋๋ค. ์ด๋ ์ง์ ์ ์ธ ๋๋ฉด ๊ต์ก์ด ์ ํ๋ ์ ์๋ ๊ธ๋ก๋ฒ ํ์ ํนํ ์ ์ฉํฉ๋๋ค.
- ํ๋ก์ ํธ ๊ฐ ์์ง์ฑ: ์ ์ฌํ ๊ธฐ์ ์คํ์ ๊ฐ์ง ์ฌ๋ฌ ํ๋ก์ ํธ๋ฅผ ๊ด๋ฆฌํ๋ ์กฐ์ง์์๋ ๊ณต์ ํ ํ๋ฆฟ์ ํตํด ์ ์ฒด ํฌํธํด๋ฆฌ์ค์ ๊ฑธ์ณ ์ฝ๋๋ฒ ์ด์ค์ ์ผ๊ด๋ ๋ชจ์๊ณผ ๋๋์ ๋ณด์ฅํ์ฌ ๋ ์ฌ์ด ๋ฆฌ์์ค ํ ๋น๊ณผ ์ง์ ์ ๋ฌ์ ์ด์งํ ์ ์์ต๋๋ค.
๊ฐ๋ฐ ํ์ฅ
์ ํ๋ฆฌ์ผ์ด์ ์ ๋ณต์ก์ฑ์ด ์ฆ๊ฐํ๊ณ ๊ฐ๋ฐํ์ด ์ ์ธ๊ณ์ ์ผ๋ก ํ์ฅ๋จ์ ๋ฐ๋ผ ํ์ฅ์ฑ์ ๊ณผ์ ๋ ๋์ฑ ๋๋๋ฌ์ง๋๋ค:
- ๋ชจ๋ ธ๋ ํฌ์ ๋ง์ดํฌ๋ก ํ๋ก ํธ์๋: ๋ชจ๋ ธ๋ ํฌ(์ฌ๋ฌ ํ๋ก์ ํธ/ํจํค์ง๋ฅผ ํฌํจํ๋ ๋จ์ผ ์ ์ฅ์)๋ ๋ง์ดํฌ๋ก ํ๋ก ํธ์๋ ์ํคํ ์ฒ์์๋ ๋ง์ ๋ชจ๋์ด ์ ์ฌํ ๊ธฐ๋ณธ ๊ตฌ์กฐ๋ฅผ ๊ณต์ ํฉ๋๋ค. ํ ํ๋ฆฟ์ ์ด๋ฌํ ๋ณต์กํ ์ค์ ๋ด์์ ์๋ก์ด ํจํค์ง๋ ๋ง์ดํฌ๋ก ํ๋ก ํธ์๋์ ์ ์ํ ์์ฑ์ ์ฉ์ดํ๊ฒ ํ์ฌ ๊ณตํต ๊ตฌ์ฑ๊ณผ ํจํด์ ์์๋ฐ๋๋ก ๋ณด์ฅํฉ๋๋ค.
- ๊ณต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ: ๊ณต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๋์์ธ ์์คํ ์ ๊ฐ๋ฐํ ๋, ํ ํ๋ฆฟ์ ์๋ก์ด ์ปดํฌ๋ํธ, ์ ํธ๋ฆฌํฐ, ํ ์ ์์ฑ์ ํ์คํํ์ฌ ์ฒ์๋ถํฐ ์ฌ๋ฐ๋ฅด๊ฒ ๊ตฌ์ถ๋๊ณ ์ข ์ ํ๋ก์ ํธ์์ ์ฝ๊ฒ ์๋น๋ ์ ์๋๋ก ๋ณด์ฅํฉ๋๋ค.
- ๊ธ๋ก๋ฒ ํ์ ๊ธฐ์ฌ: ๊ฐ๋ฐ์๋ค์ด ๋ค๋ฅธ ์๊ฐ๋, ๋ฌธํ, ์ง๋ฆฌ์ ์์น์ ํฉ์ด์ ธ ์์ ๋, ํ์คํ๋ ํ ํ๋ฆฟ์ ๋ณดํธ์ ์ธ ์ฒญ์ฌ์ง ์ญํ ์ ํฉ๋๋ค. ์ด๋ "์ด๋ป๊ฒ ์์ํ ์ง"์ ๋ํ ์ธ๋ถ ์ฌํญ์ ์ถ์ํํ์ฌ, ํ์ด ํต์ฌ ๋ก์ง์ ์ง์คํ ์ ์๋๋ก ํ๋ฉฐ, ๋๊ฐ ๋๋ ์ด๋์ ์์ฑํ๋์ง์ ๊ด๊ณ์์ด ๊ธฐ๋ณธ ๊ตฌ์กฐ๊ฐ ์ผ๊ด๋จ์ ๋ณด์ฅํฉ๋๋ค. ์ด๋ ์์ฌ์ํต ์ค๋ฅ๋ฅผ ์ต์ํํ๊ณ ํต์ผ๋ ๊ฒฐ๊ณผ๋ฌผ์ ๋ณด์ฅํฉ๋๋ค.
์ฝ๋ ์์ฑ ์๊ฐ
์ฝ๋ ์์ฑ์ ์์ค ์ฝ๋๋ฅผ ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ผ๋ก ์์ฑํ๋ ๊ฒ์ ๋๋ค. ์ด๋ ๋ชจ๋ ํ ํ๋ฆฟ์ ์ค์ ์คํ ๊ฐ๋ฅํ ์๋ฐ์คํฌ๋ฆฝํธ ํ์ผ๋ก ๋ณํํ๋ ์์ง์ ๋๋ค. ์ด ๊ณผ์ ์ ๋จ์ํ ๋ณต์ฌ-๋ถ์ฌ๋ฃ๊ธฐ๋ฅผ ๋์ด ์ง๋ฅ์ ์ด๊ณ ๋ฌธ๋งฅ์ ์ธ์ํ๋ ํ์ผ ์์ฑ ๋ฐ ์์ ์ผ๋ก ๋์๊ฐ๋๋ค.
์ฝ๋ ์์ฑ(Code Generation)์ด๋ ๋ฌด์์ธ๊ฐ?
ํต์ฌ์ ์ผ๋ก, ์ฝ๋ ์์ฑ์ ์ ์๋ ๊ท์น, ํ ํ๋ฆฟ ๋๋ ์ ๋ ฅ ๋ช ์ธ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์์ค ์ฝ๋๋ฅผ ์๋์ผ๋ก ์์ฑํ๋ ๊ณผ์ ์ ๋๋ค. ๊ฐ๋ฐ์๊ฐ ๋ชจ๋ ์ค์ ์๋์ผ๋ก ์์ฑํ๋ ๋์ , ํ๋ก๊ทธ๋จ์ด ์์ ์์ค์ ์ง์(์: "์ฌ์ฉ์ API ํด๋ผ์ด์ธํธ ์์ฑ" ๋๋ "์๋ก์ด React ์ปดํฌ๋ํธ ์ค์บํด๋ฉ")๋ฅผ ๋ฐ์ ์์ ํ๊ณ ๊ตฌ์กฐํ๋ ์ฝ๋๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
- ํ ํ๋ฆฟ ๊ธฐ๋ฐ: ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ํํ๋ ํ ํ๋ฆฟ ํ์ผ(์: EJS ๋๋ Handlebars ํ ํ๋ฆฟ)์ ๊ฐ์ ธ์ ๋์ ๋ฐ์ดํฐ(์: ์ปดํฌ๋ํธ ์ด๋ฆ, ํจ์ ๋งค๊ฐ๋ณ์)๋ฅผ ์ฃผ์ ํ์ฌ ์ต์ข ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฒ์ ๋๋ค.
- ์คํค๋ง/์ ์ธ์ ๋ช ์ธ ๊ธฐ๋ฐ: ๋ ๊ณ ๊ธ ์์ฑ์ ๋ฐ์ดํฐ ์คํค๋ง(GraphQL ์คํค๋ง, ๋ฐ์ดํฐ๋ฒ ์ด์ค ์คํค๋ง, OpenAPI ๋ช ์ธ ๋ฑ)์์ ๋ฐ์ํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์ ์์ฑ๊ธฐ๋ ์คํค๋ง์ ์ ์๋ ๊ตฌ์กฐ์ ํ์ ์ ์ดํดํ๊ณ ํด๋ผ์ด์ธํธ ์ธก ์ฝ๋, ์๋ฒ ์ธก ๋ชจ๋ธ ๋๋ ๋ฐ์ดํฐ ์ ๊ทผ ๊ณ์ธต์ ์์ฑํฉ๋๋ค.
- ๊ธฐ์กด ์ฝ๋ ๊ธฐ๋ฐ(AST ๊ธฐ๋ฐ): ์ผ๋ถ ์ ๊ตํ ์์ฑ๊ธฐ๋ ๊ธฐ์กด ์ฝ๋๋ฒ ์ด์ค๋ฅผ ์ถ์ ๊ตฌ๋ฌธ ํธ๋ฆฌ(AST)๋ก ํ์ฑํ์ฌ ๋ถ์ํ ๋ค์, AST ๋ด์์ ๋ฐ๊ฒฌ๋ ํจํด์ ๊ธฐ๋ฐ์ผ๋ก ์๋ก์ด ์ฝ๋๋ฅผ ๋ณํํ๊ฑฐ๋ ์์ฑํฉ๋๋ค. ์ด๋ ๋ฆฌํฉํ ๋ง ๋๊ตฌ๋ "์ฝ๋๋ชจ๋(codemods)"์์ ํํ ๋ณผ ์ ์์ต๋๋ค.
์ฝ๋ ์์ฑ๊ณผ ๋จ์ํ ์ค๋ํซ์ ์ฌ์ฉํ๋ ๊ฒ์ ์ฐจ์ด๋ ์ค์ํฉ๋๋ค. ์ค๋ํซ์ ์๊ณ ์ ์ ์ธ ์ฝ๋ ๋ธ๋ก์ ๋๋ค. ๋ฐ๋ฉด, ์ฝ๋ ์์ฑ์ ๋์ ์ด๊ณ ๋ฌธ๋งฅ์ ๋ฏผ๊ฐํ๋ฉฐ, ์ฌ์ฉ์ ์ ๋ ฅ์ด๋ ์ธ๋ถ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ ์ฒด ํ์ผ ๋๋ ์ํธ ์ฐ๊ฒฐ๋ ํ์ผ๋ค์ ๋๋ ํ ๋ฆฌ๊น์ง ์์ฑํ ์ ์์ต๋๋ค.
๋ชจ๋ ์ฝ๋๋ฅผ ์์ฑํ๋ ์ด์
์๋ฐ์คํฌ๋ฆฝํธ ๋ชจ๋์ ์ฝ๋ ์์ฑ์ ๊ตฌ์ฒด์ ์ผ๋ก ์ ์ฉํ๋ฉด ํ๋ ๊ฐ๋ฐ์ ๊ณผ์ ๋ฅผ ์ง์ ์ ์ผ๋ก ํด๊ฒฐํ๋ ์๋ง์ ์ด์ ์ ์ป์ ์ ์์ต๋๋ค:
- ๊ตฌ์กฐ์ ์ ์ฉ๋ DRY ์์น: ์ฝ๋ ์์ฑ์ "๋ฐ๋ณตํ์ง ๋ง๋ผ" ์์น์ ๊ตฌ์กฐ์ ์์ค์ผ๋ก ๋์ด์ฌ๋ฆฝ๋๋ค. ๋ณด์ผ๋ฌํ๋ ์ดํธ ์ฝ๋๋ฅผ ๋ฐ๋ณตํ๋ ๋์ , ํ ํ๋ฆฟ์ ํ ๋ฒ ์ ์ํ๋ฉด ์์ฑ๊ธฐ๊ฐ ํ์์ ๋ฐ๋ผ ๋ณต์ ํฉ๋๋ค.
- ๊ธฐ๋ฅ ๊ฐ๋ฐ ๊ฐ์ํ: ๊ธฐ๋ณธ์ ์ธ ๋ชจ๋ ๊ตฌ์กฐ ์์ฑ์ ์๋ํํจ์ผ๋ก์จ, ๊ฐ๋ฐ์๋ค์ ์ค์ ๊ณผ ๋ณด์ผ๋ฌํ๋ ์ดํธ์ ์๊ฐ์ ๋ญ๋นํ์ง ์๊ณ ํต์ฌ ๋ก์ง ๊ตฌํ์ ๋ฐ๋ก ๋ฐ์ด๋ค ์ ์์ต๋๋ค. ์ด๋ ๋ ๋น ๋ฅธ ๋ฐ๋ณต๊ณผ ์๋ก์ด ๊ธฐ๋ฅ์ ์ ์ํ ์ ๊ณต์ ์๋ฏธํฉ๋๋ค.
- ๋ณด์ผ๋ฌํ๋ ์ดํธ์์์ ์ธ์ ์ค๋ฅ ๊ฐ์: ์๋ ํ์ดํ์ ์คํ, ์์ด๋ฒ๋ฆฐ import, ๋๋ ์๋ชป๋ ํ์ผ ์ด๋ฆ ์ง์ ์ ์ทจ์ฝํฉ๋๋ค. ์์ฑ๊ธฐ๋ ์ด๋ฌํ ์ผ๋ฐ์ ์ธ ์ค์๋ฅผ ์ ๊ฑฐํ์ฌ ์ค๋ฅ ์๋ ๊ธฐ๋ณธ ์ฝ๋๋ฅผ ์์ฑํฉ๋๋ค.
- ์ํคํ ์ฒ ๊ท์น ๊ฐ์ : ์์ฑ๊ธฐ๋ ์ฌ์ ์ ์ ์๋ ์ํคํ ์ฒ ํจํด, ๋ช ๋ช ๊ท์น, ํ์ผ ๊ตฌ์กฐ๋ฅผ ์๊ฒฉํ๊ฒ ์ค์ํ๋๋ก ๊ตฌ์ฑํ ์ ์์ต๋๋ค. ์ด๋ ์์ฑ๋ ๋ชจ๋ ์๋ก์ด ๋ชจ๋์ด ํ๋ก์ ํธ ํ์ค์ ์ค์ํ๋๋ก ๋ณด์ฅํ์ฌ, ์ ์ธ๊ณ ์ด๋์ ์๋ ๊ฐ๋ฐ์๋ ์ฝ๋๋ฒ ์ด์ค๋ฅผ ๋ ์์ธก ๊ฐ๋ฅํ๊ณ ํ์ํ๊ธฐ ์ฝ๊ฒ ๋ง๋ญ๋๋ค.
- ์จ๋ณด๋ฉ ๊ฐ์ : ์๋ก์ด ํ์๋ค์ ์์ฑ๊ธฐ๋ฅผ ์ฌ์ฉํ์ฌ ํ์ค์ ์ค์ํ๋ ๋ชจ๋์ ์ ์ํ๊ฒ ์์ฑํจ์ผ๋ก์จ ๋น ๋ฅด๊ฒ ์์ฐ์ฑ์ ๋์ผ ์ ์์ผ๋ฉฐ, ํ์ต ๊ณก์ ์ ์ค์ด๊ณ ๋ ๋น ๋ฅธ ๊ธฐ์ฌ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค.
์ผ๋ฐ์ ์ธ ์ฌ์ฉ ์ฌ๋ก
์ฝ๋ ์์ฑ์ ๊ด๋ฒ์ํ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ ์์ ์ ์ ์ฉ ๊ฐ๋ฅํฉ๋๋ค:
- CRUD ์์ (API ํด๋ผ์ด์ธํธ, ORM): ๋ฆฌ์์ค ์ด๋ฆ์ ๊ธฐ๋ฐ์ผ๋ก RESTful ๋๋ GraphQL ์๋ํฌ์ธํธ์ ์ํธ ์์ฉํ๋ API ์๋น์ค ๋ชจ๋์ ์์ฑํฉ๋๋ค. ์๋ฅผ ๋ค์ด, getAllUsers(), getUserById(), createUser() ๋ฑ์ ํฌํจํ๋ userService.js๋ฅผ ์์ฑํฉ๋๋ค.
- ์ปดํฌ๋ํธ ์ค์บํด๋ฉ (UI ๋ผ์ด๋ธ๋ฌ๋ฆฌ): ์๋ก์ด UI ์ปดํฌ๋ํธ(์: React, Vue, Angular ์ปดํฌ๋ํธ)์ ๊ด๋ จ๋ CSS/SCSS ํ์ผ, ํ ์คํธ ํ์ผ, ์คํ ๋ฆฌ๋ถ ํญ๋ชฉ์ ํจ๊ป ์์ฑํฉ๋๋ค.
- ์ํ ๊ด๋ฆฌ ๋ณด์ผ๋ฌํ๋ ์ดํธ: Redux ์ฌ๋ผ์ด์ค, Vuex ๋ชจ๋, Zustand ์คํ ์ด ์์ฑ์ ์๋ํํ๋ฉฐ, ์ด๊ธฐ ์ํ, ๋ฆฌ๋์/์ก์ , ์ ๋ ํฐ๋ฅผ ์๋นํฉ๋๋ค.
- ๊ตฌ์ฑ ํ์ผ: ํ๋ก์ ํธ ๋งค๊ฐ๋ณ์๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๊ฒฝ๋ณ ๊ตฌ์ฑ ํ์ผ์ด๋ ํ๋ก์ ํธ ์ค์ ํ์ผ์ ์์ฑํฉ๋๋ค.
- ํ ์คํธ ๋ฐ ๋ชฉ(Mock) ๋ฐ์ดํฐ: ์๋ก ์์ฑ๋ ๋ชจ๋์ ๋ํ ๊ธฐ๋ณธ ํ ์คํธ ํ์ผ์ ์ค์บํด๋ฉํ์ฌ ๋ชจ๋ ์๋ก์ด ๋ก์ง ์กฐ๊ฐ์ ํด๋นํ๋ ํ ์คํธ ๊ตฌ์กฐ๊ฐ ์๋๋ก ๋ณด์ฅํฉ๋๋ค. ํ ์คํธ ๋ชฉ์ ์ผ๋ก ์คํค๋ง์์ ๋ชฉ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ์์ฑํฉ๋๋ค.
- ๋ฌธ์ ์คํ : ๋ชจ๋์ ๋ํ ์ด๊ธฐ ๋ฌธ์ ํ์ผ์ ์์ฑํ์ฌ ๊ฐ๋ฐ์๋ค์ด ์ธ๋ถ ์ ๋ณด๋ฅผ ์ฑ์ฐ๋๋ก ์ ๋ํฉ๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ ๋ชจ๋์ ์ํ ํต์ฌ ํ ํ๋ฆฟ ํจํด
๋ชจ๋ ํ ํ๋ฆฟ์ ์ด๋ป๊ฒ ๊ตฌ์กฐํํ ์ง ์ดํดํ๋ ๊ฒ์ด ํจ๊ณผ์ ์ธ ์ฝ๋ ์์ฑ์ ํต์ฌ์ ๋๋ค. ์ด๋ฌํ ํจํด๋ค์ ์ผ๋ฐ์ ์ธ ์ํคํ ์ฒ ์๊ตฌ์ฌํญ์ ๋ํ๋ด๋ฉฐ, ํน์ ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ ์ํด ๋งค๊ฐ๋ณ์ํ๋ ์ ์์ต๋๋ค.
๋ค์ ์์ ์์๋ EJS๋ Handlebars์ ๊ฐ์ ์์ง์์ ํํ ๋ณผ ์ ์๋ ๊ฐ์ ํ ํ๋ฆฟ ๊ตฌ๋ฌธ์ ์ฌ์ฉํ ๊ฒ์ ๋๋ค. ์ฌ๊ธฐ์ <%= variableName %>์ ์์ฑ ์ค์ ์ฌ์ฉ์๊ฐ ์ ๊ณตํ ์ ๋ ฅ์ผ๋ก ๋์ฒด๋ ์๋ฆฌ ํ์์๋ฅผ ๋ํ๋ ๋๋ค.
๊ธฐ๋ณธ ๋ชจ๋ ํ ํ๋ฆฟ
๋ชจ๋ ๋ชจ๋์๋ ๊ธฐ๋ณธ ๊ตฌ์กฐ๊ฐ ํ์ํฉ๋๋ค. ์ด ํ ํ๋ฆฟ์ ์ผ๋ฐ์ ์ธ ์ ํธ๋ฆฌํฐ ๋๋ ํฌํผ ๋ชจ๋์ ์ํ ๊ธฐ๋ณธ ํจํด์ ์ ๊ณตํฉ๋๋ค.
๋ชฉ์ : ๋ค๋ฅธ ๊ณณ์์ ๊ฐ์ ธ์ ์ฌ์ฉํ ์ ์๋ ๊ฐ๋จํ๊ณ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ํจ์๋ ์์๋ฅผ ์์ฑํ๊ธฐ ์ํจ์ ๋๋ค.
์์ ํ
ํ๋ฆฟ (์: templates/utility.js.ejs
):
export const <%= functionName %> = (param) => {
// ์ฌ๊ธฐ์ <%= functionName %> ๋ก์ง์ ๊ตฌํํ์ธ์
console.log(`Executing <%= functionName %> with param: ${param}`);
return `Result from <%= functionName %>: ${param}`;
};
export const <%= constantName %> = '<%= constantValue %>';
์์ฑ๋ ๊ฒฐ๊ณผ๋ฌผ (์: functionName='formatDate'
, constantName='DEFAULT_FORMAT'
, constantValue='YYYY-MM-DD'
):
export const formatDate = (param) => {
// ์ฌ๊ธฐ์ formatDate ๋ก์ง์ ๊ตฌํํ์ธ์
console.log(`Executing formatDate with param: ${param}`);
return `Result from formatDate: ${param}`;
};
export const DEFAULT_FORMAT = 'YYYY-MM-DD';
API ํด๋ผ์ด์ธํธ ๋ชจ๋ ํ ํ๋ฆฟ
์ธ๋ถ API์์ ์ํธ์์ฉ์ ๋ง์ ์ ํ๋ฆฌ์ผ์ด์ ์ ํต์ฌ ๋ถ๋ถ์ ๋๋ค. ์ด ํ ํ๋ฆฟ์ ๋ค๋ฅธ ๋ฆฌ์์ค์ ๋ํ API ์๋น์ค ๋ชจ๋ ์์ฑ์ ํ์คํํฉ๋๋ค.
๋ชฉ์ : ํน์ ๋ฐฑ์๋ ๋ฆฌ์์ค์ ๋ํ HTTP ์์ฒญ์ ๋ง๋ค๊ธฐ ์ํ ์ผ๊ด๋ ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณตํ๊ณ , ๊ธฐ๋ณธ URL ๋ฐ ์ ์ฌ์ ํค๋์ ๊ฐ์ ๊ณตํต ๊ด์ฌ์ฌ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํจ์ ๋๋ค.
์์ ํ
ํ๋ฆฟ (์: templates/api-client.js.ejs
):
import axios from 'axios';
const BASE_URL = process.env.VITE_API_BASE_URL || 'https://api.example.com';
const API_ENDPOINT = `${BASE_URL}/<%= resourceNamePlural %>`;
export const <%= resourceName %>API = {
/**
* ๋ชจ๋ <%= resourceNamePlural %>๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
* @returns {Promise
์์ฑ๋ ๊ฒฐ๊ณผ๋ฌผ (์: resourceName='user'
, resourceNamePlural='users'
):
import axios from 'axios';
const BASE_URL = process.env.VITE_API_BASE_URL || 'https://api.example.com';
const API_ENDPOINT = `${BASE_URL}/users`;
export const userAPI = {
/**
* ๋ชจ๋ ์ฌ์ฉ์๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
* @returns {Promise
์ํ ๊ด๋ฆฌ ๋ชจ๋ ํ ํ๋ฆฟ
์ํ ๊ด๋ฆฌ์ ํฌ๊ฒ ์์กดํ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฒฝ์ฐ, ํ ํ๋ฆฟ์ ์๋ก์ด ์ํ ์ฌ๋ผ์ด์ค๋ ์คํ ์ด์ ํ์ํ ๋ณด์ผ๋ฌํ๋ ์ดํธ๋ฅผ ์์ฑํ์ฌ ๊ธฐ๋ฅ ๊ฐ๋ฐ ์๋๋ฅผ ํฌ๊ฒ ๋์ผ ์ ์์ต๋๋ค.
๋ชฉ์ : ์ด๊ธฐ ์ํ, ์ก์ , ๋ฆฌ๋์๋ฅผ ํฌํจํ ์ํ ๊ด๋ฆฌ ์ํฐํฐ(์: Redux Toolkit ์ฌ๋ผ์ด์ค, Zustand ์คํ ์ด) ์์ฑ์ ํ์คํํ๊ธฐ ์ํจ์ ๋๋ค.
์์ ํ
ํ๋ฆฟ (์: Redux Toolkit ์ฌ๋ผ์ด์ค์ฉ, templates/redux-slice.js.ejs
):
import { createSlice } from '@reduxjs/toolkit';
const initialState = {
<%= property1 %>: <%= defaultValue1 %>,
<%= property2 %>: <%= defaultValue2 %>,
status: 'idle',
error: null,
};
const <%= sliceName %>Slice = createSlice({
name: '<%= sliceName %>',
initialState,
reducers: {
set<%= property1Capitalized %>: (state, action) => {
state.<%= property1 %> = action.payload;
},
set<%= property2Capitalized %>: (state, action) => {
state.<%= property2 %> = action.payload;
},
// ํ์์ ๋ฐ๋ผ ๋ ๋ง์ ๋ฆฌ๋์๋ฅผ ์ถ๊ฐํ์ธ์
},
extraReducers: (builder) => {
// ์ฌ๊ธฐ์ ๋น๋๊ธฐ thunk ๋ฆฌ๋์๋ฅผ ์ถ๊ฐํ์ธ์ (์: API ํธ์ถ)
},
});
export const { set<%= property1Capitalized %>, set<%= property2Capitalized %> } = <%= sliceName %>Slice.actions;
export default <%= sliceName %>Slice.reducer;
export const select<%= sliceNameCapitalized %> = (state) => state.<%= sliceName %>;
์์ฑ๋ ๊ฒฐ๊ณผ๋ฌผ (์: sliceName='counter'
, property1='value'
, defaultValue1=0
, property2='step'
, defaultValue2=1
):
import { createSlice } from '@reduxjs/toolkit';
const initialState = {
value: 0,
step: 1,
status: 'idle',
error: null,
};
const counterSlice = createSlice({
name: 'counter',
initialState,
reducers: {
setValue: (state, action) => {
state.value = action.payload;
},
setStep: (state, action) => {
state.step = action.payload;
},
// ํ์์ ๋ฐ๋ผ ๋ ๋ง์ ๋ฆฌ๋์๋ฅผ ์ถ๊ฐํ์ธ์
},
extraReducers: (builder) => {
// ์ฌ๊ธฐ์ ๋น๋๊ธฐ thunk ๋ฆฌ๋์๋ฅผ ์ถ๊ฐํ์ธ์ (์: API ํธ์ถ)
},
});
export const { setValue, setStep } = counterSlice.actions;
export default counterSlice.reducer;
export const selectCounter = (state) => state.counter;
UI ์ปดํฌ๋ํธ ๋ชจ๋ ํ ํ๋ฆฟ
ํ๋ก ํธ์๋ ๊ฐ๋ฐ์ ์ข ์ข ์๋ง์ ์ปดํฌ๋ํธ๋ฅผ ์์ฑํ๋ ์์ ์ ํฌํจํฉ๋๋ค. ํ ํ๋ฆฟ์ ๊ตฌ์กฐ, ์คํ์ผ๋ง ๋ฐ ๊ด๋ จ ํ์ผ์ ์ผ๊ด์ฑ์ ๋ณด์ฅํฉ๋๋ค.
๋ชฉ์ : ์ ํํ ํ๋ ์์ํฌ ๊ด๋ก์ ๋ฐ๋ผ ๋ฉ์ธ ํ์ผ, ์ ์ฉ ์คํ์ผ์ํธ, ๊ทธ๋ฆฌ๊ณ ์ ํ์ ์ผ๋ก ํ ์คํธ ํ์ผ์ ํฌํจํ ์๋ก์ด UI ์ปดํฌ๋ํธ๋ฅผ ์ค์บํด๋ฉํ๊ธฐ ์ํจ์ ๋๋ค.
์์ ํ
ํ๋ฆฟ (์: React ํจ์ํ ์ปดํฌ๋ํธ์ฉ, templates/react-component.js.ejs
):
{message}
import React from 'react';
import PropTypes from 'prop-types';
import './<%= componentName %>.css'; // ๋๋ .module.css, .scss ๋ฑ
/**
* ์ผ๋ฐ์ ์ธ <%= componentName %> ์ปดํฌ๋ํธ์
๋๋ค.
* @param {Object} props - ์ปดํฌ๋ํธ props.
* @param {string} props.message - ํ์ํ ๋ฉ์์ง.
*/
const <%= componentName %> = ({ message }) => {
return (
Hello from <%= componentName %>!
์ฐ๊ด๋ ์คํ์ผ ํ
ํ๋ฆฟ (์: templates/react-component.css.ejs
):
.<%= componentName.toLowerCase() %>-container {
padding: 1rem;
border: 1px solid #ccc;
border-radius: 4px;
background-color: #f9f9f9;
}
.<%= componentName.toLowerCase() %>-container h1 {
color: #333;
}
.<%= componentName.toLowerCase() %>-container p {
color: #666;
}
์์ฑ๋ ๊ฒฐ๊ณผ๋ฌผ (์: componentName='GreetingCard'
):
GreetingCard.js
:
{message}
import React from 'react';
import PropTypes from 'prop-types';
import './GreetingCard.css';
/**
* ์ผ๋ฐ์ ์ธ GreetingCard ์ปดํฌ๋ํธ์
๋๋ค.
* @param {Object} props - ์ปดํฌ๋ํธ props.
* @param {string} props.message - ํ์ํ ๋ฉ์์ง.
*/
const GreetingCard = ({ message }) => {
return (
Hello from GreetingCard!
GreetingCard.css
:
.greetingcard-container {
padding: 1rem;
border: 1px solid #ccc;
border-radius: 4px;
background-color: #f9f9f9;
}
.greetingcard-container h1 {
color: #333;
}
.greetingcard-container p {
color: #666;
}
ํ ์คํธ/๋ชฉ(Mock) ๋ชจ๋ ํ ํ๋ฆฟ
์ฒ์๋ถํฐ ์ข์ ํ ์คํธ ์ต๊ด์ ์ฅ๋ คํ๋ ๊ฒ์ ๋งค์ฐ ์ค์ํฉ๋๋ค. ํ ํ๋ฆฟ์ ๊ธฐ๋ณธ์ ์ธ ํ ์คํธ ํ์ผ์ด๋ ๋ชฉ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
๋ชฉ์ : ์๋ก์ด ๋ชจ๋์ด๋ ์ปดํฌ๋ํธ์ ๋ํ ํ ์คํธ ์์ฑ์ ์ํ ์์์ ์ ์ ๊ณตํ์ฌ ์ผ๊ด๋ ํ ์คํธ ์ ๊ทผ ๋ฐฉ์์ ๋ณด์ฅํ๊ธฐ ์ํจ์ ๋๋ค.
์์ ํ
ํ๋ฆฟ (์: Jest ํ
์คํธ ํ์ผ์ฉ, templates/test.js.ejs
):
import { <%= functionName %> } from './<%= moduleName %>';
describe('<%= moduleName %> - <%= functionName %>', () => {
it('์ฃผ์ด์ง ๋ฌธ์์ด์ ์ฌ๋ฐ๋ฅด๊ฒ <%= testDescription %>ํด์ผ ํฉ๋๋ค', () => {
// Arrange
const input = 'test input';
const expectedOutput = 'expected result';
// Act
const result = <%= functionName %>(input);
// Assert
expect(result).toBe(expectedOutput);
});
// ํ์์ ๋ฐ๋ผ ์ฌ๊ธฐ์ ๋ ๋ง์ ํ
์คํธ ์ผ์ด์ค๋ฅผ ์ถ๊ฐํ์ธ์
it('์ฃ์ง ์ผ์ด์ค๋ฅผ ์ฒ๋ฆฌํด์ผ ํฉ๋๋ค', () => {
// ๋น ๋ฌธ์์ด, null, undefined ๋ฑ์ผ๋ก ํ
์คํธํ์ธ์
expect(<%= functionName %>('')).toBe(''); // Placeholder
});
});
์์ฑ๋ ๊ฒฐ๊ณผ๋ฌผ (์: moduleName='utilityFunctions'
, functionName='reverseString'
, testDescription='์ญ์์ผ๋ก ๋ง๋ญ๋๋ค'
):
import { reverseString } from './utilityFunctions';
describe('utilityFunctions - reverseString', () => {
it('์ฃผ์ด์ง ๋ฌธ์์ด์ ์ฌ๋ฐ๋ฅด๊ฒ ์ญ์์ผ๋ก ๋ง๋ค์ด์ผ ํฉ๋๋ค', () => {
// Arrange
const input = 'test input';
const expectedOutput = 'expected result';
// Act
const result = reverseString(input);
// Assert
expect(result).toBe(expectedOutput);
});
// ํ์์ ๋ฐ๋ผ ์ฌ๊ธฐ์ ๋ ๋ง์ ํ
์คํธ ์ผ์ด์ค๋ฅผ ์ถ๊ฐํ์ธ์
it('์ฃ์ง ์ผ์ด์ค๋ฅผ ์ฒ๋ฆฌํด์ผ ํฉ๋๋ค', () => {
// ๋น ๋ฌธ์์ด, null, undefined ๋ฑ์ผ๋ก ํ
์คํธํ์ธ์
expect(reverseString('')).toBe(''); // Placeholder
});
});
์ฝ๋ ์์ฑ์ ์ํ ๋๊ตฌ ๋ฐ ๊ธฐ์
์๋ฐ์คํฌ๋ฆฝํธ ์ํ๊ณ๋ ๊ฐ๋จํ ํ ํ๋ฆฟ ์์ง๋ถํฐ ์ ๊ตํ AST ๊ธฐ๋ฐ ๋ณํ๊ธฐ์ ์ด๋ฅด๊ธฐ๊น์ง ์ฝ๋ ์์ฑ์ ์ฉ์ดํ๊ฒ ํ๋ ํ๋ถํ ๋๊ตฌ ์ธํธ๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ฌ๋ฐ๋ฅธ ๋๊ตฌ๋ฅผ ์ ํํ๋ ๊ฒ์ ์์ฑ ์๊ตฌ ์ฌํญ์ ๋ณต์ก์ฑ๊ณผ ํ๋ก์ ํธ์ ํน์ ์๊ตฌ ์ฌํญ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋๋ค.
ํ ํ๋ฆฟ ์์ง
์ด๊ฒ๋ค์ ๋์ ๋ฐ์ดํฐ๋ฅผ ์ ์ ํ ์คํธ ํ์ผ(ํ ํ๋ฆฟ)์ ์ฃผ์ ํ์ฌ ์ฝ๋๋ฅผ ํฌํจํ ๋์ ๊ฒฐ๊ณผ๋ฌผ์ ์์ฑํ๋ ๊ธฐ๋ณธ ๋๊ตฌ์ ๋๋ค.
- EJS (Embedded JavaScript): ํ ํ๋ฆฟ ๋ด์ ์์ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๋ฅผ ์ฝ์ ํ ์ ์๊ฒ ํด์ฃผ๋ ๋๋ฆฌ ์ฌ์ฉ๋๋ ํ ํ๋ฆฟ ์์ง์ ๋๋ค. ๋งค์ฐ ์ ์ฐํ๋ฉฐ HTML, Markdown ๋๋ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋ ์์ฒด๋ฅผ ํฌํจํ ๋ชจ๋ ํ ์คํธ ๊ธฐ๋ฐ ํ์์ ์์ฑํ๋ ๋ฐ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๊ทธ ๊ตฌ๋ฌธ์ Ruby์ ERB๋ฅผ ์ฐ์์ํค๋ฉฐ, ๋ณ์ ์ถ๋ ฅ์ ์ํด <%= ... %>๋ฅผ, ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋ ์คํ์ ์ํด <% ... %>๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์์ ํ ์๋ฐ์คํฌ๋ฆฝํธ์ ํ ๋๋ฌธ์ ์ฝ๋ ์์ฑ์ ๋๋ฆฌ ์ ํ๋ฉ๋๋ค.
- Handlebars/Mustache: ์ด๋ค์ "๋ก์ง ์๋(logic-less)" ํ ํ๋ฆฟ ์์ง์ผ๋ก, ํ ํ๋ฆฟ์ ๋ฐฐ์นํ ์ ์๋ ํ๋ก๊ทธ๋๋ฐ ๋ก์ง์ ์์ ์๋์ ์ผ๋ก ์ ํํฉ๋๋ค. ๋จ์ํ ๋ฐ์ดํฐ ๋ณด๊ฐ(์: {{variableName}})๊ณผ ๊ธฐ๋ณธ ์ ์ด ๊ตฌ์กฐ(์: {{#each}}, {{#if}})์ ์ค์ ์ ๋ก๋๋ค. ์ด ์ ์ฝ์ ๊ด์ฌ์ฌ์ ๋ถ๋ฆฌ๋ฅผ ์ด์งํ์ฌ, ๋ก์ง์ ์์ฑ๊ธฐ์ ์๊ณ ํ ํ๋ฆฟ์ ์์ํ๊ฒ ํํ์ ์ํ ๊ฒ์ด ๋๋๋ก ํฉ๋๋ค. ํ ํ๋ฆฟ ๊ตฌ์กฐ๊ฐ ๋น๊ต์ ๊ณ ์ ๋์ด ์๊ณ ๋ฐ์ดํฐ๋ง ์ฃผ์ ํ๋ฉด ๋๋ ์๋๋ฆฌ์ค์ ํ์ํฉ๋๋ค.
- Lodash ํ ํ๋ฆฟ: EJS์ ์ ์ ์ ์ผ๋ก ์ ์ฌํ Lodash์ _.template ํจ์๋ ERB์ ์ ์ฌํ ๊ตฌ๋ฌธ์ ์ฌ์ฉํ์ฌ ํ ํ๋ฆฟ์ ๊ฐ๊ฒฐํ๊ฒ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. ๋น ๋ฅธ ์ธ๋ผ์ธ ํ ํ๋ฆฟ์ด๋ Lodash๊ฐ ์ด๋ฏธ ํ๋ก์ ํธ ์ข ์์ฑ์ผ ๋ ์์ฃผ ์ฌ์ฉ๋ฉ๋๋ค.
- Pug (์ด์ Jade): ์ฃผ๋ก HTML์ ์ํด ์ค๊ณ๋, ๋ ๋จ์ ์ด๊ณ ๋ค์ฌ์ฐ๊ธฐ ๊ธฐ๋ฐ์ ํ ํ๋ฆฟ ์์ง์ ๋๋ค. ๊ฐ๊ฒฐํ HTML ์์ฑ์ ๋ฐ์ด๋์ง๋ง, ๊ทธ ๊ตฌ์กฐ๋ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ํฌํจํ ๋ค๋ฅธ ํ ์คํธ ํ์์ ์์ฑํ๋๋ก ์กฐ์ ๋ ์ ์์ต๋๋ค. ๋ค๋ง HTML ์ค์ฌ์ ์ธ ํน์ฑ ๋๋ฌธ์ ์ง์ ์ ์ธ ์ฝ๋ ์์ฑ์๋ ๋ ์ผ๋ฐ์ ์ ๋๋ค.
์ค์บํด๋ฉ ๋๊ตฌ
์ด ๋๊ตฌ๋ค์ ์ฌ๋ฌ ํ ํ๋ฆฟ ํ์ผ, ์ฌ์ฉ์ ํ๋กฌํํธ, ํ์ผ ์์คํ ์์ ์ ํฌ๊ดํ๋ ๋ณธ๊ฒฉ์ ์ธ ์ฝ๋ ์์ฑ๊ธฐ๋ฅผ ๊ตฌ์ถํ๊ธฐ ์ํ ํ๋ ์์ํฌ์ ์ถ์ํ๋ฅผ ์ ๊ณตํฉ๋๋ค.
- Yeoman: ๊ฐ๋ ฅํ๊ณ ์ฑ์ํ ์ค์บํด๋ฉ ์ํ๊ณ์ ๋๋ค. Yeoman ์์ฑ๊ธฐ("generators"๋ผ๊ณ ํจ)๋ ์ ์ฒด ํ๋ก์ ํธ ๋๋ ํ๋ก์ ํธ์ ์ผ๋ถ๋ฅผ ์์ฑํ ์ ์๋ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ปดํฌ๋ํธ์ ๋๋ค. ํ์ผ ์์คํ ๊ณผ ์ํธ ์์ฉํ๊ณ , ์ฌ์ฉ์์๊ฒ ์ ๋ ฅ์ ์์ฒญํ๋ฉฐ, ์์ฑ๊ธฐ๋ฅผ ๊ตฌ์ฑํ๊ธฐ ์ํ ํ๋ถํ API๋ฅผ ์ ๊ณตํฉ๋๋ค. Yeoman์ ํ์ต ๊ณก์ ์ด ๊ฐํ๋ฅด์ง๋ง ๋งค์ฐ ์ ์ฐํ๋ฉฐ ๋ณต์กํ ๊ธฐ์ ์์ค์ ์ค์บํด๋ฉ ์๊ตฌ์ ์ ํฉํฉ๋๋ค.
- Plop.js: ๋ ๊ฐ๋จํ๊ณ ์ง์ค๋ "๋ง์ดํฌ๋ก ์์ฑ๊ธฐ" ๋๊ตฌ์ ๋๋ค. Plop์ ๊ณตํต ํ๋ก์ ํธ ์์ (์: "์ปดํฌ๋ํธ ์์ฑ", "์คํ ์ด ์์ฑ")์ ์ํ ์๊ณ ๋ฐ๋ณต ๊ฐ๋ฅํ ์์ฑ๊ธฐ๋ฅผ ๋ง๋๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก Handlebars ํ ํ๋ฆฟ์ ์ฌ์ฉํ๋ฉฐ ํ๋กฌํํธ์ ์ก์ ์ ์ ์ํ๊ธฐ ์ํ ๊ฐ๋จํ API๋ฅผ ์ ๊ณตํฉ๋๋ค. Plop์ ์์ ํ Yeoman ์ค์ ์ ์ค๋ฒํค๋ ์์ด ๋น ๋ฅด๊ณ ์ฝ๊ฒ ๊ตฌ์ฑํ ์ ์๋ ์์ฑ๊ธฐ๊ฐ ํ์ํ ํ๋ก์ ํธ์ ํ์ํฉ๋๋ค.
- Hygen: Plop.js์ ์ ์ฌํ ๋ ๋ค๋ฅธ ๋น ๋ฅด๊ณ ๊ตฌ์ฑ ๊ฐ๋ฅํ ์ฝ๋ ์์ฑ๊ธฐ์ ๋๋ค. Hygen์ ์๋์ ๋จ์์ฑ์ ๊ฐ์กฐํ์ฌ ๊ฐ๋ฐ์๊ฐ ์ ์ํ๊ฒ ํ ํ๋ฆฟ์ ๋ง๋ค๊ณ ๋ช ๋ น์ ์คํํ์ฌ ํ์ผ์ ์์ฑํ ์ ์๋๋ก ํฉ๋๋ค. ์ง๊ด์ ์ธ ๊ตฌ๋ฌธ๊ณผ ์ต์ํ์ ๊ตฌ์ฑ์ผ๋ก ์ธ๊ธฐ๊ฐ ์์ต๋๋ค.
- NPM
create-*
/ Yarncreate-*
: ์ด๋ฌํ ๋ช ๋ น์ด(์: create-react-app, create-next-app)๋ ์ข ์ข ๋ฏธ๋ฆฌ ์ ์๋ ํ ํ๋ฆฟ์์ ์๋ก์ด ํ๋ก์ ํธ๋ฅผ ์์ํ๋ ์ค์บํด๋ฉ ๋๊ตฌ๋ ์ฌ์ฉ์ ์ง์ ์คํฌ๋ฆฝํธ์ ๋ํผ์ ๋๋ค. ์๋ก์ด ํ๋ก์ ํธ๋ฅผ ๋ถํธ์คํธ๋ฉํ๋ ๋ฐ ์๋ฒฝํ์ง๋ง, ๋ง์ถค ์ ์๋์ง ์๋ ํ ๊ธฐ์กด ํ๋ก์ ํธ ๋ด์์ ๊ฐ๋ณ ๋ชจ๋์ ์์ฑํ๋ ๋ฐ๋ ๋ ์ ํฉํฉ๋๋ค.
AST ๊ธฐ๋ฐ ์ฝ๋ ๋ณํ
์ถ์ ๊ตฌ๋ฌธ ํธ๋ฆฌ(AST)๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ฝ๋๋ฅผ ๋ถ์, ์์ ๋๋ ์์ฑํด์ผ ํ๋ ๋ ๊ณ ๊ธ ์๋๋ฆฌ์ค์ ๊ฒฝ์ฐ, ์ด๋ฌํ ๋๊ตฌ๋ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
- Babel (ํ๋ฌ๊ทธ์ธ): Babel์ ์ฃผ๋ก ์ต์ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ด์ ๋ฒ์ ๊ณผ ํธํ๋๋ ๋ฒ์ ์ผ๋ก ๋ณํํ๋ ์๋ฐ์คํฌ๋ฆฝํธ ์ปดํ์ผ๋ฌ๋ก ์๋ ค์ ธ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ํ๋ฌ๊ทธ์ธ ์์คํ ์ ๊ฐ๋ ฅํ AST ์กฐ์์ ํ์ฉํฉ๋๋ค. ์ฌ์ฉ์ ์ง์ Babel ํ๋ฌ๊ทธ์ธ์ ์์ฑํ์ฌ ์ฝ๋๋ฅผ ๋ถ์ํ๊ณ , ์ ์ฝ๋๋ฅผ ์ฃผ์ ํ๊ณ , ๊ธฐ์กด ๊ตฌ์กฐ๋ฅผ ์์ ํ๊ฑฐ๋, ํน์ ๊ธฐ์ค์ ๋ฐ๋ผ ์ ์ฒด ๋ชจ๋์ ์์ฑํ ์๋ ์์ต๋๋ค. ์ด๋ ๋ณต์กํ ์ฝ๋ ์ต์ ํ, ์ธ์ด ํ์ฅ ๋๋ ์ฌ์ฉ์ ์ง์ ๋น๋ ์ ์ฝ๋ ์์ฑ์ ์ฌ์ฉ๋ฉ๋๋ค.
- Recast/jscodeshift: ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ๋๊ท๋ชจ ์ฝ๋๋ฒ ์ด์ค ๋ฆฌํฉํ ๋ง์ ์๋ํํ๋ ์คํฌ๋ฆฝํธ์ธ "์ฝ๋๋ชจ๋(codemods)"๋ฅผ ์์ฑํ๊ธฐ ์ํด ์ค๊ณ๋์์ต๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ AST๋ก ํ์ฑํ๊ณ , AST๋ฅผ ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ผ๋ก ์กฐ์ํ ๋ค์, ๊ฐ๋ฅํ ํ ์์์ ๋ณด์กดํ๋ฉด์ ์์ ๋ AST๋ฅผ ๋ค์ ์ฝ๋๋ก ์ถ๋ ฅํ ์ ์์ต๋๋ค. ์ฃผ๋ก ๋ณํ์ ์ฌ์ฉ๋์ง๋ง, ๊ตฌ์กฐ์ ๋ฐ๋ผ ๊ธฐ์กด ํ์ผ์ ์ฝ๋๋ฅผ ์ฝ์ ํด์ผ ํ๋ ๊ณ ๊ธ ์์ฑ ์๋๋ฆฌ์ค์๋ ์ฌ์ฉํ ์ ์์ต๋๋ค.
- TypeScript ์ปดํ์ผ๋ฌ API: TypeScript ํ๋ก์ ํธ์ ๊ฒฝ์ฐ, TypeScript ์ปดํ์ผ๋ฌ API๋ TypeScript ์ปดํ์ผ๋ฌ์ ๊ธฐ๋ฅ์ ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ผ๋ก ์ ๊ทผํ ์ ์๊ฒ ํด์ค๋๋ค. TypeScript ํ์ผ์ AST๋ก ํ์ฑํ๊ณ , ํ์ ๊ฒ์ฌ๋ฅผ ์ํํ๋ฉฐ, ์๋ฐ์คํฌ๋ฆฝํธ ๋๋ ์ ์ธ ํ์ผ์ ์์ฑํ ์ ์์ต๋๋ค. ์ด๋ ํ์ -์์ ํ ์ฝ๋๋ฅผ ์์ฑํ๊ฑฐ๋, ์ฌ์ฉ์ ์ง์ ์ธ์ด ์๋น์ค๋ฅผ ๋ง๋ค๊ฑฐ๋, TypeScript ์ปจํ ์คํธ ๋ด์์ ์ ๊ตํ ์ฝ๋ ๋ถ์ ๋ฐ ์์ฑ ๋๊ตฌ๋ฅผ ๊ตฌ์ถํ๋ ๋ฐ ๋งค์ฐ ์ ์ฉํฉ๋๋ค.
GraphQL ์ฝ๋ ์์ฑ
GraphQL API์ ์ํธ ์์ฉํ๋ ํ๋ก์ ํธ์ ๊ฒฝ์ฐ, ํนํ๋ ์ฝ๋ ์์ฑ๊ธฐ๋ ํ์ ์์ ์ฑ์ ์ ์งํ๊ณ ์๋ ์์ ์ ์ค์ด๋ ๋ฐ ๋งค์ฐ ์ค์ํฉ๋๋ค.
- GraphQL Code Generator: ์ด๊ฒ์ GraphQL ์คํค๋ง๋ก๋ถํฐ ์ฝ๋(ํ์ , ํ , ์ปดํฌ๋ํธ, API ํด๋ผ์ด์ธํธ)๋ฅผ ์์ฑํ๋ ๋งค์ฐ ์ธ๊ธฐ ์๋ ๋๊ตฌ์ ๋๋ค. ๋ค์ํ ์ธ์ด์ ํ๋ ์์ํฌ(TypeScript, React ํ , Apollo Client ๋ฑ)๋ฅผ ์ง์ํฉ๋๋ค. ์ด๋ฅผ ์ฌ์ฉํจ์ผ๋ก์จ ๊ฐ๋ฐ์๋ค์ ํด๋ผ์ด์ธํธ ์ธก ์ฝ๋๊ฐ ํญ์ ๋ฐฑ์๋ GraphQL ์คํค๋ง์ ๋๊ธฐํ๋๋๋ก ๋ณด์ฅํ์ฌ ๋ฐ์ดํฐ ๋ถ์ผ์น์ ๊ด๋ จ๋ ๋ฐํ์ ์ค๋ฅ๋ฅผ ๋ํญ ์ค์ผ ์ ์์ต๋๋ค. ์ด๋ ์ ์ธ์ ๋ช ์ธ๋ก๋ถํฐ ๊ฒฌ๊ณ ํ ๋ชจ๋(์: ํ์ ์ ์ ๋ชจ๋, ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ ๋ชจ๋)์ ์์ฑํ๋ ๋ํ์ ์ธ ์์ ๋๋ค.
๋๋ฉ์ธ ํนํ ์ธ์ด(DSL) ๋๊ตฌ
์ผ๋ถ ๋ณต์กํ ์๋๋ฆฌ์ค์์๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ํน์ ์๊ตฌ ์ฌํญ์ ์ค๋ช ํ๊ธฐ ์ํด ์์ ๋ง์ ์ฌ์ฉ์ ์ง์ DSL์ ์ ์ํ ๋ค์, ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ ํด๋น DSL์์ ์ฝ๋๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
- ์ฌ์ฉ์ ์ง์ ํ์ ๋ฐ ์์ฑ๊ธฐ: ๊ธฐ์ฑ ์๋ฃจ์ ์ผ๋ก ํด๊ฒฐ๋์ง ์๋ ๊ณ ์ ํ ํ๋ก์ ํธ ์๊ตฌ ์ฌํญ์ ๊ฒฝ์ฐ, ํ์ ์ฌ์ฉ์ ์ง์ DSL์ ์ํ ์์ฒด ํ์๋ฅผ ๊ฐ๋ฐํ ๋ค์ ํด๋น DSL์ ์๋ฐ์คํฌ๋ฆฝํธ ๋ชจ๋๋ก ๋ณํํ๋ ์์ฑ๊ธฐ๋ฅผ ์์ฑํ ์ ์์ต๋๋ค. ์ด ์ ๊ทผ ๋ฐฉ์์ ์ต๊ณ ์ ์ ์ฐ์ฑ์ ์ ๊ณตํ์ง๋ง ์ฌ์ฉ์ ์ง์ ๋๊ตฌ๋ฅผ ๊ตฌ์ถํ๊ณ ์ ์ง ๊ด๋ฆฌํ๋ ์ค๋ฒํค๋๊ฐ ๋ฐ๋ฆ ๋๋ค.
์ฝ๋ ์์ฑ ๊ตฌํ: ์ค์ฉ์ ์ธ ์ํฌํ๋ก์ฐ
์ฝ๋ ์์ฑ์ ์ค์ ๋ก ์ ์ฉํ๋ ค๋ฉด ๋ฐ๋ณต์ ์ธ ํจํด์ ์๋ณํ๋ ๊ฒ๋ถํฐ ์์ฑ ํ๋ก์ธ์ค๋ฅผ ์ผ์์ ์ธ ๊ฐ๋ฐ ํ๋ฆ์ ํตํฉํ๋ ๊ฒ๊น์ง ๊ตฌ์กฐํ๋ ์ ๊ทผ ๋ฐฉ์์ด ํ์ํฉ๋๋ค. ๋ค์์ ์ค์ฉ์ ์ธ ์ํฌํ๋ก์ฐ์ ๋๋ค:
ํจํด ์ ์
์ฒซ ๋ฒ์งธ์ด์ ๊ฐ์ฅ ์ค์ํ ๋จ๊ณ๋ ์์ฑํ ๋์์ ์๋ณํ๋ ๊ฒ์ ๋๋ค. ์ด๋ฅผ ์ํด์๋ ์ฝ๋๋ฒ ์ด์ค์ ๊ฐ๋ฐ ํ๋ก์ธ์ค์ ๋ํ ์ธ์ฌํ ๊ด์ฐฐ์ด ํ์ํฉ๋๋ค:
- ๋ฐ๋ณต์ ์ธ ๊ตฌ์กฐ ์๋ณ: ์ ์ฌํ ๊ตฌ์กฐ๋ฅผ ๊ณต์ ํ์ง๋ง ์ด๋ฆ์ด๋ ํน์ ๊ฐ๋ง ๋ค๋ฅธ ํ์ผ์ด๋ ์ฝ๋ ๋ธ๋ก์ ์ฐพ์ผ์ญ์์ค. ์ผ๋ฐ์ ์ธ ํ๋ณด๋ก๋ ์๋ก์ด ๋ฆฌ์์ค๋ฅผ ์ํ API ํด๋ผ์ด์ธํธ, UI ์ปดํฌ๋ํธ(๊ด๋ จ CSS ๋ฐ ํ ์คํธ ํ์ผ ํฌํจ), ์ํ ๊ด๋ฆฌ ์ฌ๋ผ์ด์ค/์คํ ์ด, ์ ํธ๋ฆฌํฐ ๋ชจ๋, ๋๋ ์ ์ฒด ์ ๊ท ๊ธฐ๋ฅ ๋๋ ํ ๋ฆฌ๊ฐ ์์ต๋๋ค.
- ๋ช ํํ ํ ํ๋ฆฟ ํ์ผ ์ค๊ณ: ํจํด์ ์๋ณํ ํ์๋ ๊ณตํต ๊ตฌ์กฐ๋ฅผ ํฌ์ฐฉํ๋ ์ผ๋ฐ ํ ํ๋ฆฟ ํ์ผ์ ๋ง๋์ญ์์ค. ์ด ํ ํ๋ฆฟ์๋ ๋์ ์ธ ๋ถ๋ถ์ ์ํ ์๋ฆฌ ํ์์๊ฐ ํฌํจ๋ฉ๋๋ค. ์์ฑ ์ ๊ฐ๋ฐ์๊ฐ ์ ๊ณตํด์ผ ํ๋ ์ ๋ณด(์: ์ปดํฌ๋ํธ ์ด๋ฆ, API ๋ฆฌ์์ค ์ด๋ฆ, ์ก์ ๋ชฉ๋ก)์ ๋ํด ์๊ฐํด๋ณด์ญ์์ค.
- ๋ณ์/๋งค๊ฐ๋ณ์ ๊ฒฐ์ : ๊ฐ ํ ํ๋ฆฟ์ ๋ํด ์ฃผ์ ๋ ๋ชจ๋ ๋์ ๋ณ์๋ฅผ ๋์ดํ์ญ์์ค. ์๋ฅผ ๋ค์ด, ์ปดํฌ๋ํธ ํ ํ๋ฆฟ์๋ componentName, props ๋๋ hasStyles๊ฐ ํ์ํ ์ ์์ต๋๋ค. API ํด๋ผ์ด์ธํธ์ ๊ฒฝ์ฐ resourceName, endpoints, baseURL์ด ๋ ์ ์์ต๋๋ค.
๋๊ตฌ ์ ํ
ํ๋ก์ ํธ์ ๊ท๋ชจ, ๋ณต์ก์ฑ, ํ์ ์ ๋ฌธ์ฑ์ ๊ฐ์ฅ ์ ํฉํ ์ฝ๋ ์์ฑ ๋๊ตฌ๋ฅผ ์ ํํ์ญ์์ค. ๋ค์ ์์๋ฅผ ๊ณ ๋ คํ์ญ์์ค:
- ์์ฑ์ ๋ณต์ก์ฑ: ๊ฐ๋จํ ํ์ผ ์ค์บํด๋ฉ์ ๊ฒฝ์ฐ Plop.js๋ Hygen์ผ๋ก ์ถฉ๋ถํ ์ ์์ต๋๋ค. ๋ณต์กํ ํ๋ก์ ํธ ์ค์ ์ด๋ ๊ณ ๊ธ AST ๋ณํ์ ๊ฒฝ์ฐ Yeoman์ด๋ ์ฌ์ฉ์ ์ง์ Babel ํ๋ฌ๊ทธ์ธ์ด ํ์ํ ์ ์์ต๋๋ค. GraphQL ํ๋ก์ ํธ๋ GraphQL Code Generator์ ํฐ ์ด์ ์ ์ป์ ๊ฒ์ ๋๋ค.
- ๊ธฐ์กด ๋น๋ ์์คํ ๊ณผ์ ํตํฉ: ์ ํํ ๋๊ตฌ๊ฐ ๊ธฐ์กด์ Webpack, Rollup ๋๋ Vite ๊ตฌ์ฑ๊ณผ ์ผ๋ง๋ ์ ํตํฉ๋ฉ๋๊น? NPM ์คํฌ๋ฆฝํธ๋ฅผ ํตํด ์ฝ๊ฒ ์คํํ ์ ์์ต๋๊น?
- ํ์ ์น์๋: ํ์ด ํธ์ํ๊ฒ ๋ฐฐ์ฐ๊ณ ์ ์ง ๊ด๋ฆฌํ ์ ์๋ ๋๊ตฌ๋ฅผ ์ ํํ์ญ์์ค. ๊ฐํ๋ฅธ ํ์ต ๊ณก์ ๋๋ฌธ์ ์ฌ์ฉ๋์ง ์๋ ๊ฐ๋ ฅํ ๋๊ตฌ๋ณด๋ค ์ฌ์ฉ๋๋ ๋ ๊ฐ๋จํ ๋๊ตฌ๊ฐ ๋ซ์ต๋๋ค.
์์ฑ๊ธฐ ๋ง๋ค๊ธฐ
๋ชจ๋ ์ค์บํด๋ฉ์ ๋๋ฆฌ ์ฌ์ฉ๋๋ Plop.js๋ฅผ ์๋ก ๋ค์ด ์ค๋ช ํ๊ฒ ์ต๋๋ค. Plop์ ๊ฐ๋ณ๊ณ ๊ฐ๋จํ์ฌ ๋ง์ ํ์๊ฒ ํ๋ฅญํ ์ถ๋ฐ์ ์ด ๋ฉ๋๋ค.
1. Plop ์ค์น:
npm install --save-dev plop
# ๋๋
yarn add --dev plop
2. ํ๋ก์ ํธ ๋ฃจํธ์ plopfile.js
์์ฑ: ์ด ํ์ผ์ ์์ฑ๊ธฐ๋ฅผ ์ ์ํฉ๋๋ค.
// plopfile.js
module.exports = function (plop) {
plop.setGenerator('component', {
description: '์คํ์ผ๊ณผ ํ
์คํธ๊ฐ ํฌํจ๋ React ํจ์ํ ์ปดํฌ๋ํธ๋ฅผ ์์ฑํฉ๋๋ค',
prompts: [
{
type: 'input',
name: 'name',
message: '์ปดํฌ๋ํธ ์ด๋ฆ์ ๋ฌด์์ธ๊ฐ์? (์: Button, UserProfile)',
validate: function (value) {
if ((/.+/).test(value)) { return true; }
return '์ปดํฌ๋ํธ ์ด๋ฆ์ ํ์์
๋๋ค';
}
},
{
type: 'confirm',
name: 'hasStyles',
message: '์ด ์ปดํฌ๋ํธ์ ๋ณ๋์ CSS ํ์ผ์ด ํ์ํ๊ฐ์?',
default: true,
},
{
type: 'confirm',
name: 'hasTests',
message: '์ด ์ปดํฌ๋ํธ์ ํ
์คํธ ํ์ผ์ด ํ์ํ๊ฐ์?',
default: true,
}
],
actions: (data) => {
const actions = [];
// ๋ฉ์ธ ์ปดํฌ๋ํธ ํ์ผ
actions.push({
type: 'add',
path: 'src/components/{{pascalCase name}}/{{pascalCase name}}.js',
templateFile: 'plop-templates/component/component.js.hbs',
});
// ์์ฒญ ์ ์คํ์ผ ํ์ผ ์ถ๊ฐ
if (data.hasStyles) {
actions.push({
type: 'add',
path: 'src/components/{{pascalCase name}}/{{pascalCase name}}.css',
templateFile: 'plop-templates/component/component.css.hbs',
});
}
// ์์ฒญ ์ ํ
์คํธ ํ์ผ ์ถ๊ฐ
if (data.hasTests) {
actions.push({
type: 'add',
path: 'src/components/{{pascalCase name}}/{{pascalCase name}}.test.js',
templateFile: 'plop-templates/component/component.test.js.hbs',
});
}
return actions;
}
});
};
3. ํ
ํ๋ฆฟ ํ์ผ ์์ฑ (์: plop-templates/component
๋๋ ํ ๋ฆฌ ๋ด):
plop-templates/component/component.js.hbs
:
์ด๊ฒ์ ์์ฑ๋ ์ปดํฌ๋ํธ์
๋๋ค.
import React from 'react';
{{#if hasStyles}}
import './{{pascalCase name}}.css';
{{/if}}
const {{pascalCase name}} = () => {
return (
{{pascalCase name}} ์ปดํฌ๋ํธ
plop-templates/component/component.css.hbs
:
.{{dashCase name}}-container {
padding: 15px;
border: 1px solid #ddd;
border-radius: 5px;
margin-bottom: 10px;
}
.{{dashCase name}}-container h1 {
color: #333;
}
plop-templates/component/component.test.js.hbs
:
import React from 'react';
import { render, screen } from '@testing-library/react';
import {{pascalCase name}} from './{{pascalCase name}}';
describe('{{pascalCase name}} ์ปดํฌ๋ํธ', () => {
it('์ ์์ ์ผ๋ก ๋ ๋๋ง๋ฉ๋๋ค', () => {
render(<{{pascalCase name}} />);
expect(screen.getByText('{{pascalCase name}} ์ปดํฌ๋ํธ')).toBeInTheDocument();
});
});
4. ์์ฑ๊ธฐ ์คํ:
npx plop component
Plop์ ์ปดํฌ๋ํธ ์ด๋ฆ, ์คํ์ผ ํ์ ์ฌ๋ถ, ํ ์คํธ ํ์ ์ฌ๋ถ๋ฅผ ๋ฌป๊ณ ํ ํ๋ฆฟ์ ๋ฐ๋ผ ํ์ผ์ ์์ฑํฉ๋๋ค.
๊ฐ๋ฐ ์ํฌํ๋ก์ฐ์ ํตํฉํ๊ธฐ
์ํํ ์ฌ์ฉ์ ์ํด ์์ฑ๊ธฐ๋ฅผ ํ๋ก์ ํธ ์ํฌํ๋ก์ฐ์ ํตํฉํ์ญ์์ค:
package.json
์ ์คํฌ๋ฆฝํธ ์ถ๊ฐ: ๋ชจ๋ ๊ฐ๋ฐ์๊ฐ ์์ฑ๊ธฐ๋ฅผ ์ฝ๊ฒ ์คํํ ์ ์๋๋ก ๋ง๋์ญ์์ค.- ์์ฑ๊ธฐ ์ฌ์ฉ๋ฒ ๋ฌธ์ํ: ์์ฑ๊ธฐ ์ฌ์ฉ ๋ฐฉ๋ฒ, ์ด๋ค ์ ๋ ฅ์ ๊ธฐ๋ํ๋์ง, ์ด๋ค ํ์ผ์ ์์ฑํ๋์ง์ ๋ํ ๋ช ํํ ์ง์นจ์ ์ ๊ณตํ์ญ์์ค. ์ด ๋ฌธ์๋ ์์น๋ ์ธ์ด ๋ฐฐ๊ฒฝ์ ๊ด๊ณ์์ด ๋ชจ๋ ํ์์ด ์ฝ๊ฒ ์ ๊ทผํ ์ ์์ด์ผ ํฉ๋๋ค (๋จ, ๋ฌธ์ ์์ฒด๋ ๊ธ๋ก๋ฒ ํ์ ์ํด ํ๋ก์ ํธ์ ์ฃผ ์ธ์ด, ์ผ๋ฐ์ ์ผ๋ก ์์ด๋ก ์ ์ง๋์ด์ผ ํฉ๋๋ค).
- ํ ํ๋ฆฟ ๋ฒ์ ๊ด๋ฆฌ: ํ ํ๋ฆฟ๊ณผ ์์ฑ๊ธฐ ๊ตฌ์ฑ(์: plopfile.js)์ ๋ฒ์ ๊ด๋ฆฌ ์์คํ ์์ ์ผ๊ธ ์๋ฏผ์ผ๋ก ์ทจ๊ธํ์ญ์์ค. ์ด๋ ๋ชจ๋ ๊ฐ๋ฐ์๊ฐ ๋์ผํ ์ต์ ํจํด์ ์ฌ์ฉํ๋๋ก ๋ณด์ฅํฉ๋๋ค.
{
"name": "my-project",
"version": "1.0.0",
"scripts": {
"generate": "plop",
"generate:component": "plop component",
"generate:api": "plop api-client"
},
"devDependencies": {
"plop": "^3.0.0"
}
}
์ด์ ๊ฐ๋ฐ์๋ค์ ๊ฐ๋จํ npm run generate:component๋ฅผ ์คํํ ์ ์์ต๋๋ค.
๊ณ ๊ธ ๊ณ ๋ ค์ฌํญ ๋ฐ ๋ชจ๋ฒ ์ฌ๋ก
์ฝ๋ ์์ฑ์ ์๋นํ ์ด์ ์ ์ ๊ณตํ์ง๋ง, ํจ๊ณผ์ ์ธ ๊ตฌํ์ ์ํด์๋ ์ผ๋ฐ์ ์ธ ํจ์ ์ ํผํ๊ธฐ ์ํ ์ ์คํ ๊ณํ๊ณผ ๋ชจ๋ฒ ์ฌ๋ก ์ค์๊ฐ ํ์ํฉ๋๋ค.
์์ฑ๋ ์ฝ๋ ์ ์ง๋ณด์
์ฝ๋ ์์ฑ๊ณผ ๊ด๋ จํ์ฌ ๊ฐ์ฅ ์์ฃผ ๋ฌป๋ ์ง๋ฌธ ์ค ํ๋๋ ์์ฑ๋ ํ์ผ์ ๋ณ๊ฒฝ ์ฌํญ์ ์ด๋ป๊ฒ ์ฒ๋ฆฌํด์ผ ํ๋๊ฐ์ ๋๋ค. ๋ค์ ์์ฑํด์ผ ํ ๊น์? ์๋์ผ๋ก ์์ ํด์ผ ํ ๊น์?
- ์ฌ์์ฑ vs. ์๋ ์์ ์์ :
- ์ฌ์์ฑ: ๊ฐ๋ฐ์๊ฐ ์ง์ ํธ์งํ ๊ฐ๋ฅ์ฑ์ด ๊ฑฐ์ ์๋ ๋ณด์ผ๋ฌํ๋ ์ดํธ ์ฝ๋(์: GraphQL ํ์ , ๋ฐ์ดํฐ๋ฒ ์ด์ค ์คํค๋ง ๋ง์ด๊ทธ๋ ์ด์ , ์ผ๋ถ API ํด๋ผ์ด์ธํธ ์คํ )์ ์ด์์ ์ ๋๋ค. ์ง์ค์ ์์ฒ(์คํค๋ง, ํ ํ๋ฆฟ)์ด ๋ณ๊ฒฝ๋๋ฉด ์ฌ์์ฑ์ ํตํด ์ผ๊ด์ฑ์ ๋ณด์ฅํฉ๋๋ค.
- ์๋ ์์ : ์์์ ์ผ๋ก ์ฌ์ฉ๋์ง๋ง ๋ง์ด ์ปค์คํฐ๋ง์ด์ง๋ ๊ฒ์ผ๋ก ์์๋๋ ํ์ผ(์: UI ์ปดํฌ๋ํธ, ๋น์ฆ๋์ค ๋ก์ง ๋ชจ๋)์ ๊ฒฝ์ฐ. ์ฌ๊ธฐ์๋ ์์ฑ๊ธฐ๊ฐ ์ค์บํด๋๋ฅผ ์ ๊ณตํ๊ณ ํ์ ๋ณ๊ฒฝ์ ์๋์ผ๋ก ์ด๋ฃจ์ด์ง๋๋ค.
- ํผํฉ ์ ๊ทผ ์ ๋ต:
// @codegen-ignore
๋ง์ปค: ์ผ๋ถ ๋๊ตฌ๋ ์ฌ์ฉ์ ์ง์ ์คํฌ๋ฆฝํธ๋ ์์ฑ๋ ํ์ผ ๋ด์ // @codegen-ignore์ ๊ฐ์ ์ฃผ์์ ํฌํจํ ์ ์๊ฒ ํฉ๋๋ค. ๊ทธ๋ฌ๋ฉด ์์ฑ๊ธฐ๋ ์ด ์ฃผ์์ผ๋ก ํ์๋ ์น์ ์ ๋ฎ์ด์ฐ์ง ์๋๋ก ์ดํดํ์ฌ ๊ฐ๋ฐ์๊ฐ ์์ ํ๊ฒ ์ฌ์ฉ์ ์ง์ ๋ก์ง์ ์ถ๊ฐํ ์ ์์ต๋๋ค.- ์์ฑ๋ ํ์ผ ๋ถ๋ฆฌ: ํน์ ์ ํ์ ํ์ผ(์: ํ์ ์ ์, API ์ธํฐํ์ด์ค)์ ์ ์ฉ /src/generated ๋๋ ํ ๋ฆฌ์ ์์ฑํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ธ ๊ดํ์ ๋๋ค. ๊ฐ๋ฐ์๋ค์ ์ด ํ์ผ๋ค์์ ๊ฐ์ ธ์ค์ง๋ง ์ง์ ์์ ํ๋ ๊ฒฝ์ฐ๋ ๋๋ญ ๋๋ค. ๊ทธ๋ค ์์ ์ ๋น์ฆ๋์ค ๋ก์ง์ ๋ณ๋์ ์๋์ผ๋ก ์ ์ง ๊ด๋ฆฌ๋๋ ํ์ผ์ ์์นํฉ๋๋ค.
- ํ ํ๋ฆฟ ๋ฒ์ ๊ด๋ฆฌ: ํ ํ๋ฆฟ์ ์ ๊ธฐ์ ์ผ๋ก ์ ๋ฐ์ดํธํ๊ณ ๋ฒ์ ์ ๊ด๋ฆฌํ์ญ์์ค. ํต์ฌ ํจํด์ด ๋ณ๊ฒฝ๋๋ฉด ๋จผ์ ํ ํ๋ฆฟ์ ์ ๋ฐ์ดํธํ ๋ค์, ๊ฐ๋ฐ์์๊ฒ ์ํฅ์ ๋ฐ๋ ๋ชจ๋์ ๋ค์ ์์ฑํ๋๋ก ์๋ฆฌ๊ฑฐ๋(ํด๋นํ๋ ๊ฒฝ์ฐ) ๋ง์ด๊ทธ๋ ์ด์ ๊ฐ์ด๋๋ฅผ ์ ๊ณตํ์ญ์์ค.
์ฌ์ฉ์ ์ ์ ๋ฐ ํ์ฅ์ฑ
ํจ๊ณผ์ ์ธ ์์ฑ๊ธฐ๋ ์ผ๊ด์ฑ์ ๊ฐ์ ํ๋ ๊ฒ๊ณผ ํ์ํ ์ ์ฐ์ฑ์ ํ์ฉํ๋ ๊ฒ ์ฌ์ด์ ๊ท ํ์ ๋ง์ถฅ๋๋ค.
- ์ฌ์ ์ ๋๋ ํ ํ์ฉ: ํ ํ๋ฆฟ์ "ํ "์ด๋ ํ์ฅ ์ง์ ์ ํฌํจํ๋๋ก ์ค๊ณํ์ญ์์ค. ์๋ฅผ ๋ค์ด, ์ปดํฌ๋ํธ ํ ํ๋ฆฟ์๋ ์ฌ์ฉ์ ์ง์ props๋ ์ถ๊ฐ ์๋ช ์ฃผ๊ธฐ ๋ฉ์๋๋ฅผ ์ํ ์ฃผ์ ์น์ ์ด ํฌํจ๋ ์ ์์ต๋๋ค.
- ๊ณ์ธตํ๋ ํ ํ๋ฆฟ: ๊ธฐ๋ณธ ํ ํ๋ฆฟ์ด ํต์ฌ ๊ตฌ์กฐ๋ฅผ ์ ๊ณตํ๊ณ , ํ๋ก์ ํธ๋ณ ๋๋ ํ๋ณ ํ ํ๋ฆฟ์ด ๊ทธ ์ผ๋ถ๋ฅผ ํ์ฅํ๊ฑฐ๋ ์ฌ์ ์ํ ์ ์๋ ์์คํ ์ ๊ตฌํํ์ญ์์ค. ์ด๋ ๊ณตํต ๊ธฐ๋ฐ์ ๊ณต์ ํ์ง๋ง ํนํ๋ ์ ์์ด ํ์ํ ์ฌ๋ฌ ํ์ด๋ ์ ํ์ ๊ฐ์ง ๋๊ท๋ชจ ์กฐ์ง์์ ํนํ ์ ์ฉํฉ๋๋ค.
์ค๋ฅ ์ฒ๋ฆฌ ๋ฐ ์ ํจ์ฑ ๊ฒ์ฌ
๊ฒฌ๊ณ ํ ์์ฑ๊ธฐ๋ ์ ํจํ์ง ์์ ์ ๋ ฅ์ ์ฐ์ํ๊ฒ ์ฒ๋ฆฌํ๊ณ ๋ช ํํ ํผ๋๋ฐฑ์ ์ ๊ณตํด์ผ ํฉ๋๋ค.
- ์์ฑ๊ธฐ ๋งค๊ฐ๋ณ์ ์ ๋ ฅ ์ ํจ์ฑ ๊ฒ์ฌ: ์ฌ์ฉ์ ํ๋กฌํํธ์ ๋ํ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ๊ตฌํํ์ญ์์ค(์: ์ปดํฌ๋ํธ ์ด๋ฆ์ด PascalCase์ธ์ง ํ์ธํ๊ฑฐ๋ ํ์ ํ๋๊ฐ ๋น์ด ์์ง ์์์ง ํ์ธ). ๋๋ถ๋ถ์ ์ค์บํด๋ฉ ๋๊ตฌ(Yeoman, Plop.js ๋ฑ)๋ ํ๋กฌํํธ์ ๋ํ ๋ด์ฅ ์ ํจ์ฑ ๊ฒ์ฌ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
- ๋ช ํํ ์ค๋ฅ ๋ฉ์์ง: ์์ฑ์ ์คํจํ ๊ฒฝ์ฐ(์: ํ์ผ์ด ์ด๋ฏธ ์กด์ฌํ์ฌ ๋ฎ์ด์ธ ์ ์๊ฑฐ๋ ํ ํ๋ฆฟ ๋ณ์๊ฐ ๋๋ฝ๋ ๊ฒฝ์ฐ), ๊ฐ๋ฐ์๊ฐ ํด๊ฒฐ์ฑ ์ ์ฐพ์ ์ ์๋๋ก ์ ๋ณด๋ฅผ ์ ๊ณตํ๋ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ ๊ณตํ์ญ์์ค.
CI/CD์์ ํตํฉ
๊ฐ๋ณ ๋ชจ๋ ์ค์บํด๋ฉ์๋ ๋ ์ผ๋ฐ์ ์ด์ง๋ง, ์ฝ๋ ์์ฑ์ CI/CD ํ์ดํ๋ผ์ธ์ ์ผ๋ถ๊ฐ ๋ ์ ์์ผ๋ฉฐ, ํนํ ์คํค๋ง ๊ธฐ๋ฐ ์์ฑ์ ๊ฒฝ์ฐ ๋์ฑ ๊ทธ๋ ์ต๋๋ค.
- ํ๊ฒฝ ์ ๋ฐ์ ๊ฑธ์ณ ํ ํ๋ฆฟ ์ผ๊ด์ฑ ๋ณด์ฅ: CI/CD ์์คํ ์์ ์ ๊ทผํ ์ ์๋ ์ค์ ์ง์ค์ ๋ฒ์ ๊ด๋ฆฌ ์ ์ฅ์์ ํ ํ๋ฆฟ์ ์ ์ฅํ์ญ์์ค.
- ๋น๋ ๋จ๊ณ์ ์ผ๋ถ๋ก ์ฝ๋ ์์ฑ: GraphQL ํ์ ์์ฑ์ด๋ OpenAPI ํด๋ผ์ด์ธํธ ์์ฑ๊ณผ ๊ฐ์ ๊ฒฝ์ฐ, CI ํ์ดํ๋ผ์ธ์ ์ฌ์ ๋น๋ ๋จ๊ณ๋ก ์์ฑ๊ธฐ๋ฅผ ์คํํ๋ฉด ๋ชจ๋ ์์ฑ๋ ์ฝ๋๊ฐ ์ต์ ์ํ์ด๊ณ ๋ฐฐํฌ ์ ๋ฐ์ ๊ฑธ์ณ ์ผ๊ด๋จ์ ๋ณด์ฅํฉ๋๋ค. ์ด๋ ์ค๋๋ ์์ฑ ํ์ผ๊ณผ ๊ด๋ จ๋ "๋ด ์ปดํจํฐ์์๋ ๋๋๋ฐ" ๋ฌธ์ ๋ฅผ ๋ฐฉ์งํฉ๋๋ค.
๊ธ๋ก๋ฒ ํ ํ์
์ฝ๋ ์์ฑ์ ๊ธ๋ก๋ฒ ๊ฐ๋ฐํ์ ์ํ ๊ฐ๋ ฅํ ์กฐ๋ ฅ์์ ๋๋ค.
- ์ค์ ์ง์ค์ ํ ํ๋ฆฟ ์ ์ฅ์: ์์น์ ๊ด๊ณ์์ด ๋ชจ๋ ํ์ด ์ ๊ทผํ๊ณ ๊ธฐ์ฌํ ์ ์๋ ์ค์ ์ ์ฅ์์ ํต์ฌ ํ ํ๋ฆฟ๊ณผ ์์ฑ๊ธฐ ๊ตฌ์ฑ์ ํธ์คํ ํ์ญ์์ค. ์ด๋ ์ํคํ ์ฒ ํจํด์ ๋ํ ๋จ์ผ ์ง์ค ๊ณต๊ธ์์ ๋ณด์ฅํฉ๋๋ค.
- ์๋ฌธ ๋ฌธ์ํ: ํ๋ก์ ํธ ๋ฌธ์๊ฐ ํ์งํ๋ ์ ์์ง๋ง, ์์ฑ๊ธฐ์ ๋ํ ๊ธฐ์ ๋ฌธ์(์ฌ์ฉ ๋ฐฉ๋ฒ, ํ ํ๋ฆฟ ๊ธฐ์ฌ ๋ฐฉ๋ฒ)๋ ๊ธ๋ก๋ฒ ์ํํธ์จ์ด ๊ฐ๋ฐ์ ๊ณต์ฉ์ด์ธ ์์ด๋ก ์์ฑ๋์ด์ผ ํฉ๋๋ค. ์ด๋ ๋ค์ํ ์ธ์ด ๋ฐฐ๊ฒฝ์ ๊ฐ์ง ์ฌ๋๋ค ์ฌ์ด์ ๋ช ํํ ์ดํด๋ฅผ ๋ณด์ฅํฉ๋๋ค.
- ์์ฑ๊ธฐ ๋ฒ์ ๊ด๋ฆฌ: ์์ฑ๊ธฐ ๋๊ตฌ์ ํ ํ๋ฆฟ์ ๋ฒ์ ๋ฒํธ๋ก ์ทจ๊ธํ์ญ์์ค. ์ด๋ฅผ ํตํด ํ์ ์๋ก์ด ํจํด์ด๋ ๊ธฐ๋ฅ์ด ๋์ ๋ ๋ ๋ช ์์ ์ผ๋ก ์์ฑ๊ธฐ๋ฅผ ์ ๊ทธ๋ ์ด๋ํ์ฌ ๋ณ๊ฒฝ ์ฌํญ์ ํจ๊ณผ์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
- ์ง์ญ ๊ฐ ์ผ๊ด๋ ๋๊ตฌ ์ฌ์ฉ: ๋ชจ๋ ๊ธ๋ก๋ฒ ํ์ด ๋์ผํ ์ฝ๋ ์์ฑ ๋๊ตฌ์ ์ ๊ทผํ๊ณ ๊ต์ก๋ฐ๋๋ก ๋ณด์ฅํ์ญ์์ค. ์ด๋ ๋ถ์ผ์น๋ฅผ ์ต์ํํ๊ณ ํต์ผ๋ ๊ฐ๋ฐ ๊ฒฝํ์ ์กฐ์ฑํฉ๋๋ค.
์ธ์ ์์
์ฝ๋ ์์ฑ์ ๊ฐ๋ฐ์์ ํ๋จ์ ๋์ฒดํ๋ ๊ฒ์ด ์๋๋ผ ๊ฐ๋ฐ์์๊ฒ ํ์ ์ค์ด์ฃผ๋ ๋๊ตฌ์์ ๊ธฐ์ตํ์ญ์์ค.
- ์ฝ๋ ์์ฑ์ ์ดํด๋ฅผ ๋์ฒดํ๋ ๊ฒ์ด ์๋ ๋๊ตฌ์ ๋๋ค: ๊ฐ๋ฐ์๋ค์ ์ฌ์ ํ ๊ธฐ๋ณธ ํจํด๊ณผ ์์ฑ๋ ์ฝ๋๋ฅผ ์ดํดํด์ผ ํฉ๋๋ค. ์์ฑ๋ ๊ฒฐ๊ณผ๋ฌผ์ ๊ฒํ ํ๊ณ ํ ํ๋ฆฟ์ ์ดํดํ๋๋ก ์ฅ๋ คํ์ญ์์ค.
- ๊ต์ก ๋ฐ ํ๋ จ: ๊ฐ๋ฐ์๋ค์๊ฒ ์์ฑ๊ธฐ ์ฌ์ฉ ๋ฐฉ๋ฒ, ํ ํ๋ฆฟ ๊ตฌ์กฐ, ๊ทธ๋ฆฌ๊ณ ๊ทธ๊ฒ๋ค์ด ๊ฐ์ ํ๋ ์ํคํ ์ฒ ์์น์ ๋ํ ๊ต์ก ์ธ์ ์ด๋ ํฌ๊ด์ ์ธ ๊ฐ์ด๋๋ฅผ ์ ๊ณตํ์ญ์์ค.
- ์๋ํ์ ๊ฐ๋ฐ์ ์์จ์ฑ์ ๊ท ํ: ์ผ๊ด์ฑ์ ์ข์ง๋ง, ์ฐฝ์์ฑ์ ์ ํดํ๊ฑฐ๋ ๊ฐ๋ฐ์๊ฐ ํ์ํ ๋ ๋ ํนํ๊ณ ์ต์ ํ๋ ์๋ฃจ์ ์ ๊ตฌํํ๋ ๊ฒ์ ๋ถ๊ฐ๋ฅํ๊ฒ ๋ง๋๋ ๊ณผ๋ํ ์๋ํ๋ ํผํ์ญ์์ค. ํน์ ์์ฑ ๊ธฐ๋ฅ์์ ๋ฒ์ด๋ ์ ์๋ ํ์ถ๊ตฌ๋ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํ์ญ์์ค.
์ ์ฌ์ ํจ์ ๊ณผ ๊ณผ์
์ด์ ์ ์๋นํ์ง๋ง, ์ฝ๋ ์์ฑ์ ๊ตฌํํ๋ ๋ฐ๋ ์ด๋ ค์์ด ๋ฐ๋ฆ ๋๋ค. ์ด๋ฌํ ์ ์ฌ์ ํจ์ ์ ์ธ์ํ๋ฉด ํ์ด ์ฑ๊ณต์ ์ผ๋ก ์ด๋ฅผ ํค์ณ๋๊ฐ๋ ๋ฐ ๋์์ด ๋ ์ ์์ต๋๋ค.
๊ณผ์ ์์ฑ
๋๋ฌด ๋ง์ ์ฝ๋๋ ์ง๋์น๊ฒ ๋ณต์กํ ์ฝ๋๋ฅผ ์์ฑํ๋ฉด ๋๋ก๋ ์๋ํ์ ์ด์ ์ ์์ํ ์ ์์ต๋๋ค.
- ์ฝ๋ ๋น๋ํ: ํ ํ๋ฆฟ์ด ๋๋ฌด ๊ด๋ฒ์ํ๊ณ ์ค์ ๋ก ํ์ํ์ง ์์ ๋ง์ ํ์ผ์ด๋ ์ฅํฉํ ์ฝ๋๋ฅผ ์์ฑํ๋ฉด, ํ์ํ๊ณ ์ ์ง ๊ด๋ฆฌํ๊ธฐ ๋ ์ด๋ ค์ด ๋ ํฐ ์ฝ๋๋ฒ ์ด์ค๋ก ์ด์ด์ง ์ ์์ต๋๋ค.
- ๋ ์ด๋ ค์ด ๋๋ฒ๊น : ์๋์ผ๋ก ์์ฑ๋ ์ฝ๋์ ๋ฌธ์ ๋ฅผ ๋๋ฒ๊น ํ๋ ๊ฒ์ ๋ ์ด๋ ค์ธ ์ ์์ผ๋ฉฐ, ํนํ ์์ฑ ๋ก์ง ์์ฒด์ ๊ฒฐํจ์ด ์๊ฑฐ๋ ์์ฑ๋ ๊ฒฐ๊ณผ๋ฌผ์ ๋ํ ์์ค ๋งต์ด ์ ๋๋ก ๊ตฌ์ฑ๋์ง ์์ ๊ฒฝ์ฐ ๋์ฑ ๊ทธ๋ ์ต๋๋ค. ๊ฐ๋ฐ์๋ค์ ๋ฌธ์ ๋ฅผ ์๋ ํ ํ๋ฆฟ์ด๋ ์์ฑ๊ธฐ ๋ก์ง์ผ๋ก ์ถ์ ํ๋ ๋ฐ ์ด๋ ค์์ ๊ฒช์ ์ ์์ต๋๋ค.
ํ ํ๋ฆฟ ๋๋ฆฌํํธ
ํ ํ๋ฆฟ์ ๋ค๋ฅธ ์ฝ๋์ ๋ง์ฐฌ๊ฐ์ง๋ก ์ ๊ทน์ ์ผ๋ก ๊ด๋ฆฌ๋์ง ์์ผ๋ฉด ๊ตฌ์์ด ๋๊ฑฐ๋ ์ผ๊ด์ฑ์ด ์์ด์ง ์ ์์ต๋๋ค.
- ์ค๋๋ ํ ํ๋ฆฟ: ํ๋ก์ ํธ ์๊ตฌ ์ฌํญ์ด ์งํํ๊ฑฐ๋ ์ฝ๋ฉ ํ์ค์ด ๋ณ๊ฒฝ๋จ์ ๋ฐ๋ผ ํ ํ๋ฆฟ์ ์ ๋ฐ์ดํธํด์ผ ํฉ๋๋ค. ํ ํ๋ฆฟ์ด ์ค๋๋๋ฉด ํ์ฌ์ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ฐ๋ฅด์ง ์๋ ์ฝ๋๋ฅผ ์์ฑํ๊ฒ ๋์ด ์ฝ๋๋ฒ ์ด์ค์ ๋น์ผ๊ด์ฑ์ ์ด๋ํฉ๋๋ค.
- ์ผ๊ด์ฑ ์๋ ์์ฑ ์ฝ๋: ํ ์ ์ฒด์์ ๋ค๋ฅธ ๋ฒ์ ์ ํ ํ๋ฆฟ์ด๋ ์์ฑ๊ธฐ๊ฐ ์ฌ์ฉ๋๊ฑฐ๋, ์ผ๋ถ ๊ฐ๋ฐ์๊ฐ ๋ณ๊ฒฝ ์ฌํญ์ ํ ํ๋ฆฟ์ ๋ค์ ๋ฐ์ํ์ง ์๊ณ ์์ฑ๋ ํ์ผ์ ์๋์ผ๋ก ์์ ํ๋ฉด ์ฝ๋๋ฒ ์ด์ค๋ ๋น ๋ฅด๊ฒ ์ผ๊ด์ฑ์ ์์ ์ ์์ต๋๋ค.
ํ์ต ๊ณก์
์ฝ๋ ์์ฑ ๋๊ตฌ๋ฅผ ์ฑํํ๊ณ ๊ตฌํํ๋ ๊ฒ์ ๊ฐ๋ฐํ์ ํ์ต ๊ณก์ ์ ๋์ ํ ์ ์์ต๋๋ค.
- ์ค์ ๋ณต์ก์ฑ: ๊ณ ๊ธ ์ฝ๋ ์์ฑ ๋๊ตฌ(ํนํ AST ๊ธฐ๋ฐ ๋๊ตฌ๋ ๋ณต์กํ ์ฌ์ฉ์ ์ง์ ๋ก์ง์ด ์๋ ๋๊ตฌ)๋ฅผ ๊ตฌ์ฑํ๋ ๋ฐ๋ ์๋นํ ์ด๊ธฐ ๋ ธ๋ ฅ๊ณผ ์ ๋ฌธ ์ง์์ด ํ์ํ ์ ์์ต๋๋ค.
- ํ ํ๋ฆฟ ๊ตฌ๋ฌธ ์ดํด: ๊ฐ๋ฐ์๋ค์ ์ ํํ ํ ํ๋ฆฟ ์์ง(์: EJS, Handlebars)์ ๊ตฌ๋ฌธ์ ๋ฐฐ์์ผ ํฉ๋๋ค. ์ข ์ข ๊ฐ๋จํ์ง๋ง ์ถ๊ฐ์ ์ธ ๊ธฐ์ ์ด ํ์ํฉ๋๋ค.
์์ฑ๋ ์ฝ๋ ๋๋ฒ๊น
์์ฑ๋ ์ฝ๋๋ก ์์ ํ ๋ ๋๋ฒ๊น ๊ณผ์ ์ด ๋ ๊ฐ์ ์ ์ด ๋ ์ ์์ต๋๋ค.
- ๋ฌธ์ ์ถ์ : ์์ฑ๋ ํ์ผ์์ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ ๋, ๊ทผ๋ณธ ์์ธ์ ์ฆ์ ๋ณด์ด๋ ์ฝ๋๊ฐ ์๋๋ผ ํ ํ๋ฆฟ ๋ก์ง, ํ ํ๋ฆฟ์ ์ ๋ฌ๋ ๋ฐ์ดํฐ ๋๋ ์์ฑ๊ธฐ์ ์ก์ ์ ์์ ์ ์์ต๋๋ค. ์ด๋ ๋๋ฒ๊น ์ ์ถ์ํ ๊ณ์ธต์ ์ถ๊ฐํฉ๋๋ค.
- ์์ค ๋งต ๋ฌธ์ : ์์ฑ๋ ์ฝ๋๊ฐ ์ ์ ํ ์์ค ๋งต ์ ๋ณด๋ฅผ ์ ์งํ๋๋ก ๋ณด์ฅํ๋ ๊ฒ์ ํจ๊ณผ์ ์ธ ๋๋ฒ๊น ์ ๋งค์ฐ ์ค์ํ๋ฉฐ, ํนํ ๋ฒ๋ค๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ์์ ๊ทธ๋ ์ต๋๋ค. ๋ถ์ ํํ ์์ค ๋งต์ ๋ฌธ์ ์ ์๋ ์์ค๋ฅผ ์ ํํ ์ฐพ์๋ด๊ธฐ ์ด๋ ต๊ฒ ๋ง๋ค ์ ์์ต๋๋ค.
์ ์ฐ์ฑ ์์ค
๋งค์ฐ ๋ ๋จ์ ์ด๊ฑฐ๋ ์ง๋์น๊ฒ ๊ฒฝ์ง๋ ์ฝ๋ ์์ฑ๊ธฐ๋ ๋๋๋ก ๊ฐ๋ฐ์๋ค์ด ๋ ํนํ๊ฑฐ๋ ๊ณ ๋๋ก ์ต์ ํ๋ ์๋ฃจ์ ์ ๊ตฌํํ๋ ๋ฅ๋ ฅ์ ์ ํํ ์ ์์ต๋๋ค.
- ์ ํ๋ ์ฌ์ฉ์ ์ ์: ์์ฑ๊ธฐ๊ฐ ์ฌ์ฉ์ ์ ์๋ฅผ ์ํ ์ถฉ๋ถํ ํ ์ด๋ ์ต์ ์ ์ ๊ณตํ์ง ์์ผ๋ฉด ๊ฐ๋ฐ์๋ค์ ์ ์ฝ์ ๋๋ผ๊ณ , ์ด๋ ์์๋ฐฉํธ์ ์ฐพ๊ฑฐ๋ ์์ฑ๊ธฐ ์ฌ์ฉ์ ๊บผ๋ฆฌ๊ฒ ๋ง๋ค ์ ์์ต๋๋ค.
- "๊ณจ๋ ํจ์ค" ํธํฅ: ์์ฑ๊ธฐ๋ ์ข ์ข ๊ฐ๋ฐ์ ์ํ "๊ณจ๋ ํจ์ค(์ต์ ๊ฒฝ๋ก)"๋ฅผ ๊ฐ์ ํฉ๋๋ค. ์ด๋ ์ผ๊ด์ฑ์๋ ์ข์ง๋ง, ํน์ ๋งฅ๋ฝ์์ ์คํ์ด๋ ์ ์ฌ์ ์ผ๋ก ๋ ๋์ ๋์์ ์ํคํ ์ฒ ์ ํ์ ์ ํดํ ์ ์์ต๋๋ค.
๊ฒฐ๋ก
ํ๋ก์ ํธ์ ๊ท๋ชจ์ ๋ณต์ก์ฑ์ด ์ปค์ง๊ณ ํ์ด ์ข ์ข ์ ์ธ๊ณ์ ์ผ๋ก ๋ถ์ฐ๋์ด ์๋ ์ญ๋์ ์ธ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ ์ธ๊ณ์์, ์๋ฐ์คํฌ๋ฆฝํธ ๋ชจ๋ ํ ํ๋ฆฟ ํจํด๊ณผ ์ฝ๋ ์์ฑ์ ์ง๋ฅ์ ์ธ ์ ์ฉ์ ๊ฐ๋ ฅํ ์ ๋ต์ผ๋ก ๋๋๋ฌ์ง๋๋ค. ์ฐ๋ฆฌ๋ ์๋์ ์ธ ๋ณด์ผ๋ฌํ๋ ์ดํธ ์์ฑ์ ๋์ด ์๋ํ๋๊ณ ํ ํ๋ฆฟ ๊ธฐ๋ฐ์ ๋ชจ๋ ์์ฑ์ผ๋ก ์ ํํ๋ ๊ฒ์ด ๊ฐ๋ฐ ์ํ๊ณ ์ ๋ฐ์ ํจ์จ์ฑ, ์ผ๊ด์ฑ, ํ์ฅ์ฑ์ ์ผ๋ง๋ ํฐ ์ํฅ์ ๋ฏธ์น ์ ์๋์ง ํ๊ตฌํ์ต๋๋ค.
API ํด๋ผ์ด์ธํธ ๋ฐ UI ์ปดํฌ๋ํธ ํ์คํ๋ถํฐ ์ํ ๊ด๋ฆฌ ๋ฐ ํ ์คํธ ํ์ผ ์์ฑ ๊ฐ์ํ์ ์ด๋ฅด๊ธฐ๊น์ง, ์ฝ๋ ์์ฑ์ ๊ฐ๋ฐ์๋ค์ด ๋ฐ๋ณต์ ์ธ ์ค์ ์์ ๋์ ๊ณ ์ ํ ๋น์ฆ๋์ค ๋ก์ง์ ์ง์คํ ์ ์๊ฒ ํด์ค๋๋ค. ์ด๋ ๋์งํธ ์ํคํ ํธ ์ญํ ์ ํ์ฌ ๋ชจ๋ฒ ์ฌ๋ก, ์ฝ๋ฉ ํ์ค, ์ํคํ ์ฒ ํจํด์ ์ฝ๋๋ฒ ์ด์ค ์ ์ฒด์ ๊ท ์ผํ๊ฒ ์ ์ฉํ๋ฉฐ, ์ด๋ ์๋ก์ด ํ์์ ์จ๋ณด๋ฉํ๊ณ ๋ค์ํ ๊ธ๋ก๋ฒ ํ ๋ด์์ ์์ง๋ ฅ์ ์ ์งํ๋ ๋ฐ ๋งค์ฐ ์ค์ํฉ๋๋ค.
EJS, Handlebars, Plop.js, Yeoman, GraphQL Code Generator์ ๊ฐ์ ๋๊ตฌ๋ค์ ํ์ํ ํ๊ณผ ์ ์ฐ์ฑ์ ์ ๊ณตํ์ฌ ํ์ด ํน์ ์๊ตฌ์ ๊ฐ์ฅ ์ ํฉํ ์๋ฃจ์ ์ ์ ํํ ์ ์๊ฒ ํฉ๋๋ค. ํจํด์ ์ ์คํ๊ฒ ์ ์ํ๊ณ , ์์ฑ๊ธฐ๋ฅผ ๊ฐ๋ฐ ์ํฌํ๋ก์ฐ์ ํตํฉํ๋ฉฐ, ์ ์ง๋ณด์, ์ฌ์ฉ์ ์ ์, ์ค๋ฅ ์ฒ๋ฆฌ์ ๋ํ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ์ค์ํจ์ผ๋ก์จ ์กฐ์ง์ ์๋นํ ์์ฐ์ฑ ํฅ์์ ์ด๋ฃฐ ์ ์์ต๋๋ค.
๊ณผ์ ์์ฑ, ํ ํ๋ฆฟ ๋๋ฆฌํํธ, ์ด๊ธฐ ํ์ต ๊ณก์ ๊ณผ ๊ฐ์ ๊ณผ์ ๊ฐ ์กด์ฌํ์ง๋ง, ์ด๋ฅผ ์ดํดํ๊ณ ์ ์ ์ ์ผ๋ก ๋์ฒํ๋ฉด ์ฑ๊ณต์ ์ธ ๊ตฌํ์ ๋ณด์ฅํ ์ ์์ต๋๋ค. ์ํํธ์จ์ด ๊ฐ๋ฐ์ ๋ฏธ๋๋ ์ ์ฌ์ ์ผ๋ก AI์ ์ ์ ๋ ์ง๋ฅ์ ์ธ ๋๋ฉ์ธ ํนํ ์ธ์ด์ ์ํด ์ฃผ๋๋๋, ํจ์ฌ ๋ ์ ๊ตํ ์ฝ๋ ์์ฑ์ ์์ํ๋ฉฐ, ์ด๋ ์ ๋ก ์๋ ์๋๋ก ๊ณ ํ์ง ์ํํธ์จ์ด๋ฅผ ๋ง๋๋ ์ฐ๋ฆฌ์ ๋ฅ๋ ฅ์ ๋์ฑ ํฅ์์ํฌ ๊ฒ์ ๋๋ค.
์ฝ๋ ์์ฑ์ ์ธ๊ฐ์ ์ง์ฑ์ ๋์ฒดํ๋ ๊ฒ์ด ์๋๋ผ, ์์ด์๋ ์ ๋ ๊ฐ์๊ธฐ๋ก ๋ฐ์๋ค์ด์ญ์์ค. ์๊ฒ ์์ํ์ฌ ๊ฐ์ฅ ๋ฐ๋ณต์ ์ธ ๋ชจ๋ ๊ตฌ์กฐ๋ฅผ ์๋ณํ๊ณ , ์ ์ฐจ์ ์ผ๋ก ํ ํ๋ฆฟ๊ณผ ์์ฑ์ ์ํฌํ๋ก์ฐ์ ๋์ ํ์ญ์์ค. ์ด๋ฌํ ํฌ์๋ ๊ฐ๋ฐ์ ๋ง์กฑ๋, ์ฝ๋ ํ์ง, ๊ทธ๋ฆฌ๊ณ ๊ธ๋ก๋ฒ ๊ฐ๋ฐ ๋ ธ๋ ฅ์ ์ ๋ฐ์ ์ธ ๋ฏผ์ฒฉ์ฑ ์ธก๋ฉด์์ ์๋นํ ์์ต์ ๊ฐ์ ธ๋ค์ค ๊ฒ์ ๋๋ค. ์ฌ๋ฌ๋ถ์ ์๋ฐ์คํฌ๋ฆฝํธ ํ๋ก์ ํธ ์์ค์ ๋์ด์ญ์์ค โ ์ค๋, ๋ฏธ๋๋ฅผ ์์ฑํ์ญ์์ค.