Skip to Content
Nextra 4.0 is released πŸŽ‰

πŸ—οΈ λΉŒλ“œ 방식

이 λ¬Έμ„œλŠ” 이 ν”„λ‘œμ νŠΈμ—μ„œ νŒ¨ν‚€μ§€λ₯Ό μ–΄λ–»κ²Œ λΉŒλ“œν•˜λŠ”μ§€μ— λŒ€ν•œ μ„€λͺ…을 μ œκ³΅ν•¨μœΌλ‘œμ„œ, 이 ν”„λ‘œμ νŠΈμ—μ„œ νŒ¨ν‚€μ§€κ°€ μ–΄λ–»κ²Œ λΉŒλ“œλ˜λŠ”μ§€μ— λŒ€ν•œ 이해λ₯Ό 돕기 μœ„ν•΄ μž‘μ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

⚑ Vite 기반 λΉŒλ“œ

이 ν”„λ‘œμ νŠΈμ—μ„œ μ œκ³΅λ˜λŠ” νŒ¨ν‚€μ§€λ“€μ€ Viteλ₯Ό μ‚¬μš©ν•˜μ—¬ λΉŒλ“œλ©λ‹ˆλ‹€.

νŒ¨ν‚€μ§€λΉŒλ“œ 방식
packages/browser-utilsVite 
http-clientsVite 
packages/node-utilsVite 
packages/react-utilsVite 
packages/react-uiVite 

eslint-plugin-sample νŒ¨ν‚€μ§€μ™€ 같은 ESLint ν”ŒλŸ¬κ·ΈμΈ νŒ¨ν‚€μ§€λŠ” λ³„λ„μ˜ λΉŒλ“œ 과정을 κ±°μΉ˜μ§€ μ•Šλ„λ‘ μ„€κ³„λ˜μ—ˆμŠ΅λ‹ˆλ‹€. λŒ€μ‹ , ESLint ν”ŒλŸ¬κ·ΈμΈ νŒ¨ν‚€μ§€λŠ” lib 디렉토리에 μžˆλŠ” index.js νŒŒμΌμ„ κ·ΈλŒ€λ‘œ μ‚¬μš©ν•˜λ„λ‘ package.json의 files, main, exports ν•„λ“œμ— μ„€μ •λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.

채택 μ˜λ„

Vite λ₯Ό μ‚¬μš©ν•˜μ—¬ νŒ¨ν‚€μ§€λ₯Ό λΉŒλ“œν•˜λŠ” μ΄μœ λŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:

β€œκ° νŒ¨ν‚€μ§€λ“€μ„ npm νŒ¨ν‚€μ§€λ‘œ 배포할 것을 μ „μ œλ‘œ ν•˜μ—¬, Vite의 λΉŒλ“œ κΈ°λŠ₯을 μ‚¬μš©ν•˜μ—¬ 각 νŒ¨ν‚€μ§€μ˜ μ†ŒμŠ€ μ½”λ“œλ₯Ό λ²ˆλ“€λ§ν•˜κ³ , μ΅œμ ν™”λœ 결과물을 μƒμ„±ν•˜κΈ° μœ„ν•¨μž…λ‹ˆλ‹€.”

νŠΉμ§•

이 ν”„λ‘œμ νŠΈμ—μ„œ μ œκ³΅ν•˜λŠ” νŒ¨ν‚€μ§€λ“€μ€ κ³΅ν†΅μ μœΌλ‘œ λ‹€μŒκ³Ό 같은 νŠΉμ§•μ„ 갖도둝 μ„€κ³„λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€:

1) ESModule 및 CommonJS μ‹œμŠ€ν…œ 지원

각 νŒ¨ν‚€μ§€λŠ” ESModule(.es.js)κ³Ό CommonJS(.cjs.js) ν˜•μ‹μœΌλ‘œ λΉŒλ“œλ˜μ–΄, λ‹€μ–‘ν•œ ν™˜κ²½μ—μ„œ μ‚¬μš©ν•  수 μžˆλ„λ‘ μ§€μ›ν•©λ‹ˆλ‹€. μ΄λŠ” Vite λΉŒλ“œ μ„€μ •μ—μ„œ 라이브러리 λͺ¨λ“œλ₯Ό ν†΅ν•œ Rollup 섀정을 ν™œμš©ν•˜μ—¬ κ΅¬ν˜„λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

packages/browser-utils/vite.config.js
/// <reference types="vitest" /> // ... λ‹€λ₯Έ import λ¬Έλ“€ // https://vitejs.dev/config/ export default defineConfig({ // ... λ‹€λ₯Έ μ„€μ •λ“€ ... build: { // ... λ‹€λ₯Έ μ„€μ •λ“€ ... lib: { // ... λ‹€λ₯Έ μ„€μ •λ“€ ... formats: ["es", "cjs"], // ESModuleκ³Ό CommonJS ν˜•μ‹μœΌλ‘œ λΉŒλ“œ fileName: (format, entryName) => `${entryName}/index.${format}.js`, }, }, });

2) νƒ€μž… μ„ μ–Έ 파일 제곡

각 νŒ¨ν‚€μ§€λŠ” TypeScript둜 μž‘μ„±λ˜μ–΄ 있으며, λΉŒλ“œ μ‹œ νƒ€μž… μ„ μ–Έ 파일(.d.ts)을 μžλ™μœΌλ‘œ μƒμ„±ν•©λ‹ˆλ‹€. μ΄λŠ” vite-plugin-dts ν”ŒλŸ¬κ·ΈμΈμ„ μ‚¬μš©ν•˜μ—¬ 각 μ—”νŠΈλ¦¬λ³„λ‘œ νƒ€μž… μ„ μ–Έ νŒŒμΌμ„ μƒμ„±ν•˜λ„λ‘ μ„€μ •ν•¨μœΌλ‘œμ„œ κ΅¬ν˜„λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

packages/browser-utils/vite.config.js
/// <reference types="vitest" /> import { defineConfig } from "vite"; import dtsPlugin from "vite-plugin-dts"; // ... λ‹€λ₯Έ import λ¬Έλ“€ // https://vitejs.dev/config/ export default defineConfig({ plugins: [dtsPlugin({ include: ["src"] }), tsConfigPaths()], // ... λ‹€λ₯Έ μ„€μ •λ“€ ... });

3) 트리 쉐이킹 및 μ½”λ“œ μŠ€ν”Œλ¦¬νŒ… 지원

각 νŒ¨ν‚€μ§€λŠ” Vite의 트리 쉐이킹 및 μ½”λ“œ μŠ€ν”Œλ¦¬νŒ… κΈ°λŠ₯을 ν™œμš©ν•˜μ—¬, μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” μ½”λ“œλŠ” λΉŒλ“œ 결과물에 ν¬ν•¨λ˜μ§€ μ•Šλ„λ‘ μ΅œμ ν™”λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.

μ΄λŠ” 각 νŒ¨ν‚€μ§€λ“€μ˜ package.jsonμ—μ„œ exports ν•„λ“œλ₯Ό 톡해 각 κΈ°λŠ₯ λ‹¨μœ„λ“€μ„ μ„œλΈŒ λͺ¨λ“ˆλ‘œ 뢄리함과 λ™μ‹œμ—,

packages/browser-utils/package.json
{ "exports": { "./dom": { "types": "./dist/dom/index.d.ts", "import": "./dist/dom/index.es.js", "require": "./dist/dom/index.cjs.js" }, "./msw": { "types": "./dist/msw/index.d.ts", "import": "./dist/msw/index.es.js", "require": "./dist/msw/index.cjs.js" }, "./string": { "types": "./dist/string/index.d.ts", "import": "./dist/string/index.es.js", "require": "./dist/string/index.cjs.js" } }, // ... λ‹€λ₯Έ μ„€μ •λ“€ ... }

이듀을 κ΅¬μ„±ν•˜λŠ” μ†ŒμŠ€ μ½”λ“œ νŒŒμΌλ“€ 각각이 μ €λ§ˆλ‹€ μ—”νŠΈλ¦¬ ν¬μΈνŠΈλ‘œμ„œ λ²ˆλ“€λ§λ˜λ„λ‘ μ„€μ •ν•¨μœΌλ‘œμ„œ κ΅¬ν˜„λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

packages/browser-utils/vite.config.js
/// <reference types="vitest" /> // ... λ‹€λ₯Έ import λ¬Έλ“€ import { runWithGlob } from "@repo/helpers/runWithGlob"; // https://vitejs.dev/config/ export default defineConfig({ // ... λ‹€λ₯Έ μ„€μ •λ“€ ... build: { lib: { // ... λ‹€λ₯Έ μ„€μ •λ“€ ... entry: Object.fromEntries( runWithGlob( "src/**/*.{ts,tsx}", (file) => [ // μ—”νŠΈλ¦¬ 이름 file.replace(/^src\//, "").replace(/index\.(ts|tsx)$/, ""), // μ ˆλŒ€ 경둜 resolve(__dirname, file), ], ["src/**/*.{d,spec}.ts"], ), ), fileName: (format, entryName) => `${entryName}/index.${format}.js`, }, }, });

4) 개발 νŽΈμ˜μ„± 제곡

각 νŒ¨ν‚€μ§€λŠ” 개발 ν™˜κ²½μ—μ„œμ˜ νŽΈλ¦¬ν•œ μ‚¬μš©μ„ μœ„ν•΄, λ‹€μŒκ³Ό 같은 κΈ°λŠ₯듀을 μ œκ³΅ν•©λ‹ˆλ‹€:

  • pnpm dev λͺ…λ Ήμ–΄λ₯Ό ν†΅ν•œ HMR κΈ°λŠ₯을 μ§€μ›ν•©λ‹ˆλ‹€.
  • TypeScript 검사 및 Linter 검사λ₯Ό μœ„ν•œ μŠ€ν¬λ¦½νŠΈκ°€ μ œκ³΅λ©λ‹ˆλ‹€.
  • TypeScript 경둜 별칭을 μ§€μ›ν•˜μ—¬, μ›Œν¬μŠ€νŽ˜μ΄μŠ€ λ‚΄ μ½”λ“œλ₯Ό importν•  λ•Œ νŽΈλ¦¬ν•œ λͺ¨λ“ˆ 경둜 μ‚¬μš©μ΄ κ°€λŠ₯ν•©λ‹ˆλ‹€.
  • Vitest 기반의 Test 싀행을 μœ„ν•œ 기본적인 ν™˜κ²½κ³Ό μŠ€ν¬λ¦½νŠΈκ°€ μ œκ³΅λ©λ‹ˆλ‹€.
    • λΈŒλΌμš°μ € DOM 및 React κ΄€λ ¨ νŒ¨ν‚€μ§€μ˜ 경우, @testing-library/react 및 @testing-library/jest-dom νŒ¨ν‚€μ§€λ₯Ό μ‚¬μš©ν•˜μ—¬ ν…ŒμŠ€νŠΈ ν™˜κ²½μ„ κ΅¬μ„±ν•©λ‹ˆλ‹€.

λ‹€λ₯Έ νŒ¨ν‚€μ§€ 및 μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œμ˜ μ‚¬μš©

이 ν”„λ‘œμ νŠΈμ˜ νŒ¨ν‚€μ§€λ“€μ„ μ˜μ‘΄μ„±μœΌλ‘œ κ°–λŠ” λ‹€λ₯Έ νŒ¨ν‚€μ§€ 및 μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œλŠ” νŒ¨ν‚€μ§€μ˜ λΉŒλ“œλœ κ²°κ³Όλ¬Ό(dist)을 μ‚¬μš©ν•˜λ„λ‘ μ„€μ •λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€. μ΄λŸ¬ν•œ 섀정은 각 νŒ¨ν‚€μ§€λ§ˆλ‹€ package.json의 files, exports ν•„λ“œμ— μ •μ˜λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.

μ˜ˆμ‹œλ‘œ, react-utils νŒ¨ν‚€μ§€μ˜ package.json νŒŒμΌμ„ μ‚΄νŽ΄λ³΄λ©΄ λ‹€μŒκ³Ό 같이 μ„€μ •λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€:

μ΄λŸ¬ν•œ 섀정에 μ˜ν•΄ pnpm은 react-utils νŒ¨ν‚€μ§€λ₯Ό μ˜μ‘΄μ„±μœΌλ‘œ κ°–λŠ” λ‹€λ₯Έ νŒ¨ν‚€μ§€λ‚˜ μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ react-utils νŒ¨ν‚€μ§€λ₯Ό μ„€μΉ˜ν•  λ•Œ, λΉŒλ“œλœ κ²°κ³Όλ¬Ό(dist)을 μ‚¬μš©ν•˜κ²Œ λ©λ‹ˆλ‹€. 즉, react-utils νŒ¨ν‚€μ§€λ₯Ό μ‚¬μš©ν•˜λŠ” λ‹€λ₯Έ νŒ¨ν‚€μ§€λ‚˜ μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ node_modules/@repo/react-utils λ””λ ‰ν† λ¦¬μ—λŠ” λΉŒλ“œλœ κ²°κ³Όλ¬Ό(dist)이 ν¬ν•¨λ˜μ–΄ 있게 λ©λ‹ˆλ‹€.

packages/react-utils/package.json
{ // ...existing code... "files": [ "dist" ], "exports": { "./hooks": { "types": "./dist/hooks/index.d.ts", "import": "./dist/hooks/index.es.js", "require": "./dist/hooks/index.cjs.js" }, "./hocs": { "types": "./dist/hocs/index.d.ts", "import": "./dist/hocs/index.es.js", "require": "./dist/hocs/index.cjs.js" }, "./providers": { "types": "./dist/providers/index.d.ts", "import": "./dist/providers/index.es.js", "require": "./dist/providers/index.cjs.js" } }, // ...existing code... }

개발 ν™˜κ²½(pnpm dev)μ—μ„œμ˜ HMR 지원

μ•žμ„œ μ„€λͺ…ν•œ 바와 같이, 이 ν”„λ‘œμ νŠΈμ˜ νŒ¨ν‚€μ§€λ“€μ„ μ˜μ‘΄μ„±μœΌλ‘œ κ°–λŠ” λ‹€λ₯Έ νŒ¨ν‚€μ§€λ‚˜ μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œλŠ” ν•΄λ‹Ή νŒ¨ν‚€μ§€μ˜ μ‹€μ œ λΉŒλ“œλœ κ²°κ³Όλ¬Ό(dist)을 μ‚¬μš©ν•˜λ„λ‘ μ„€κ³„λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.

λ”°λΌμ„œ, 개발 ν™˜κ²½μ—μ„œ pnpm dev λͺ…λ Ήμ–΄λ₯Ό μ‹€ν–‰ν–ˆμ„ λ•Œμ—λ„, 각 νŒ¨ν‚€μ§€μ˜ λΉŒλ“œλœ κ²°κ³Όλ¬Ό(dist)을 μ‚¬μš©ν•˜μ—¬ 개발 μ„œλ²„κ°€ μ‹€ν–‰λ©λ‹ˆλ‹€.

이 λ•Œ, 개발 쀑인 νŒ¨ν‚€μ§€μ˜ λ³€κ²½ 사항을 μ‹€μ‹œκ°„μœΌλ‘œ λ°˜μ˜ν•  수 μžˆμ–΄μ•Ό ν•˜λ―€λ‘œ, Vite의 HMR(Hot Module Replacement) κΈ°λŠ₯을 μ‚¬μš©ν•˜μ—¬ 각 νŒ¨ν‚€μ§€μ˜ dev μŠ€ν¬λ¦½νŠΈκ°€ λ‹€μŒκ³Ό 같이 μ„€μ •λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.

packages/react-utils/package.json
{ // ...existing code... "scripts": { "dev": "tsc -b && vite build --watch", // ...other scripts... }, // ...existing code... }

Linter 검사 및 TypeScript 검사

이 ν”„λ‘œμ νŠΈμ˜ νŒ¨ν‚€μ§€λ“€μ„ μ˜μ‘΄μ„±μœΌλ‘œ κ°–λŠ” λ‹€λ₯Έ νŒ¨ν‚€μ§€λ‚˜ μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œλŠ” ν•΄λ‹Ή νŒ¨ν‚€μ§€μ˜ μ‹€μ œ λΉŒλ“œλœ κ²°κ³Όλ¬Ό(dist)을 μ‚¬μš©ν•˜λ„λ‘ μ„€κ³„λ˜μ–΄ 있기 λ•Œλ¬Έμ—,

λ§Œμ•½ 각 νŒ¨ν‚€μ§€λ₯Ό μ‚¬μš©ν•˜λŠ” λ‹€λ₯Έ νŒ¨ν‚€μ§€λ‚˜ μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ Linter 검사(pnpm run lint) 및 TypeScript 검사(pnpm run check-types)λ₯Ό μ‹€ν–‰ν•˜λŠ” μ‹œμ μ—μ„œ dist 디렉토리가 μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄, 였λ₯˜κ°€ λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ”°λΌμ„œ, Linter 검사 및 TypeScript 검사λ₯Ό μ‹€ν–‰ν•˜κΈ° 전에 λͺ¨λ“  νŒ¨ν‚€μ§€λ“€μ— λŒ€ν•œ dist 디렉토리가 μƒμ„±λ˜μ–΄ μžˆλ‹€λŠ” 것을 보μž₯ν•  ν•„μš”κ°€ μžˆμŠ΅λ‹ˆλ‹€. 이λ₯Ό μœ„ν•΄, Turborepo νƒœμŠ€ν¬ 쀑 lint 및 check-types에 λŒ€ν•΄μ„œλŠ” λΉŒλ“œ μž‘μ—…(build)에 μ˜μ‘΄ν•˜λ„λ‘ λ‹€μŒκ³Ό 같이 μ„€μ •λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.

turbo.json
{ // ...existing code... "tasks": { // ...other tasks... "lint": { "dependsOn": ["build", "^lint"] }, "check-types": { "dependsOn": ["build", "^check-types"] }, // ...other tasks... }, // ...existing code... }

πŸ“Œ μ°Έκ³ 

이 ν”„λ‘œμ νŠΈμ—μ„œ μ±„νƒν•œ λΉŒλ“œ 방식에 λŒ€ν•œ μžμ„Έν•œ λ‚΄μš©μ€ λ‹€μŒ λ¬Έμ„œλ₯Ό μ°Έκ³ ν•˜μ„Έμš”:


Last updated on