๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
React

๋‚˜๋งŒ์˜ React + TypeScript ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ NPM์— ๋ฐฐํฌํ•ด๋ณด์ž

by LasBe 2023. 12. 2.
๋ฐ˜์‘ํ˜•

๐Ÿ“’ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์—


React ํ”„๋กœ์ ํŠธ๋ฅผ ์œ„ํ•œ TypeScript ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ฐœ๋ฐœ, ๋ฒ„์ „ ๊ด€๋ฆฌ, ๊ทธ๋ฆฌ๊ณ  ๋ฐœํ–‰ํ•˜๋Š” ๊ณผ์ •์€ ๊ฐ„๋‹จํ•˜์ง€๋งŒ ๋ช‡ ๊ฐ€์ง€ ์ค€๋น„ ์‚ฌํ•ญ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.


๐Ÿ“Œ Node.js ๋ฐ npm ์„ค์น˜

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ฐœ๋ฐœํ•˜๋ ค๋ฉด Node.js์™€ npm์ด ์„ค์น˜๋˜์–ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฏธ ์„ค์น˜๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”.

node -v
npm -v

์„ค์น˜๋˜์–ด ์žˆ์ง€ ์•Š๋‹ค๋ฉด Node.js ๊ณต์‹ ์›น์‚ฌ์ดํŠธ ํ˜น์€ NVM์„ ํ†ตํ•ด Node.js๋ฅผ ์„ค์น˜ํ•ด์ฃผ์„ธ์š”.


๐Ÿ“Œ npm ํšŒ์›๊ฐ€์ž…

 

 

npm | Home

Bring the best of open source to you, your team, and your company Relied upon by more than 17 million developers worldwide, npm is committed to making JavaScript development elegant, productive, and safe. The free npm Registry has become the center of Java

www.npmjs.com

npm์— ํŒจํ‚ค์ง€๋ฅผ ์˜ฌ๋ฆฌ๊ธฐ ์œ„ํ•ด์„œ๋Š” ๊ณ„์ •์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
๊ณ„์ •์ด ์—†๋‹ค๋ฉด ํšŒ์›๊ฐ€์ž…์„ ํ•ด์ฃผ์„ธ์š”.

 

 

๐Ÿ“’ ๋‹จ๊ณ„๋ณ„ ๊ฐ€์ด๋“œ


๐Ÿ“Œ 1. CRA๋กœ React + TypeScript ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

$ npx create-react-app react-ts-lib --template typescript

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํ…œํ”Œ๋ฆฟ์„ ์ด์šฉํ•ด ๋ฆฌ์•กํŠธ ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•ด์ค๋‹ˆ๋‹ค.


๐Ÿ“Œ 2. ํด๋” ๊ตฌ์กฐ ์žก์•„์ฃผ๊ธฐ

ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ ํ›„ ์“ธ๋ชจ ์—†๋Š” ํŒŒ์ผ๋“ค ๋‹ค ์ณ๋‚ด์ค๋‹ˆ๋‹ค.

 

๊ทธ ํ›„ src ์•„๋ž˜์— lib ํด๋”๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๋ฐฐํฌํ•  ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‹ด์„ ํด๋”๋ฅผ ์ƒ์„ฑํ•ด ์ค๋‹ˆ๋‹ค.

 

์ด๋ ‡๊ฒŒ ํ•ด์ค˜์•ผ ๊ฐœ๋ฐœ ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ ํ–ˆ์„ ๋•Œ ๋””๋ฒ„๊น… ํ•˜๊ธฐ๋„ ํŽธํ•˜๊ณ 
๋ฐฐํฌ ์ „ lib ํด๋” ์•„๋ž˜์˜ ํŒŒ์ผ๋“ค๋งŒ ์ปดํŒŒ์ผํ•ด์ฃผ๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๊ตฌ๋ถ„๊ฐ๋„ ์ƒ๊ธฐ๊ณ  ํŽธํ•ด์ง‘๋‹ˆ๋‹ค.

 

๋˜ํ•œ ์ง„์ž…์ ์ธ ์—”ํŠธ๋ฆฌ ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด์ค˜์•ผ ๋˜๊ธฐ ๋•Œ๋ฌธ์— src/lib/index.ts์„ ์ƒ์„ฑํ•ด์„œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํŒŒ์ผ์„ export ํ•ด์ค๋‹ˆ๋‹ค.

 

barrel ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด๋‘๋ฉด ๊ด€๋ฆฌํ•˜๊ธฐ ํŽธํ•˜๋‹ˆ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”.

[React, JS, TS] ๊ฐ„๊ฒฐํ•œ import๋ฅผ ์œ„ํ•œ index(barrel) ํŒŒ์ผ์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ด๋ณด์ž


๐Ÿ“Œ 3. tsconfig.json ํŒŒ์ผ ์„ค์ •

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋ฐฐํฌํ•˜๊ธฐ ์ „ TS ์ปดํŒŒ์ผ๋Ÿฌ ํ˜•๋‹˜์ด
JS ํŒŒ์ผ๊ณผ ํƒ€์ž… ํŒŒ์ผ๋กœ ์ปดํŒŒ์ผ ํ•ด ์ฃผ์‹œ๊ธฐ ๋•Œ๋ฌธ์— ์„ค์ •ํŒŒ์ผ์ธ tsconfig.json์„ ์†์ข€ ๋ด์ค๋‹ˆ๋‹ค.

{
  "compilerOptions": {
    "target": "es5",                           // ์ปดํŒŒ์ผ๋œ JS ์ฝ”๋“œ์˜ ECMAScript ๋ฒ„์ „
    "lib": ["dom", "dom.iterable", "esnext"],  // ํฌํ•จํ•  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ชฉ๋ก
    "allowJs": true,                           // JS ํŒŒ์ผ ์ปดํŒŒ์ผ ํ—ˆ์šฉ
    "noEmit": false,                           // ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ถœ๋ ฅ ํŒŒ์ผ ์ƒ์„ฑ
    "declaration": true,                       // .d.ts ์„ ์–ธ ํŒŒ์ผ ์ƒ์„ฑ
    "outDir": "dist",                          // ์ปดํŒŒ์ผ๋œ ํŒŒ์ผ ์ €์žฅ ๋””๋ ‰ํ† ๋ฆฌ
    "skipLibCheck": true,                      // ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํŒŒ์ผ ํƒ€์ž… ์ฒดํฌ ์Šคํ‚ต
    "esModuleInterop": true,                   // CommonJS ๋ชจ๋“ˆ์„ ES6์ฒ˜๋Ÿผ ์‚ฌ์šฉ
    "allowSyntheticDefaultImports": true,      // ๋””ํดํŠธ ๋ชจ๋“ˆ import ๋ฌธ๋ฒ• ์‚ฌ์šฉ ํ—ˆ์šฉ
    "strict": true,                            // ์—„๊ฒฉํ•œ ํƒ€์ž… ์ฒดํ‚น ํ™œ์„ฑํ™”
    "forceConsistentCasingInFileNames": true,  // ํŒŒ์ผ ์ด๋ฆ„ ๋Œ€์†Œ๋ฌธ์ž ์ผ๊ด€์„ฑ ๊ฐ•์ œ
    "noFallthroughCasesInSwitch": true,        // switch๋ฌธ์˜ case๋ฌธ ๋„˜์–ด๊ฐ ๋ฐฉ์ง€
    "module": "esnext",                        // ๋ชจ๋“ˆ ์‹œ์Šคํ…œ (์ตœ์‹  ECMAScript)
    "moduleResolution": "node",                // ๋ชจ๋“ˆ ํ•ด์„ ๋ฐฉ์‹ (Node.js)
    "resolveJsonModule": true,                 // JSON ๋ชจ๋“ˆ ๊ฐ€์ ธ์˜ค๊ธฐ ํ—ˆ์šฉ
    "isolatedModules": true,                   // ํŒŒ์ผ์„ ๋…๋ฆฝ์  ๋ชจ๋“ˆ๋กœ ์ปดํŒŒ์ผ
    "jsx": "react-jsx"                         // JSX ์ฝ”๋“œ ์ฒ˜๋ฆฌ ๋ฐฉ์‹ (React JSX)
  },
    // ์ปดํŒŒ์ผํ•  ํŒŒ์ผ ํŒจํ„ด
  "include": ["./src/lib/**/*.tsx", "./src/lib/**/*.ts"]                                            
}

์œ„ ์†์„ฑ ์ค‘ ์ค‘์š”ํ•œ ์†์„ฑ 4๊ฐ€์ง€๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • noEmit
    ์ปดํŒŒ์ผ๋Ÿฌ์˜ ์ถœ๋ ฅ ํŒŒ์ผ ์ƒ์„ฑ ์—ฌ๋ถ€์ž…๋‹ˆ๋‹ค.
    ๋‹น์—ฐํžˆ ๊ด€๋ จ ํŒŒ์ผ๋“ค์ด ์„ธ์ƒ ๋ฐ–์œผ๋กœ ๋‚˜์™€์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— false๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
  • declaration
    ์ปดํŒŒ์ผ๋Ÿฌ์—๊ฒŒ ํƒ€์ž…์„ ์ธ์ง€์‹œ์ผœ์ฃผ๋Š” d.ts ํŒŒ์ผ์˜ ์ƒ์„ฑ ์—ฌ๋ถ€์ž…๋‹ˆ๋‹ค.
    ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ผ๋ฉด ๋‹น์—ฐํžˆ true๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
  • outDir
    ๋นŒ๋“œ ํŒŒ์ผ์˜ ์ƒ์„ฑ ๊ฒฝ๋กœ์ž…๋‹ˆ๋‹ค.
    ๋ณด์•„ํ•˜๋‹ˆ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ด€๋ จ ๋นŒ๋“œ ์‚ฐ์ถœ๋ฌผ์€ dist๋กœ ํ•˜๋Š”๊ฒŒ ๊ตญ๋กค์ด์–ด์„œ ๋”ฐ๋ผ๊ฐ‘๋‹ˆ๋‹ค.
  • include
    ์ปดํŒŒ์ผํ•  ํŒŒ์ผ๋“ค์˜ ํŒจํ„ด์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” src/lib ๋””๋ ‰ํ† ๋ฆฌ ์•„๋ž˜์˜ ๋ชจ๋“  .tsx, .ts ํŒŒ์ผ๋“ค์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

๐Ÿ“Œ 4. package.json ์ปดํŒŒ์ผ ์Šคํฌ๋ฆฝํŠธ ์ž‘์„ฑ

{
  ...
  "dependencies": {
    ...
  },
"scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "compile": "rm -rf dist && mkdir dist && tsc"
  },
  ...
}

package.json ํŒŒ์ผ์˜ scripts ๋ถ€๋ถ„์— ์œ„์™€ ๊ฐ™์€ ๋‚ด์šฉ์„ ์ถ”๊ฐ€ํ•ด์ค๋‹ˆ๋‹ค.

 

์ˆœ์ฐจ์ ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

dist ํด๋” ์‚ญ์ œ (๊ธฐ์กด ์‚ฐ์ถœ๋ฌผ ์‚ญ์ œ) → dist ํด๋” ์ƒ์„ฑ → ์ปดํŒŒ์ผ

 

๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ์ž˜ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


๐Ÿ“Œ 5. package.json์— ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ •๋ณด ์ž‘์„ฑ

npm์— ์˜ฌ๋ฆฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋ณด๋ฉด ๋ญ ์ •๋ณด๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค.

 

์ด๋Ÿฐ ์ •๋ณด๋“ค์„ ๋“ฑ๋กํ•ด๋†”์•ผ ๋ˆ„๊ฐ€ ๋งŒ๋“ค์—ˆ๋Š”์ง€, github ์ฃผ์†Œ๊ฐ€ ์–ด๋””์ธ์ง€ ์•Œ ์ˆ˜ ์žˆ๊ฒ ์ฃ ?

 

๊ทธ๋Ÿฌ๊ธฐ ์œ„ํ•ด package.json์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ •๋ณด๋“ค์„ ์ž‘์„ฑํ•ด์ค๋‹ˆ๋‹ค.

{
  "name": "npm์— ๋“ฑ๋กํ•  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ด๋ฆ„",
  "version": "0.1.0",
  "private": false,
  "main": "dist/index.js",
  "types": "dist/index.d.ts",
  "browser": "./browser/specific/main.js",
  "author": {
    "name": "์ด๋ฆ„",
    "email": "์ด๋ฉ”์ผ",
    "url": "์›น์‚ฌ์ดํŠธ"
  },
  "description": "ํŒจํ‚ค์ง€ ์„ค๋ช…",
  "keywords": ["react", "๊ฒ€์ƒ‰ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•œ ํ‚ค์›Œ๋“œ ๋ฐฐ์—ด"],
  "dependencies": {
    ...
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "compile": "rm -rf dist && mkdir dist && tsc"
  },
  ...
}

์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ ์†์„ฑ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • name
    npm์— ๋“ฑ๋กํ•  ํŒจํ‚ค์ง€ ์ด๋ฆ„์ž…๋‹ˆ๋‹ค.
    npm์— ํŒจํ‚ค์ง€๋ฅผ ์˜ฌ๋ฆฌ๋ ค๋ฉด ์ค‘๋ณต๋˜์ง€ ์•Š์€ ์ด๋ฆ„์ด ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์— npm์— ๊ผญ ํ•œ๋ฒˆ ๊ฒ€์ƒ‰ํ•ด๋ณด์„ธ์š”.
  • private
    ๊ณต๊ฐœํ•˜๋ ค๊ณ  ๋ฐฐํฌํ•˜๋Š” ๊ฑด๋ฐ ๋น„๊ณต๊ฐœ ํ•˜๋ฉด ์•ˆ๋˜๊ฒ ์ฃ ? false๋กœ ๊ณต๊ฐœํ•ด์ค์‹œ๋‹ค.
  • main
    ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ง„์ž…์ ์ธ ์—”ํŠธ๋ฆฌ ํŒŒ์ผ์„ ์ง€์ •ํ•ด์ค๋‹ˆ๋‹ค.
  • types
    ํƒ€์ž…๋“ค์ด ์„ ์–ธ๋˜์–ด ์žˆ๋Š” ์—”ํŠธ๋ฆฌ ํŒŒ์ผ์„ ์ง€์ •ํ•ด์ค๋‹ˆ๋‹ค.

๐Ÿ“Œ 6. npm์— ๋ฐœํ–‰

npm์— ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋ฐœํ–‰ํ•˜๊ธฐ ์œ„ํ•ด npm ๊ณ„์ •์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์•„๋ž˜ ๋ช…๋ น์–ด๋กœ npm ๋กœ๊ทธ์ธ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

npm login

๋กœ๊ทธ์ธ ์ •๋ณด๋ฅผ ์ž…๋ ฅํ•œ ํ›„, npm ํŒจํ‚ค์ง€๋ฅผ ๋ฐœํ–‰ํ•ฉ๋‹ˆ๋‹ค.

npm publish --access=public

--access=public ์˜ต์…˜์„ ์ œ์™ธํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

402 Payment Required - PUT https://registry.npmjs.org/@lasbe/react-ts-lib - You must sign up for private packages

์ •์ƒ์ ์œผ๋กœ ๋ฐœํ–‰์„ ๋งˆ์น˜๋ฉด ์œ„์™€ ๊ฐ™์ด ๊ฒ€์ƒ‰ํ•ด์„œ ํŒจํ‚ค์ง€๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


๐Ÿ“Œ 7. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์žฌ๋ฐœํ–‰ ๋ฐ ๋ฒ„์ „ ๊ด€๋ฆฌ

ํŒจํ‚ค์ง€๋ฅผ ๋ฐœํ–‰ํ•œ ํ›„ ์—…๋ฐ์ดํŠธ๋ฅผ ํ•˜๋ ค๋ฉด ๋ฐ˜๋“œ์‹œ package.json์˜ ๋ฒ„์ „์„ ๋†’ํ˜€์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด ๋ฒ„์ „์€ Semantic Versioning (SemVer) ๊ทœ์น™์„ ๋”ฐ๋ผ์•ผ ์‚ฌ์šฉ์ž์—๊ฒŒ ํ˜ผ๋ž€์ด ์—†์œผ๋ฉฐ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ˆœ์„œ๋กœ ์ž‘์—…ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

  1. ํŒจํ‚ค์ง€ ์ˆ˜์ •
  2. ์ปดํŒŒ์ผ
  3. ๋ฒ„์ „ ์ˆ˜์ •
  4. ๋ฐœํ–‰

๐Ÿ“Œ 8. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ

์ผ๋ฐ˜์ ์œผ๋กœ ํŒจํ‚ค์ง€ ์„ค์น˜ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์„ค์น˜ํ•˜๊ณ  import ํ•ด์„œ ์‚ฌ์šฉํ•˜๋ฉด ์™ ์ง€ ๋ชจ๋ฅผ ๋ฟŒ๋“ฏํ•จ์ด ๋ฐ€๋ ค์˜ต๋‹ˆ๋‹ค.

 

์—ฌ๋Ÿฌ๋ถ„๋„ ๋ณธ์ธ๋งŒ์˜ ํŒจํ‚ค์ง€๋ฅผ ํ•œ๋ฒˆ ๋ฐฐํฌํ•ด๋ณด๋Š” ๊ฑธ ์‹œ์ž‘์œผ๋กœ ์˜คํ”ˆ์†Œ์Šค ์ƒํƒœ๊ณ„์— ๊ธฐ์—ฌํ•ด๋ณด๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค!

๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€


์˜คํ”ˆ ์ฑ„ํŒ