Node.js 패키지와 의존성 이해하기

Sara Jo·2026년 3월 11일
post-thumbnail

패키지와 의존성, 그리고 package.json과 lockfile 등등 헷갈리는 개념 정리해보기!


📦 패키지(Package)란?

패키지는 다른 사람이 만들어 배포한 코드 라이브러리를 의미한다.

예를 들어 이런것들이 다 패키지다.

  • react
  • axios
  • lodash
  • tanstack-query

이런 패키지들은 npm registry에 배포되어 있고, 우리는 다음과 같은 명령어로 쉽게 설치할 수 있다.

pnpm add axios

이렇게 설치하면 프로젝트에서 axios 라이브러리를 사용할 수 있게 된다.

즉,

패키지 = 재사용 가능한 코드 묶음

이라고 이해하면 쉽다.


🔗 의존성(Dependency)

의존성은 프로젝트가 동작하기 위해 필요한 패키지를 의미한다.

예를 들어 코드에서 axios를 사용한다면:

import axios from "axios"

이 프로젝트는 axios에 의존하고 있다고 말할 수 있다.

그래서 package.json에는 다음과 같이 기록된다.

"dependencies": {
  "axios": "^1.6.0"
}

🧾 package.json의 역할

package.json프로젝트의 설정과 의존성을 관리하는 파일이다.

대표적으로 다음과 같은 정보를 담고 있다.

  • 프로젝트 이름과 버전
  • 실행 스크립트
  • 의존성 목록

예시:

{
  "name": "my-project",
  "version": "1.0.0",
  "scripts": {
    "dev": "vite",
    "build": "vite build"
  },
  "dependencies": {
    "react": "^18.2.0",
    "axios": "^1.6.0"
  }
}

여기서 dependencies 항목은

이 프로젝트가 어떤 패키지에 의존하는지

를 보여준다.


🔐 lockfile

package.json을 보면 버전이 이렇게 적혀 있는 경우가 많다.

axios: ^1.6.0

이 의미는

1.6.x 범위에서 최신 버전 사용

이라는 뜻이다.

그래서 설치할 때마다 다음과 같이 다른 버전이 설치될 수 있다.

1.6.1
1.6.2
1.6.5

이 경우 팀원 간에 다른 버전의 패키지가 설치되어 문제가 발생할 수 있다.

이를 해결하기 위해 lockfile이 사용된다.


lockfile의 역할

lockfile은 실제로 설치된 정확한 버전을 기록하는 파일이다.

예를 들어 pnpm-lock.yaml에는 다음과 같은 정보가 저장된다.

axios 1.6.3
lodash 4.17.21

그래서 팀원이 다음 명령어를 실행하면

pnpm install

항상 동일한 버전의 패키지가 설치된다.

대표적인 lockfile은 다음과 같다.

  • package-lock.json (npm)
  • yarn.lock
  • pnpm-lock.yaml

즉,

파일설명
package.json프로젝트가 허용하는 패키지 버전 범위를 정의
lockfile실제 설치된 정확한 패키지 버전을 기록

📌 직접 의존성과 전이 의존성

의존성은 크게 두 가지로 나눌 수 있다.

직접 의존성 (Direct Dependency)

개발자가 직접 설치한 패키지다.

pnpm add axios

이 경우 axios는 직접 의존성이다.

전이 의존성 (Transitive Dependency)

설치한 패키지가 또 다른 패키지를 사용하는 경우다.

예를 들어 axios 내부 구조는 다음과 같다.

my-project
 └ axios
      └ follow-redirects

우리는 follow-redirects를 설치한 적 없지만
axios가 필요로 하기 때문에 자동으로 함께 설치된다.

이런 패키지를 전이 의존성이라고 한다.


🤝 Peer Dependency

Peer dependency는 처음 보면 가장 헷갈리는 개념인데,

간단히 말하면

이 패키지를 사용하려면 특정 패키지가 함께 필요하다

라는 의미다.

예를 들어 react-query는 React 위에서 동작한다.

그래서 내부에 다음과 같이 선언되어 있다.

peerDependencies:
  react: ^18

이 의미는

react-query는 React가 필요하지만
React는 프로젝트에서 직접 설치해야 한다

라는 뜻이다.

그래서 우리는 보통 이렇게 설치한다.

pnpm add react @tanstack/react-query

왜 peer dependency가 필요할까?

React 같은 라이브러리는 여러 버전이 동시에 설치되면 문제가 생긴다.

예를 들어 이런 상황이 발생할 수 있다.

react (앱)
react (라이브러리 내부)

React는 싱글톤 구조로 동작하기 때문에 두 개가 존재하면 충돌이 발생한다.

그래서 React 같은 핵심 라이브러리는 프로젝트에서 직접 관리하도록 peer dependency를 사용한다.


🛠 devDependencies

devDependencies는 개발할 때만 필요한 패키지다.

예:

  • typescript
  • eslint
  • vite
  • prettier
  • jest

예시:

"devDependencies": {
  "typescript": "^5.0.0"
}

이 패키지들은 개발 환경에서만 필요하고 실제 서비스 실행에는 필요하지 않다.


📚 정리

패키지 관리 구조는 다음과 같이 정리할 수 있다.

프로젝트
 ├ package.json
 │     ├ dependencies
 │     ├ devDependencies
 │     └ peerDependencies
 │
 ├ lockfile
 │     └ 실제 설치된 버전 기록
 │
 └ node_modules
       ├ 직접 의존성
       └ 전이 의존성

1️⃣ package.json → 어떤 패키지를 사용할지 정의
2️⃣ lockfile → 실제 설치된 정확한 버전 기록
3️⃣ node_modules → 실제 패키지가 설치되는 위치

이 개념을 이해하면 패키지 관련 문제를 훨씬 쉽게 해결할 수 있다. 🚀

0개의 댓글