npm

우리에게 흔히 알려진 패키지 매니저로 npm, yarn, pnpm 등이 있다. 각각의 특징과 장단점을 사용경험에 비추어 정리해보려한다. npm을 시작으로 하나씩 다뤄보자.

npm?

npm은 node package manager의 약자로, Node.js 에 내장되어 자동으로 설치되는 패키지 매니저이다. 여기서 말하는 패키지란, Node.js 환경에서 사용이 가능한 모듈/라이브러리들을 의미한다. 즉, Node.js 환경에서 사용가능한 라이브러리들을 다운받을수 있게 하는 도구를 우리는 패키지 매니저라고 부른다. (앱스토어와 유사하다.)

주로 npm install [라이브러리] 의 명령어로 라이브러리를 설치하며, 설치된 라이브러리들은 ./node_modules 에 설치된다. 그런데 우리가 npm으로 설치해 사용하는 라이브러리들은 빈번하게 업데이트가 이루어진다. 그렇다면 업데이트가 될때마다 변경점에 맞추어 프로젝트를 수정해야하나? 물론 그럴수 있겠지만, 보통 어떠한 파일을 통해 설치된 라이브러리들의 버전을 명시하여 관리하게 되고, 이 파일이 바로 package.json이다.

package.json

{
  "name": "next_template",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "eslint --cache .",
    "format": "prettier --cache --write .",
    "prepare": "husky",
    "postinstall": "husky install"
  },
  "dependencies": {
    "next": "^14.2.15",
    "next-themes": "^0.2.1",
    "react": "^18",
    "react-dom": "^18"
  },
  "devDependencies": {
    "@types/node": "^20.11.24",
    "@types/react": "^18.2.56",
    "@types/react-dom": "^18.2.19",
    "@typescript-eslint/eslint-plugin": "^6.21.0",
    "@typescript-eslint/parser": "^7.0.2",
    "autoprefixer": "^10.0.1",
    "eslint": "^8.57.0",
    "eslint-config-prettier": "^9.1.0",
    "eslint-config-standard-with-typescript": "^43.0.1",
    "eslint-import-resolver-typescript": "^3.6.1",
    "eslint-plugin-import": "^2.29.1",
    "eslint-plugin-n": "^15.0.0 || ^16.0.0 ",
    "eslint-plugin-promise": "^6.0.0",
    "eslint-plugin-react": "^7.34.0",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-react-refresh": "^0.4.5",
    "husky": "^9.0.11",
    "lint-staged": "^15.2.2",
    "postcss": "^8",
    "prettier": "^3.2.5",
    "tailwindcss": "^3.3.0",
    "typescript": "^5"
  },
  "lint-staged": {
    "./src/**/*.{js,jsx,ts,tsx}": [
      "prettier --cache --write",
      "eslint-config-prettier './src/**/*.{js,jsx,ts,tsx}'",
      "eslint --cache --fix --max-warnings=0"
    ]
  },
  "eslintIgnore": [
    "next-env.d.ts",
    "next.config.js",
    "postcss.config.js"
  ],
}

우리에게 익숙한 package.json 파일이다. 이 파일을 통해 프로젝트의 정보와 사용되는 라이브러리, 라이브러리들의 버전 등 패키지 의존성을 관리한다. 프로젝트를 클론하거나 테스트해볼때도 이 파일을 바탕으로 의존성을 설치해 실행하게 된다.

여기서 눈여겨볼점은 dependenciesdevDependencies가 나뉘어져 있다는 점이다. 개발의존성과 그냥 의존성을 분리해놓은 이유는, dependencies 에 명시된 라이브러리들은 배포 시에 포함되지만, devDependencies 에 명시된 라이브러리들은 말 그대로 개발 의존성이기 때문에 배포할때 포함되지 않는다. 이를 통해 보다 빠른 빌드시간을 가질수 있고, 배포시 불필요한 의존성을 설치하지 않을수 있다.

Why npm?

직접 npm을 사용해본 경험을 비춰보아, npm의 가장 큰 장점은 간편함 인것 같다. Node.js에 내장되어 있어 추가적인 설치가 필요없다. 물론 다른 패키지 매니저들의 설치/사용이 어려운것은 아니지만, 신경써야 할 부분이 하나 줄어든다는 것을 무시하지 못할 것 같다.

그리고 대부분의 라이브러리들이 npm에서 설치를 지원하며, NPM 홈페이지 를 통해 어떤 라이브러리들이 있는지 확인도 가능하다.

그럼 npm만 사용하면 되는것 아닌가? 라는 생각이 들겠지만, 장점이 있으면 단점도 분명히 있는 법.

대표적인 단점으로는 패키지 수가 많아질수록 node_modules 폴더의 크기가 커져 빌드 시간이 크게 증가한다는 점이다. 또한, 서로 다른 패키지가 동일한 의존성을 서로 다른 버전으로 요구할 경우, 기존 node_modules 내부에 새로운 node_modules 폴더가 생성되어 트리 구조가 복잡해지고, 설치 시간과 폴더 크기가 더욱 늘어나는 의존성 문제가 발생한다.

Last updated