NPM

버전 정의

  • npm 패키지 버전 : Major.Minor.Patch
    1. Major : 이전 버전과 호환되지 않으면 변경
    2. Minor : 이전 버전과 호환되면서 신규 기능 추가
    3. Patch : 이전 버전과 호환되면서 버그 수정
  • ^1.2.2 : [1.2.2, 2.0.0) 호환
  • 0이 아닌 최초 버전의 하위 버전 변경 모두를 포함

  • ~1.2.2 : [1.2.2, 1.3) 호환
  • 지정된 버전의 상위 버전 변경 전까지 모두를 포함

  • 1.2.2-1.4.4 : 직접 지정
  • >=1.2.2 <=1.4.4와 동일

  • 1.2.x : 와일드카드

프로젝트 의존성 관리

↓shell

$ npm init # package.json 생성 $ npm install # package.json대로 의존 라이브러리 설치 # name 패키지 설치 후 package.json에 의존성 추가 $ npm install name --save $ npm install name --save-dev

package.json

아래 예시는 다른 패키지의 것들을 맘대로 섞은 것임

↓javascript

{ "name": "mongodb", // 대문자 사용 불가. URL 안전해야 함 "version": "3.5.4", "description": "The official MongoDB driver for Node.js", "author": { // 1명만 가능. name은 필수 "name": "TJ Holowaychuk", "email": "tj@vision-media.ca", "url": "http://1.1.1.1/" }, "contributors": [ "Aaron Heckmann <aaron.heckmann+github@gmail.com>", "Ciaran Jessup <ciaranj@gmail.com>" ], "keywords": [ // npm 검색 키워드 "mongodb", "driver" ], "homepage": "https://github.com/mongodb/node-mongodb-native", "repository": { // 버전 관리 저장소 "type": "git", "url": "git@github.com:mongodb/node-mongodb-native.git" }, "bugs": { // url 또는 email 하나만 적용 "url": "https://github.com/mongodb/node-mongodb-native/issues" }, "license": "Apache-2.0", "main": "index.js", // 메인 모듈 설정. require시 해당 모듈의 exports가 넘겨진다 "files": [ // 패키지 포함 목록. ".npmignore" 파일로 제외 항목 관리 가능 "index.js", "lib" ], "bin": { // 패키지 설치 시 실행 파일에 대한 링크를 만들어 CLI 실행 가능하게 한다 "forever": "./bin/forever.js" }, "dependencies": { // 의존 패키지 "bl": "^2.2.0", }, "peerDependencies": { // 의존 관계 X. 같이 사용될 수 있는 패키지 "kerberos": "^1.1.0", }, // 패키지 테스트, 문서화에 필요한 패키지; 모듈 사용만 하는 경우엔 불필요한 패키지 "devDependencies": { "eslint": "2.13.1", "mocha": "7.0.1" }, "scripts": { // npm이 패키지 관리 시 실행할 명령. https://docs.npmjs.com/misc/scripts "lint": "eslint .", "test": "mocha --require test/support/env --reporter spec --bail --check-leaks test/ test/acceptance/" }, "engines": { // Node 버전 제한 "node": ">=10" } }

패키지 배포

참고자료

프로젝트 설정

  1. 프로젝트를 위한 GitHub 저장소가 없다면 하나 생성
  2. 작업 환경에 GitHub 저장소 클론
  3. npm 프로젝트 설정이 안 됐다면 $ npm init으로 package.json 초기화
  4. 프로젝트 이름에 GitHub 사용자/조직 이름을 포함하여 구분시키기
  5. e.g. @aws-sdk/client-s3

NPM 계정 생성

  1. signup
  2. $ npm login

배포 관련 커맨드

↓shell

$ npm pack # 패키지 tar 생성. --dry-run 가능 $ npm publish --access=public # 패키지 배포. --dry-run 가능 $ npm version # 버전 설정/증가 $ npm unpublish # 배포 중단

프로덕션 사용을 위한 설정

CommonJS와 ECMAScript Module 모두 지원하기

  1. TypeScript 설치
  2. 공통 설정 파일 작성
  3. ↓configs/tsconfig.base.json

    { "compilerOptions": { "strict": true, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "skipLibCheck": true, "checkJs": true, "allowJs": true, "declaration": true, "declarationMap": true, "allowSyntheticDefaultImports": true, "experimentalDecorators": true }, "include": [ "../src/**/*" ] }
  4. CommonJS 타입을 위한 설정 파일 작성
  5. ↓configs/tsconfig.cjs.json

    { "extends": "./tsconfig.base.json", "compilerOptions": { "lib": [ "ES6", "DOM" ], "target": "ES6", "module": "CommonJS", "moduleResolution": "Node", "outDir": "../lib/cjs", "declarationDir": "../lib/types" } }
  6. ECMAScript Module 타입을 위한 설정 파일 작성
  7. ↓configs/tsconfig.esm.json

    { "extends": "./tsconfig.base.json", "compilerOptions": { "lib": [ "ES6", "DOM" ], "target": "ES6", "module": "ESNext", "moduleResolution": "Node10", "outDir": "../lib/esm", "declarationDir": "../lib/types" } }
  8. 빌드 산출물을 모두 포함하도록 package.json 설정
  9. ↓package.json

    { "files": ["lib/**/*"] }
  10. 모듈 로더에 따라 적절한 위치에서 파일을 찾도록 package.json 설정
  11. ↓package.json

    { "exports": { ".": { "import": { "types": "./lib/types/index.d.ts", "default": "./lib/esm/index.mjs" }, "require": { "types": "./lib/types/index.d.ts", "default": "./lib/cjs/index.js" } } } }
  12. CJS 산출물에 맞춰 package.json 기본값 설정
  13. ↓package.json

    { "types": "./lib/types/index.d.ts", "main": "./lib/cjs/index.js" }
  14. package.json에 빌드 커맨드 설정
  15. ↓package.json

    { "scripts": { "clean": "rm -rf ./lib hi.donggi-test-*.tgz", "build": "npm run clean && npm audit --omit dev && npm run build:esm && npm run build:cjs && npm pack", "build:cjs": "npx tsc -p ./configs/tsconfig.cjs.json", "build:esm": "npx tsc -p ./configs/tsconfig.esm.json && mv ./lib/esm/index.js ./lib/esm/index.mjs" } }

테스트 코드 작성

  • mocha 패키지 : 테스트 실행 라이브러리
  • chai 패키지 : assertion 라이브러리
  • ts-node 패키지 : TypeScript 코드 즉시 실행 라이브러리
  • 테스트 실행 설정
  • ↓.mocharc.json

    { "extension": [ "ts" ], "spec": "./tests/**/*.spec.ts", "require": "ts-node/register", "parallel": true, "jobs": 8, "timeout": 5000 }
  • tests 디렉터리에 테스트 코드 작성
  • package.json에 테스트 커맨드 설정
  • ↓package.json

    { "scripts": { "test": "env TS_NODE_PROJECT=./configs/tsconfig.cjs.json npx mocha" } }

eslint 설정

  • $ npx eslint --init으로 초기화
  • ↓.eslintrc.json

    { "env": { "browser": true, "es2021": true, "node": true, "mocha": true }, "extends": [ "standard" ], "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": "latest", "sourceType": "module" }, "plugins": [ "@typescript-eslint" ], "rules": { "indent": [ "error", 4 ] } }
  • VS Code eslint 확장 프로그램이 낮은 버전의 기본 설치 Node를 이용하는 경우 런타임 변경
  • ↓settings.json

    { "eslint.runtime": "/Users/user/.nvm/versions/node/v18.16.0/bin/node" }
  • VS Code에서 파일 저장시 자동으로 수정사항 적용
  • ↓settings.json

    { "editor.codeActionsOnSave": { "source.fixAll.eslint": true }, "eslint.alwaysShowStatus": true }

패키지를 배포하기 전에 작동하는지 확인

  • 라이브러리 프로젝트 디렉터리에서, 번들 생성
  • ↓shell

    $ npm pack
  • 라이브러리를 사용할 프로젝트 디렉터리에서, 번들 설치
  • ↓shell

    $ npm install file:./path/to/package.tgz

TypeScript

  1. JavaScript에 타입이 추가된 수퍼셋. 컴파일하면 자바스크립트 코드가 된다
  2. ↓shell

    $ npm install --save-dev typescript $ npx tsc file-name.ts --target es6
  3. 타입스크립트에서는 생성자 매개변수 앞에 public/private 접근한정자가 있으면 자동으로 클래스의 속성으로 선언한다
  4. VS Code의 타입스크립트 컴파일러를 npm 패키지로 설정
  5. "typescript.tsdk": "C:/Users/name/AppData/Roaming/npm/node_modules/typescript/bin/tsc"

디버깅

Lib/Cluster

Lib/Console

↓javascript

console.log(any data[, any ...args]) // + info, debug, warn, error // util.format(format[, ...args]) 형태의 호출 가능 console.table(any tabularData[, string[] properties]) // Since 10 console.time([string label]) // + timeEnd // label(기본값 'default')로 타이머 시작/종료 console.timeLog([string label][, any ...data]) // Since 10.7 // label(기본값 'default')의 타이머를 중지하지 않고, 경과 시간과 data 출력 console.trace([any message][, any ...args]) // 스택 출력 new console.Console(stream.Writable stdout[, stream.Writable stderr][, boolean ignoreErrors]) console.assert(any value[, any ...message]) // value가 false면 console.error(...message) console.count([string label]) // Since 8.3 + countReset // label(기본값 'default')로 몇 번 호출했는지 출력한다 console.dir(any obj[, Object options]) // boolean options.showHidden : 기본값 false // number options.depth : 기본값 2. null이면 끝까지 재귀 console.group([any ...label]) // console.log(...label)실행 후, 다음 출력부터는 앞에 공백 2개 추가 // + groupEnd

Lib/Events

Lib/Globals

Lib/HTTP, HTTPS

Lib/Modules

  1. require(string id)
    • 각 파일들은 별개의 모듈로 취급된다
    • require('./foo/bar.js');

    • 로드된 모듈은 캐시되므로, 반복적인 require()는 같은 객체를 반환한다
    • require()가 두 개 이상의 파일을 찾은 경우, 요구한 이름의 대소문자를 바꾼 경우 등은 예외

    • 모듈이 Node에 의해 직접 실행되는 경우, require.main으로 설정된다
    • 따라서 require.main === module로 현재 모듈이 메인인지 판별 가능하다

    • 모듈 사이에 require() 사이클이 존재하는 경우, 초기화 완료되지 않은 exports 객체를 반환하여 무한 반복을 방지한다
    • 모듈을 /usr/lib/node_modules/{name}/{version} 경로로 관리하면 효율적인 require() 가능
    • require알고리즘
    • 확장자 없는 파일 X, X.js 파일, X.json 파일, X.node 파일, X/index.js 디렉터리, X/package.json 디렉터리 등을 적절히 처리

    • 선두 '/', './', '../' 없이 요구된 모듈
      1. core 모듈이면 해당 모듈 로드
      2. ROOT 디렉터리에 도달할 때까지, {부모 디렉터리}/node_modules/{X} 모듈을 탐색
    • 아무데서도 모듈을 찾지 못한 경우, $NODE_PATH 환경변수의 디렉터리를 탐색하지만, $NODE_PATH 사용은 권장되지 않는다
  2. 디렉터리를 모듈로
    1. package.json
    2. ↓javascript

      { "name" : "some-library", "main" : "./lib/some-library.js" }
    3. index.js
  3. 로드된 모듈의 실행은 아래와 유사하다
  4. ↓javascript

    (function(exports, require, module, __filename, __dirname) { // Module code actually lives in here });
    1. 모듈 top-level에 정의된 변수들이 모듈 스코프에 존재
    2. 모듈 밖에서는 exports를 공유
    3. 최초 exports는 module.exports를 가리키므로, exports에 다른 객체를 할당하는 경우, 해당 부분은 외부와 공유되지 않는다. 외부에 공유하려면 module.exports = exports = newObject

    4. 모듈 안에서는 __filename, __dirname을 편리하게 획득

Lib/Process

3rd/CryptoJS

해싱, 암/복호화, 인코딩/디코딩 관련 함수 제공

3rd/express : Web Framework

3rd/fastify : Web Framework

3rd/forever : 종료 시 자동 재시작

3rd/Pug : 템플릿 엔진(구 Jade)

3rd/mocha : 테스트 프레임워크

3rd/mongodb : MongoDB 공식 드라이버