최근 수정 시각 : 2024-11-20 14:19:39

npm


파일:나무위키+유도.png  
은(는) 여기로 연결됩니다.
New Public Management의 약자인 NPM에 대한 내용은 신공공관리론 문서
번 문단을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
참고하십시오.
<colbgcolor=#ffffff,#1f2023><colcolor=#cb3837> npm
파일:npm 로고.svg
개발사 npm, Inc.
분류 패키지 관리자
공개일 2010년 1월 12일
최신 버전 10.4.0
파일:홈페이지 아이콘.svg | 파일:GitHub 아이콘.svg 파일:GitHub 아이콘 화이트.svg

1. 패키지 관리자
1.1. 개요1.2. 대안
2. 패키지 저장소
2.1. 주요 패키지2.2. 인수2.3. 문제점2.4. 사건 사고
2.4.1. left-pad 사건2.4.2. funding 사건2.4.3. everything 사건

[clearfix]

1. 패키지 관리자

1.1. 개요

Node.js의 패키지를 관리할 수 있는 도구이다. Python의 pip나 Ruby의 gem처럼, 후술할 웹 사이트에서 패키지를 다운로드하여 컴퓨터에 설치해 준다.

package.json에서 메타데이터와 파일의 종속성 기록하며, 이러한 종속성의 정확한 버전 및 의존성 트리는 package-lock.json과 npm-shrinkwrap.json에서 관리한다.

일반적인 경우에는 Node.js를 설치하면 자동으로 설치된다.

7 버전부터 자체적인 Workspace 를 지원하여 다중 모듈 프로젝트를 구성할 수 있다.

흔히 npm이 'Node Package Manager'의 줄임말로 알려져 있으나, 공식적으로는 npm은 줄임말이 아닌 그 자체로 하나의 단어라고 한다. Github의 npm 공식 문서에 따르면 기존의 "pkgmakeinst", 줄여서 "pm"을 진화시킨 작품이라고 소개하고 있으니 굳이 풀어서 쓴다면 Node pm 혹은 Node pkgmakeinst가 되겠지만, 풀지 말고 npm으로 불러달라면서 덤으로 가능한한 소문자로만 표기하여 사용할 것을 요청하고 있다.

1.2. 대안

이 문단에서는 npm 대신 사용할 수 있는 node.js 패키지 관리자를 소개한다. 하지만 npm은 지울 수 없으므로 추가 설치하는 방식으로 관리한다.
각 패키지 관리자들의 관리 방식이 다르기 때문에, 패키지 관리자 전환 시 node_modules 와 각 패키지 관리자의 .lock 파일을 제거 후 수행하는 것을 추천한다.

여기에 소개된 패키지 관리자들은 모두 npm(웹 사이트)에서 패키지를 다운로드해 설치한다. Yarn은 registry.yarnpkg.com을 사용하고 있으나 해당 도메인은 npm(웹 사이트)의 서버로 연결되어 있므로 같은 패키지 저장소에 접속하게 된다.
  • yarn: npm의 알려진 단점으로는 패키지 종속성 해결이 쉬운 만큼, 패키지가 중복 설치된다는 문제가 있다. yarn은 이 문제를 해결하기 위해 중복 패키지 발견 시 링크(바로가기) 방식으로 해결한다. 또한, lerna Workspace 패키지와의 궁합으로 효율적으로 다중 모듈 패키지를 관리할 수 있었기 때문에 각광을 받았다. 그래서 Workspace 기능을 통한 다중 모듈이 요구되는 국내 환경에서 많이 사용하고 있는 패키지 관리자. yarn 2에서는 이를 더 개선하여 pnpm과 비슷하게 Workspace 자체 지원, 더 효율적인 패키지 관리 기능을 지원한다. 특이 사항으로는 .lock 파일이 YAML 방식이다.
  • pnpm: 또다른 패키지 관리자로 빠른 속도와 디스크 용량 절약을 내세우는 또다른 패키지 관리자. Yarn과는 달리 한국에서 많이 알려져 있지 않지만, 특히 모 스트리머 유저의 닉네임이라 자체적으로 지원하는 다양한 기능(더욱 유연한 Workspace, 패키지 별칭 등)과 신속성, 절약성 때문에 요즘 사용 중인 패키지 프로젝트에서 채택하고 있다. 호불호가 큰 특징으로는, pnpm은 package.json 에 정의한 패키지만 설치한다. 기존 npm에서 특정 패키지를 설치하면 거기에 필요한 패키지를 추가로 설치하기 때문에 별도로 명시하지 않아도 패키지 내 제공하는 기능을 바로 사용할 수 있는 반면, pnpm은 명시된 패키지만 사용할 수 있으며 설치한 패키지에 요구되는 패키지 내 기능을 사용할 수 없다는 단점이 있다. 용량을 아끼는 대신 희생한 기능으로, 이를 해결하려면 직접 필요한 패키지를 명시하거나 pnpm hook 기능을 사용하라고 공식 문서에 기재되어 있다. 이는 yarn 2에서도 채택한 방식이다.

2. 패키지 저장소

위의 프로그램이 패키지를 다운로드할 때 사용하는 패키지 저장소 (package registry) 서비스의 이름으로, 동명의 회사가 운영하고 있다. 홈페이지는 https://www.npmjs.com이다.

JavaScript와 Node.js의 급격한 인기몰이에 힘입어 빠르게 성장하여 세계 최대의 패키지 저장소가 되었다. 2020년 9월 기준으로 140만 개의 패키지가 등록되었다.[1]

2.1. 주요 패키지

  • Express.js - Node.js에서 가장 인기있는 웹 프레임워크이다.
  • Request: Node.js에서 HTTP Request를 편리하게 보낼 수 있도록 만들어진 모듈이다.[2]
  • Mongoose: 비동기 환경에서 작동할 수 있도록 설계된 MongoDB 오브젝트 모델링 툴이다.
  • EJS: 템플릿을 사용해 HTML을 동적으로 생성할 수 있게 하는 패키지이다. PHP와 같은 서버사이드 언어로 페이지를 렌더링할 수 있게 한다. 이 외에도 Mustache나 Handlebars, Pug와 같은 수많은 템플릿 패키지가 있다.

2.2. 인수

2020년 3월 16일 GitHub이 인수한다고 발표했다.[3] GitHub은 2018년에 마이크로소프트가 인수했으니 사실상 Microsoft의 소유가 된 것이다.

2.3. 문제점

워낙 많은 패키지가 등록되었다 보니 자신이 원하는 이름을 찾으려 하면 이미 남이 선점한 경우가 많다. 별다른 기능이 없는 쓸모없는 패키지를 수십, 수백 개씩 만들어서 알박기하는 사람도 있다. 심지어 인기있는 패키지의 이름과 비슷한 이름으로 가짜 패키지를 등록하여, 패키지 이름을 잘못 입력하는 개발자를 노리는 경우도 있다. 이때 가짜에는 악성 코드를 심어 설치된 컴퓨터를 해킹한다.

알박기에 대처하는 가장 좋은 방법은 스코프(scope)를 사용하는 것이다. 스코프는 @ 문자 뒤에 npmjs.com에 등록된 자신의 계정명을 붙인 것으로, 해당 스코프에 속한 패키지는 계정의 주인만이 만들거나 지울 수 있다. 따라서 적절한 계정명을 선점했다면 패키지를 마음대로 만들 수 있다.

예시: 계정명이 'namu'이면 스코프는 @namu가 되며, 이 스코프 내에 hello-world라는 패키지를 만들면 이름이 @namu/hello-world가 된다.

이 외에도 알박기라 의심되는 패키지에 대해 이의제기를 하면 npm의 심의를 거쳐 패키지명의 소유권을 강제로 넘겨받을 수 있다. 다만 이 때문에 후술할 left-pad 사건이 발생하였다.

2.4. 사건 사고

2.4.1. left-pad 사건


파일:CC-white.svg 이 문서의 내용 중 전체 또는 일부는 문서의 r404에서 가져왔습니다. 이전 역사 보러 가기
파일:CC-white.svg 이 문서의 내용 중 전체 또는 일부는 다른 문서에서 가져왔습니다.
[ 펼치기 · 접기 ]
문서의 r404 ( 이전 역사)
문서의 r ( 이전 역사)

npmjs.com에 등록된 패키지 하나가 삭제된 것으로 인해 수많은 IT 회사의 업무가 마비된 사건이다.

미국 캘리포니아에 사는 에저 코출루(Azer Koçulu)라는 개발자는 자신이 만든 여러 프로그램을 npmjs.com에 올려 공개하고 있었는데, 그 중에는 'kik'이라는 패키지도 있었다. 어느 날, Kik이라는 회사의 변리사가 코출루에게 이메일을 보내, 'kik'이라는 이름에 대한 상표권을 자기 회사가 갖고 있으니 코출루가 만든 패키지의 이름을 바꿔달라고 요청했다. 코출루가 이를 거절하자 해당 직원은 비즈니스 매너라고는 눈꼽만큼도 찾아볼 수 없는 무례한 내용의 답변을 보내 협박했다.
We don’t mean to be a dick about it, but it’s a registered trademark in most countries around the world and if you actually release an open source project called kik, our trademark lawyers are going to be banging on your door and taking down your accounts and stuff like that — and we’d have no choice but to do all that because you have to enforce trademarks or you lose them.
저희도 재수없게 굴기는 싫지만, 킥은 세계 대부분의 국가에 등록된 저희 상표이니, 만일 같은 이름의 오픈소스 프로젝트를 공개하신다면 저희 상표권 변호사들이 당신 집에 찾아가서 현관문을 두드리고 당신 계정을 삭제하려 할 겁니다.
출처

당연히 협상은 결렬되었고, 이에 Kik은 npm에 중재를 요청했다. 그러자 npm은 Kik의 편을 들어 'kik'이라는 패키지명에 대한 소유권을 Kik에게 넘겨주었다. 분노한 코출루는 npm의 행동에 항의하고자 2016년 3월 22일, 자신이 그동안 npm에 공개했던 273개의 패키지를 모두 삭제했다.

코출루가 삭제한 패키지 중에 left-pad가 있었다. 이 패키지는 코드가 11줄에 불과한 작은 라이브러리에 불과했고, 문자열 왼쪽에 공백을 추가해주는 기능이다.
#!syntax javascript
module.exports = leftpad;
function leftpad (str, len, ch) {
    str = String(str);
    var i = -1;
    if (!ch && ch !== 0) ch = '';
    len = len - str.length;
    while (++i < len) {
        str = ch + str;
    }
    return str;
}

그러나 다른 개발자가 제작한 line-numbers라는 패키지가 left-pad를 불러와 쓰고 있었고, 다시 이 line-numbers는 '바벨(babel)'이라는 패키지가 불러와 쓰고 있었다. npm(프로그램)은 이렇게 의존 관계에 있는 패키지를 자동으로 불러와 설치하기 때문에, 바벨을 쓰는 개발자들은 자신도 모르는 사이에 left-pad를 함께 설치하고 있었다. 당연히 left-pad가 삭제되자 바벨 또한 설치가 불가능해졌다.

문제는 바벨은 JavaScript 개발에 반쯤 필수적으로 쓰이는 인기 패키지였다는 것이다. 페이스북, 링크드인, 스포티파이 등 이름난 IT 기업부터 전세계의 수많은 1인 개발자까지 많은 사람들이 바벨을 사용하고 있었다. left-pad가 삭제되자 이들의 업무가 모두 마비되었고, 사람들이 원인을 분석하면서 left-pad 사건이 널리 알려지게 되었다.

npm은 예상치 못한 상황에 당황했고, 우선 left-pad를 임시로 복구하여 설치할 수 있게 만들어서 문제를 해결했다. 이후 npm은 사과문을 공개하였으며, 앞으로 똑같은 문제가 발생하지 않도록 공개된 지 24시간이 지난 프로젝트는 소유자가 임의로 삭제할 수 없도록 규정을 변경했다. 한편 바벨의 개발진은 line-numbers를 호출하는 코드를 지우고 필요한 기능을 직접 추가하는 방식으로 문제를 해결했다.

Kik 대표는 medium에 이메일 내역을 공개하며 코출루에게 올린 부적절한 표현의 메일에 대해 사과글을 올렸으며, 코출루는 kik을 hek로 이름을 변경했다고 한다. 무례한 메일을 보낸 직원에 대해서는 알려진 바가 없다.

이 사건의 의의는 npm의 미흡한 운영 방식이 드러난 것 외에도, npm을 비롯한 JavaScript 생태계의 취약점이 드러났다는 것이다. JavaScript는 다른 프로그래밍 언어에 비해 내장된 API가 부실하기 때문에, 다른 언어라면 표준 라이브러리에서 제공할 법한 기능도 직접 코드를 짜거나 다른 사람이 만든 라이브러리를 가져와 사용해야 한다. 여기에 JavaScript를 많은 사람이 사용한다는 점과, npm에 패키지를 등록하는 것이 쉽다는 점이 맞물려서 비교적 단순한 기능도 직접 구현하기보다는 npm에 공개된 패키지를 설치하는 것이 관습화되었다. 이 때문에 패키지 A가 B를 불러오고, B가 C를 불러오고...하는 식으로 의존 관계가 여러 겹 쌓이다 보니 개발자들은 자신이 어떤 패키지를 설치했는지도 파악하기 어렵게 되었다. 게다가 패키지 하나에 문제가 생기면 여기에 의존하는 수많은 패키지가 영향을 받으니 보안 면에서 취약할 수밖에 없다. 이 문제는 JavaScript가 눈부신 발전을 거듭한 2020년대에도 여전히 JavaScript의 아킬레스건으로 지적받고 있다.

2.4.2. funding 사건

GitHub
Reddit
standard 라이브러리[4]의 개발자가 npm install의 결과창에 큼지막한 광고를 출력하는 funding이라는 프로젝트를 만든 사건. 당연히 엄청난 양의 비난을 받았고, 현재는 '실험이 종료'되었다.

2.4.3. everything 사건

https://everything.npm.lol/
Hacker News
https://t.co/00s0m0gIex
https://uncenter.dev/posts/npm-install-everything/

2024년 1월 3일 한 개발자가 npm의 결함을 이용해 자기 자신을 포함한 npm의 모든 패키지를 의존하는 everything이라는 패키지를 배포한 사건. 즉, npm install everything을 입력하면 컴퓨터에 npm의 모든 패키지가 설치되는 장관을 볼 수 있다.용량이 20TB였는데 200명이 넘게 다운받았다. 뭐하는 사람들이지

이 것 자체는 별 일 아니지만 한 가지 문제가 있었는데 위에서 언급한 left-pad 사건으로 인해 npm의 정책이 변경되면서 다른 패키지가 의존 중인 패키지는 삭제할 수 없게 되었었다는 것이다. 결국 everything 패키지 자기 자신을 포함한 모든 npm 패키지의 삭제가 잠겨버렸다.

이로 인해 모든 개발자가 자신의 패키지를 npm에서 삭제할 수 없는 사태가 벌어졌고, 결국 개발자가 패키지를 삭제하기 위해 npm과 GitHub에 문의한 뒤에야 GitHub 레포지토리를 삭제할 수 있었다.


[1] npm by the numbers(로그인 후 조회 가능) [2] 2019년에 deprecated로 선언되었다. 자세한 사항은 https://github.com/request/request/issues/3142 참고. [3] https://github.blog/2020-03-16-npm-is-joining-github/ [4] 이름과 달리 절대 표준이 아니다.