현록

dependencies와 devDependencies 차이

Node 프로젝트를 처음 다루면 package.json 안의 dependenciesdevDependencies가 헷갈린다.
둘 다 패키지 목록처럼 보이는데, 어떤 패키지는 위에 있고 어떤 패키지는 아래에 있다.
명령어도 npm install react처럼 쓰는 경우가 있고, npm install -D eslint처럼 -D를 붙이는 경우가 있다.

핵심은 간단하다.
dependencies는 애플리케이션 실행에 필요한 패키지다.
devDependencies는 개발, 빌드, 테스트처럼 개발 과정에 필요한 패키지다.

dependencies의 역할

dependencies에는 앱이 실행될 때 필요한 패키지를 넣는다.
코드가 런타임에서 직접 import하거나, 배포된 앱이 동작하기 위해 필요한 패키지가 여기에 들어간다.

예를 들어 React 앱이라면 reactreact-dom은 보통 dependencies에 들어간다.
서버 앱이라면 express, zod, 데이터베이스 클라이언트 같은 패키지도 실행에 필요할 수 있다.

{
  "dependencies": {
    "react": "19.2.5",
    "react-dom": "19.2.5",
    "zod": "4.3.6"
  }
}

npm install react처럼 별도 옵션 없이 설치하면 npm은 기본적으로 패키지를 dependencies에 저장한다.
예전에는 --save 옵션을 명시하는 예시도 많았지만, 현재 npm에서는 기본 동작으로 생각하면 된다.

devDependencies의 역할

devDependencies에는 개발할 때 필요한 패키지를 넣는다.
애플리케이션 실행 자체에는 필요하지 않지만, 코드를 만들고 검사하고 빌드하는 과정에 필요한 도구가 여기에 들어간다.

대표적인 예시는 TypeScript, ESLint, Prettier, Vitest, Playwright 같은 패키지다.
이 패키지들은 개발자가 코드를 작성하거나 CI에서 테스트를 돌릴 때 필요하지만, 배포된 런타임 코드가 직접 import하지 않는 경우가 많다.

{
  "devDependencies": {
    "typescript": "6.0.3",
    "eslint": "9.39.4",
    "prettier": "3.8.3",
    "vitest": "4.1.5"
  }
}

개발용 패키지는 -D 또는 --save-dev 옵션으로 설치한다.

npm install -D eslint
npm install --save-dev prettier

두 명령어는 같은 의도로 사용한다.
짧게 쓰고 싶으면 -D, 명확하게 쓰고 싶으면 --save-dev를 쓰면 된다.

npm install과 npm install -D의 차이

npm installnpm install -D의 차이는 설치 위치다.
둘 다 node_modules에 패키지를 설치하고 lock 파일을 갱신할 수 있다.
다만 package.json에 기록되는 위치가 다르다.

npm install axios

이 명령어는 axiosdependencies에 추가한다.

npm install -D eslint

이 명령어는 eslintdevDependencies에 추가한다.

설치 후에는 package.json을 확인하는 습관이 좋다.
실행에 필요한 패키지를 실수로 devDependencies에 넣으면 배포 환경에서 빠질 수 있다.
반대로 개발 도구를 dependencies에 넣으면 프로덕션 설치가 불필요하게 무거워질 수 있다.

배포 환경에서 설치되는 의존성

배포 환경에서는 개발용 의존성을 설치하지 않도록 설정하는 경우가 있다.
npm에서는 --omit=dev 옵션을 사용하면 devDependencies를 디스크 설치에서 제외할 수 있다.
production 설정에서도 dev 의존성을 제외하는 흐름이 사용될 수 있다.

npm ci --omit=dev

이 명령어는 lock 파일을 기준으로 설치하되, 개발용 의존성은 실제 node_modules에 설치하지 않는다.
CI나 배포에서 npm ci를 사용하는 이유는 npm ci란?에 따로 정리해두었다.

여기서 주의할 점이 있다.
Next.js, Vite, TypeScript처럼 빌드가 필요한 프로젝트는 배포 전에 빌드 도구가 필요할 수 있다.
빌드 단계에서는 devDependencies가 필요하고, 빌드가 끝난 런타임 단계에서는 필요 없을 수 있다.
그래서 Docker나 서버 배포에서는 빌드 단계와 실행 단계를 나눠서 의존성을 설치하기도 한다.

헷갈리기 쉬운 패키지 예시

프레임워크 패키지는 프로젝트 방식에 따라 판단이 달라질 수 있다.
next는 빌드 도구처럼 보이지만, Next.js 앱을 실행할 때도 필요할 수 있어서 보통 dependencies에 둔다.
반면 eslint-config-next는 lint 설정에 필요하므로 devDependencies에 두는 경우가 자연스럽다.

타입 패키지도 자주 헷갈린다.
@types/node, @types/react 같은 패키지는 TypeScript가 타입 검사를 할 때 쓰므로 보통 devDependencies에 둔다.
실행 중인 JavaScript 코드가 타입 패키지를 import하는 것은 아니다.

테스트 도구도 대부분 devDependencies에 둔다.
vitest, jest, playwright, @testing-library/react는 앱 실행보다 검증 과정에 가깝다.

package-lock.json과의 관계

dependenciesdevDependenciespackage.json에 사람이 읽기 좋은 의존성 선언으로 저장된다.
반면 package-lock.json은 실제로 설치될 전체 의존성 트리를 더 자세히 기록한다.
직접 설치한 패키지뿐 아니라, 그 패키지가 다시 의존하는 하위 패키지까지 포함된다.

그래서 개발용 패키지를 설치해도 package-lock.json은 함께 바뀔 수 있다.
이것은 정상이다.
lock 파일은 설치 결과를 재현하기 위한 파일이기 때문이다.
lock 파일의 역할은 package-lock.json 파일의 역할에 따로 정리해두었다.

.npmrc 설정도 설치 결과에 영향을 줄 수 있다.
registry, peer dependency 처리 방식, install 옵션을 프로젝트에서 고정해야 한다면 .npmrc 파일이란?도 같이 보면 좋다.

정리

dependencies는 실행에 필요한 패키지다.
devDependencies는 개발, 빌드, 테스트에 필요한 패키지다.

npm install 패키지명은 기본적으로 dependencies에 저장한다.
npm install -D 패키지명devDependencies에 저장한다.

패키지를 어디에 둘지 헷갈리면 한 가지 질문을 해보면 된다.
이 패키지가 배포된 앱이 실행되는 순간에도 필요한가.
필요하다면 dependencies에 가깝고, 코드 작성이나 검증 과정에서만 필요하다면 devDependencies에 가깝다.

참고 자료

관련 포스트
npm ci란? thumbnail
npm ci란?
npm ci는 CI, 테스트, 배포처럼 같은 의존성 트리를 반복해서 설치해야 하는 환경에 어울리는 clean install 명령어입니다. package-lock.json 조건, npm install과의 차이, .npmrc 플래그 주의점을 정리합니다.
.npmrc 파일이란? thumbnail
.npmrc 파일이란?
storybook을 사용해보려고 하다 마주한 이슈의 해결법을 알아보다가 등장한 .npmrc라는 파일에 대해 공부해보았다. .npmrc 파일이란? .npmrc 파일은 npm에 대한 config 파일이다. (npm에 대한 rc 파일) 프로젝트별 registry, install 옵션, 인증 토큰처럼 npm CLI가 읽는 설정을 관리할 때 사용한다.
스토리북이란? thumbnail
스토리북이란?
Storybook은 UI 컴포넌트를 독립적으로 개발하고, 문서화하고, 테스트하기 위한 프론트엔드 워크샵입니다. Storybook 10.4 기준 설치 흐름과 stories, 문서화, 테스트 활용 방식을 정리합니다.
TTV와 TTI란? thumbnail
TTV와 TTI란?
TTV는 Time to View이며, 사용자가 화면을 보는 시점을 의미한다. TTI는 Time to Interact이며, 사용자가 웹에서 특정 동작을 수행할 수 있는 시점을 의미한다.
Maria DB 외부 접속 설정하기 thumbnail
Maria DB 외부 접속 설정하기
안녕하세요. 오늘은 Maria DB 초기 세팅 시, 외부에서 접속이 안될 때 매뉴얼을 작성해보겠습니다. dotenv 패키지를 통해서 환경변수로 관리한다면, 별도의 추가 작업을 할 일이 없으실 겁니다.
package-lock.json 파일의 역할 thumbnail
package-lock.json 파일의 역할
안녕하세요. 오늘은 node 환경의 개발자라면 한번쯤 궁금했을만한 package-lock.json의 역할에 대해 알아보겠습니다. 우리는 node 환경에서 개발을 할 때 다양한 패키지들을 설치하여 활용하곤 합니다. 우리가 설치하는 패키지 또한 다른 npm 패키지를 활용하여 만든 패키지들이고 이들 또한 설치를 하게 됩니다. 이렇게 직간접적으로 설치된 패키지들은 대부분 호환성을 "^1.1.5"와 같이 표현하여, 범위로 지정해두고 있습니다.
Linux 환경 배포 자동화 체험해보기 thumbnail
Linux 환경 배포 자동화 체험해보기
안녕하세요. 요즘 포트폴리오를 만들면서 서버 상에 자주 반영할 일이 생겼는데, 매번 명령어들을 타이핑하는 것이 비효율적이라 생각이 들어 배포 자동화를 생각해보게 되었습니다. 현재 레벨에서는 단순히 명령어들만 단축시켜도 효율적이라 생각이 들어 간단한 쉘 스크립트만 작성하였습니다. 정말 간단하니 여러분도 도전해보시길 바랍니다.
협업 필수품. Prettier thumbnail
협업 필수품. Prettier
안녕하세요. 오늘은 Prettier이라는 도구에 대해 알려드리고자 합니다. 개발자는 각자의 코딩스타일이 존재합니다. 그러다보니 같은 프로젝트에서도 작성하는 소스마다 스타일이 제각기 다르기 일쑤입니다. 그럴 때 도입하면 좋은 것이 Prettier입니다. 프로젝트 root 폴더에 .prettierrc 라는 파일을 생성한 뒤, 위 예시와 같이 원하는 옵션을 JSON 형식으로 작성해주면 됩니다.