본문 바로가기
DEV

[Npm Deep Dive] 1장 - NPM? 유의적 버전?

by krokerdile 2025. 6. 25.
728x90

들어가며

상반기에 수십 곳의 기업에 지원을 하고, 면접을 보면서 그리고 개인적으로 토이 프로젝트를 하면서 채워온 경험 만큼이나 빈 구멍이 많다고 느꼈다. 그러던 와중에 뭘로 채울까 고민을 했었는데 마침 npm deep dive라는 신간의 스터디가 진행 된다고 해서 참여를 하게 되었다.

참여를 결정 했던 계기는 npm을 일상적으로 개발하면서 쓰는게 구체적인 원리나 맥락, 그와 관련된 개념들에 대해서 너무 수박 겉핡기 처럼 아는 것 같아서 그런 점을 해결 해보고 싶었던 것 같다.

도입부

책 초반부에서 “This package is now pure ESM. Please read this” , “legacy-peer-deps=true” 등 패키지로 인해서 생기는 문제나 해결하는 방식에 대해서 예시를 들면서 npm을 통한 패키지를 사용할 때 생기는 여러 상황에 대해서 제시를 해준다.

책에 적혀 있는 것 처럼 자바스크립트 개발자라면 하루에 수십 번도 넘게 터미널에서 npm 관련 명령어를 실행하게 된다. npm install 로 설치를 하는 건 일상이고 npm run dev 나 npm run build 처럼 프로젝트를 실행하기 위해 사용하는 명령어 들도 많이 있다.

우리가 npm install을 실행 하게 되면 흔히 알고 있는 node_modules 가 package.json 과 같은 폴더에 생성되어지게 된다. 사실 나도 개발을 하면서 설치하고 삭제 하기만 했지 그에 대해서 깊게 본적은 없던 것 같다.

책에서는 위의 이미지를 예시로 들면서 우리가 몇 줄 안되는 package.json 내용을 바탕으로 설치를 하지만 실제로 다운 되는 양은 수많은 코드 들로 이뤄진 패키지들이 설치되어 지게 되어진다고 알려준다.

실제로 프로젝트를 다수 하다 보면 컴퓨터의 용량이 부족해질 때 항상 크게 차지하는게 npm install 을 통해서 설치한 패키지 들이 차지하고 있는 걸 자주 볼 수 있었던 것 같다.

해당 책에서는 이러한 패키지를 관리하는 node_modules, npm의 개념을 살펴보고, Node.js의 역사 까지 살펴 본다고 한다. 그리고 실제로 npm에 패키지를 배포하기 위해 알아야 할 유의적 버전 관리, 트랜스파일, 폴리필. 번들링의 개념도 알려준다고 하니 기대가 된다.

개발 환경 세팅하기

책에서 요구하는 개발 환경은 아래와 같으니 참고하면 좋을 것 같다.

Nodejs: 20.18.0
npm: 10.9.0
yarn:
	Classic: 1.22.19
	Berry: 4.2.2
pnpm: 9.12.3
TypeScript: 5.5.4

1장. npm과 유의적 버전

npm을 사용하면서 유의적 버전이라는 개념을 사실 모르고 사용했었는데, 이에 대해서 먼저 알아야 된다고 한다.

유의적 버전이란 **“semantic version”**을 번역한 것이고 semantic은 “의미의”이라는 뜻으로 유의적 버전은 “의미가 있는 버전”이라는 뜻이라고 한다.

패키지 관리에서 가장 중요한 역할을 하는 것이 바로 버전이고 그에 대한 규약을 이 유의적 버전에서 관리를 해준다고 한다.

1.1 npm의 정의와 역사

자바스크립트 개발을 한다면 가장 많이 쓰는 도구는 npm일 것이다. 나중에 yarn이나 pnpm으로 넘어가더라도 우리가 “Hello World!”를 치기위해서 처음 사용하는 도구는 npm으로 시작할 것 같다.

이 npm을 통해서 전 세계에서 업로드 된 패키지를 손쉽게 설치하고 업데이트 하며, 프로젝트 간의 의존성을 효율적으로 관리할 수 있다.

1.1.1 npm의 역사와 배경

책에서 말하듯이 나도 npm의 약자를 **“Node Package Manager”**로 알고 있었는데, 실제로는 그게 아니라고 한다.

npm의 전신이 bash 유틸리티인 pm이고, 이 pm은 **“pkgmakenist”**의 약자라고 한다. npm은 이 pm을 발전 시킨 프로젝트이기 때문에 굳이 약자로 따지면 “Node pm” 혹은 **“Node pkgmakeinst”**가 옳다고 한다.

npm을 처음 만든 사람은 **개발자 아이작 Z. 슐루터(Isaac Z. Schlueter)**라고 한다.

이 개발자는 Node.js가 초기 등장한 2009년 부터 열렬히 사용한 개발자며 커뮤니티에도 참여한 개발자 분이라고 한다. 야후에서 근무하면서 개발 과정의 일환으로 여러 코드를 패키지로 묶는 것에 익숙했고 이것의 연장선으로 사람들에게 Node.js 코드를 공유하기 위해 하나의 번들로 묶어서 배포한 것이 npm의 전신이라고 한다. (2010년에 npm@1.0.0 등장)

초기에는 2013년 까지도 임시로 만들어진 인프라에서 작동되어서 트래픽을 감당 못해 다운되는 경우가 많았다고 한다. 불과 10년 정도 전인데 지금 활발하게 사용하고 있는 npm도 초기에는 이런 배경이 있었다는게 신기한 것 같다.

이런 환경을 해결하기 위해서 동시에 장기적으로 지속가능한 생태계 구축을 위해 npm이라는 회사를 설립하고 오픈소스로 전환하게 되었다고 한다. 이를 통해서 우리가 자바스크립트 패키지가 업로드 되는 npm 레지스트리를 무료로 사용할 수 있게 하려고 했다고 한다.

회사 설립 초기까지만 해도 Node.js 생태계에서 동작되는 코드만 업로드 되어 있었다고 한다.

〈script src="<https://ajax.googleapis.eom/ajax/libs/jquery/3.5.l/jquery.min.js>"> 와 같이 사용할 수 있도록 CDN에 업로드 하고 이를 필요로 하느 개발자들이 사용할 수 있도록 하는 것이 일반적이었다고 한다.

2019년에 처음 웹개발을 접하고 배웠을 때를 돌아보면 간단한 블로그 페이지를 만들기 위해서 저런 식으로 나도 Head 태그 안에 스크립트 코드를 넣었던 것 같다.

이런 방식은 차후에 페이스북이 리액트를 npm에 올리고, 다른 프론트엔드에서 동작하는 프레임워크나 라이브러리도 npm에 배포하는 것을 선호하기 시작했다. CDN에 올리게 되었을 때 생기는 다운로드 비용이나, 보안, 버전 관리 등의 이슈가 있었고, 그에 반에 npm은 CDN 형태에서 발생하는 문제에서 자유롭고 패키지의 버전을 관리할 수 있어서 개발자들이 버전을 관리하는데 도움을 줄 수 있었다고 한다.

현재는 제삼자 스크립트 방식으로 사용하는 패키지는 거의 없을 정도로 npm이 대세가 되었다고 한다. 2020년에 깃허브가 npm을 인수하였고 오늘날에도 2024년을 기준으로 300만여 개의 패키지를 보유하고 있다고 한다.

1.1.2 npm의 주요 기능

npm은 다양한 기능을 제공하여 생산성을 높이고 프로젝트 관리 효율성을 극대화 해준다. npm이 어떤 기능을 제공하는지 간단하게 보자

  1. 패키지 설치 및 관리오래된 패키지 업데이트, 보안이 취약한 패키지 체크와 의존성 수정 까지 가능
  2. package.json의 dependencies와 devDependencies에 선언된 패키지를node_modules에 설치해 Node.js 기반 프로젝트에서 사용할 수 있도록 도와준다.
  3. 패키지 배포와 공유유료 서비스를 통해 업로드 하면 사설 패키지로 업로드도 가능하다.
  4. 자바스크립트로 만든 패키지를 업로드할 수 있는 오픈소스 생태계 “npm 레지스트리” 에서 업로드 하고 설치할 수 있도록 지원해준다.
  5. 스크립트 실행자주 사용하는 명령어를 간단한 CLI로 실행 할 수 있고, PATH도 등록해줘 일반적으로 실행 하지 못하는 eslint 같은 .bin 스크립트도 실행할 수 있게 해준다.
  6. package.json 의 scripts 필드를 사용하면 원하는 스크립트를 실행하게 해준다.

1.1.3 npm과 관련된 유용한 사이트

  1. 번들포피아 → npm에 업로드된 패키지의 크기와 관련된 정보 얻을 수 있음. 실제 구성된 요소까지 확인할 수 있음
  2. 내부 요소 까지 확인하면서 패키지를 사용한 기억이 많이 없는데 이걸 통해서 평소에 사용하는 패키지들에 대해서 다시 봐두면 좋을 것 같다.
  3. npm 트렌드각 패키지의 현재 상태 + 다운로드 횟수 를 비교할 수도 있고, 비슷한 역할을 하는 패키지를 찾아보는 용도로도 사용할 수 있다.
  4. 2024년에 300만개 이상의 패키지가 등록되어져 있는 만큼, 다양한 패키지가 있기 때문에 패키지 들을 비교할 수 있도록 해주는 사이트이다. 여기는 평소에도 여러 패키지를 놓고 고민할 때 한번씩 사용해봤던 경험이 있다.
  5. https://www.unpkg.com/browse/react/ 와 같이 주소를 입력하면 해당 패키지의 버전, 파일을 볼 수 있다고 한다.
  6. 실제 npm에 업로드 되어 있는 파일을 node_modules 를 보는 것 처럼 볼 수 있는 사이트라고 한다.

1.2 유의적 버전이란?

우리가 개발을 하면서 17.0.2라던가 1.0.0이라던가 개발을 하면서 다양한 버전을 보고 설치를 하게 된다. 이러한 버전이 위에서 언급된 유의적 버전이라는 규칙에 의해서 관리 된다고 한다.

유의적 버전의 등장 배경과 정의

오픈소스 생태계로 이뤄져 있고, 동시에 계속해서 npm에는 수천 개의 새로운 패키지가 릴리스 된다고 한다. 그래서 매번 패키지의 변경사항을 추적해서 찾고 예측하기는 어렵다고 한다.

이러한 특성이 node_modules 내부에 쉽게 예측할 수 없는 필연적인 혼란을 야기한다고 한다. 만약 매일 수십, 수백개의 패키지가 출시되는데 이걸 일관되게 관리할 수 없다면 개발자에게는 당연히 끔찍한 재앙이 될 것 같다.

버전이 바뀔 때 마다 패키지를 새로 설치한다면 호환성을 고려해야 되고, 새로운 기능을 배척하고 보수적으로 기존 패키지만 사용한다면 매일 진화되는 오픈소스의 장점을 포기해야 되기 때문에 이러한 문제를 해결하기 위해서 만들어진 것이 유의적 버전이라고 한다.

유의적 버전은 소프트웨어의 버전을 어떻게 정의하고, 어떻게 올리고 관리하는지에 대한 규약을 나타낸다. 개발자는 해당 소프트웨어의 예상되는 변경점을 사용자에게 손쉽게 알려줄 수 있으며, 사용자는 개발자가 유의적 버전 체계를 지켰다는 가정하에 해당 소프트웨어에 유연하게 의존할 수 있는 시스템을 만들 수 있게 된다.

유의적 버전의 구조는 요약하면 다음과 같다고 한다.

  • 버전은 주.부.수 → Major.Minor.Patch로 이뤄진다고 한다.
  • 기존 버전과 호환되지 않는 API 변경 사항이 있다면 주 버전이 올라간다.
  • 기존 버전과 호환되면서 새로운 기능이 추가되면 부 버전을 올린다.
  • 기존 버번과 호환되면서 버그를 수정한다면 수 버전을 올린다.

책에서는 리액트를 예시로 이를 설명 해준다.

  • 주 → 리액트 17.0.2에서 18.0.0으로 업그레이드 되면서 Promise, Symbol, Object.assign이 없는 환경에서 에러가 발생하도록 변경 되었다. ⇒ 이는 기존 환경과 호환이 안되는 것이므로 주 버전이 올라가야 한다.
  • 부 → 18.0.0에서 18.0.1로 업그레이드 되면서 useInsertionEffect 내부에 setState를 호출 하면 경고를 출력하는 기능이 추가되었다고 한다. ⇒ 새로운 기능 추가 이지만 버전업을 해도 사용하는데는 문제가 없도록 호환되기 때문에 부버전이 올라가야 한다.
  • 수 → 18.3.0에서 18.3.1로 업그레이드 되면서 누락된 act를 export 했다. 이는 실수로 생긴 버그를 수정한 것이므로 수 버전을 올려야 한다.

좀 더 자세한 내용은 https://semver.org/ 에서 볼 수 있다고 한다. (기본은 영문으로 되어 있는데, 한국어로 변경해서 읽을 수 있다는 점 참고)

1.2.2 유의적 버전의 구체적인 명세

우리가 기능을 만들 때 처럼 유의적 버전에도 11가지 명세가 있다고 한다.

  1. 유의적 버전을 쓰는 소프트웨어는 반드시 공개 API를 선언한다. 이 API는 코드 자체로 선언하거나 문서로 엄격히 명시해야 한다. 어떤 방식으로든 정확하고 이해하기 쉬워야 한다.
  2. 보통 버전 번호는 반드시 XYZ의 형태로 하고. X, Y, Z는 각각 자연수(음이 아닌 정수)이고, 절대로 0이 앞에 붙어서는 안 된다. X는 주(主) 버전 번호이고, Y는 부(部) 버전 번호이며, Z는 수(修) 버전 번호이다. 각각은 반드시 중가하는수여야 한다. 예: 1.9.0 —1.10.0 -1.11.0.
  3. 특정 버전으로 패키지를 배포하고 나면 해당 버전의 내용은 절대 변경하지 말아야 한다. 변경분이 있다면 반드시 새로운 버전으로 배포한다.
  4. 주 버전 0은 초기 개발을 위해서 쓴다. 아무 때나 마음대로 바꿀 수 있다. 이 공개 API는 안정판으로 보지 않는게 좋다.
    이건 흔히 우리가 베타로 출시 할 때 느낌이라고 생각하면 좋은 것 같다. 초기 개발을 중이라는 의미이면서 아직은 안정적인 패키지나 소프트웨어가 아니라는 의미니까
  5. 1.0.0 버전은 공개 API를 정의한다. 이후의 버전 번호는 이때 배포한 공개 API에서 어떻게 바뀌는지에 따라 올린다.
    1.0.0 이 된다는 건 이제는 안정적인 소프트웨어가 되었다는 의미
  6. 수 버전 Z(x.y.Z I x〉0)는 반드시 그 전 버전 API와 호환되는 버그 수정인 경우에만 올린다. 버그 수정은 잘못된 내부기능을 고치는 것으로 정의한다.
  7. 공개 API에 기존과 호환되는 새로운 기능을 추가할 때는 반드시 부 버전을 올린다. 공개 API의 일부를 deprecated 하는 경우에도 올린다. 내부 비공개 코드에 신규 기능, 개선사항이 있을 때도 가능하다. 부 버전이 올라가면 수 버전은 반드시 0에서 다시 시작한다.
  8. 공개 API에 기존과 호환되지 않는 변화가 있을 때는 반드시 주 버전을 올리고, 반드시 부 버전과 수 버전을 0으로 초기화 한다.
  9. 수 버전 바로 뒤에 붙임표(-)를 붙이고 마침표(.)로 구분된 식별자를 더해서 정식 배포를 앞둔(pre-release) 버전을 표기할 수 있다. 식별자는 반드시 아스키(ASCII) 문자, 숫자, 붙임표로만 구성하고(0-9A-Za-z-) 한 글자 이상으로 한다. 숫자 식별자의 경우 절대 앞에 0을 붙인 숫자로 표기하지 않는다. 정식 배포 전 버전은 관련한 보통 버전보다 우선순위가 낮다. 정식 배포 전 버전은 아직 불안정하며 연관된 일반 버전에 대해 호환성 요구사항이 충족되지 않을 수도 있다. 예: 1.0.0-alpha
  10. 빌드 메타데이터는 수 버전이나 정식 배포 전 식별자 뒤에 더하기(+) 기호를 붙인 뒤에 마침표로 구분된 식별자를 덧붙여서 표현할 수 있다. 식별자는 반드시 아스키 문자와 숫자와 붙임표로만 구성한다(0-9A-Za-z-). 식별자는 반드시 한 글자 이상으로 한다. 빌드 메타데이터는 버전 간의 우선순위를 판단하고자 할 때 반드시 무시해야 한다.
  11. 우선순위는 버전의 순서를 정렬할 때 서로를 어떻게 비교할지를 나타낸다. 우선순위는 반드시 주, 부. 수 버전, 그리고 정식 배포 전 버전의 식별자를 나누어 계산하도록 한다

이상 11가지 명세서 내용이다. 간단하게 적어둔 것도 있고, 구체적인 요소를 적어둔 곳도 있어서 세부사항은 책 혹은 위에 있는 https://semver.org/ 를 들어가는 걸 추천 한다.

읽어보면서 느낀 건 패키지의 버전을 관리하기 위해 이렇게 많은 조건들이 적용된다는 점, 그리고 편하게 사용했던 뒷 배경에는 이런 규칙들이 녹아져 있었기 때문에 평소에 문제 없이 사용할 수 있었다는 점들을 체감할 수 있었던 것 같다.

그리고 프로젝트를 진행하면서 한번 씩 버전 문제가 있었던 적이 있는데 이런 점들을 고려하면서 확인을 했으면 좀 더 빠르게 문제에 대해서 파악할 수 있었지 않았을까 싶다.

이런 버전에 대한 문법은 semver라는 패키지를 통해서 혹은 정규표현식을 사용해서 확인할 수 있는데 일반적으로는 전자를 선택한다고 한다.

이런 세세한 조건들을 체크해주지만 npm에서 올라오는 패키지 버전의 내용이 주, 부, 수 버전에 맞게 선언돼 있는지, 하위 호환은 지키고 있는지 등은 확인하지 못한다고 한다. 그래서 유의적 버전의 준수 여부는 개발자의 몫이라고도 볼 수 있다.

1.3 유의적 버전과 npm 생태계의 명과 암

위에서 언급 했듯이 유의적 버전은 명문화된 규칙이니 만큼 세부 내용을 지키는 것은 개발자의 판단과 관리에 의존하게 된다고 한다.

필수적인 관리 방식이지만 이 방식이 반드시 안전하거나 완벽한 해결책이 아니라는 점을 보여주는 사례들을 책에서는 소개 해준다.

1.3.1 left-pad 수천만 패키지에 의존하는 유틸 패키지가 사라지면?

현재는 사용하지 않지만 과거에 문자열에 특정 숫자 만큼 왼쪽에 공백이나 문자를 채워넣는 역할을 해주던 “left-pad”라는 패키지가 있었다고 한다.

현재는 String.prototype.padStart() 가 있지만 당시에만 해당 요소가 없었기 때문에 left-pad가 폭넓게 사용되던 패키지라고 한다.

이 left-pad를 line-numbers 라는 패키지가 사용하고 있었고, 당시에 커뮤니티에서 폭넓게 사용되던 바벨에서 사용되어 지고 있었다고 한다.

그런데 이 left-pad 패키지가 값자기 삭제 되었다고 한다. 이 패키지를 관리하던 개발자가 kik 이라는 패키지를 업로드 했다가 타 회사의 이름과 동일하다는 이유로 삭제 요청을 받았고 해당 메일이 상당히 무례하게 작성되어 모든 패키지를 삭제하게 되며 문제가 생겼다고 한다.

평소에 개발 관련된 글을 자주 읽다 보니 kik 이라는 패키지로 인해서 문제가 생겼다 라는 내용은 읽은 적이 있었는데 그 사건이 구체적으로 이런 사건이었다는 게 진짜 충격 이었던 것 같다.

무례한 정도가 책에서 얘기하는 메일 내용에 따르면 “저희도 재수없게 굴기는 싫지만 킥은 전 세계 대부분의 국가에 등록된 저희 상표이므로 만일 같은 이름의 오픈소스 프로젝트를 공개하려고 하신다면 저희 상표권 변호사들이 당신 집에 찾아가서 현관문을 쾅쾅 두드리고 당신 계정을 삭제하려 할 겁니다." 라고 한다.

left-pad 사건을 처음 들었을 때는 꽤 충격적이었지만, 실제 이메일 내용을 보고 나니 그 개발자의 결정도 이해가 되었다. 단순히 '남 탓'이 아닌 오픈소스 생태계 내에서 발생하는 신뢰와 권한의 문제라는 점에서 시사하는 바가 컸다

여튼 이로인해서 바벨을 사용하던 대부분의 자바스크립트 프로젝트에서 문제가 생겼고, 약 2시간 반 동안 분 당 수백 개의 에러가 발생했다고 한다.

이를 해결하기 위해서 npm 팀에서 left-pad를 복구하고 다른 패키지가 의존하면 삭제가 안되도록 동시에 버려진 유명 패키지가 있으면 부정 사용되는 것을 막기 위해 security-holder라는 제도를 추가 했다고 한다.

이 패키지가 차후에 다른 문제를 발생 시켰다는데.. 마저 넘어가보겠다.

1.3.2 everthing: 의존성으로 있으면 패키지 삭제가 안된다고? 그렇다면 모든 자바스크립트 패키지를 의존성으로 가지면?

의존성을 가지면 삭제가 안된다고? 라는 상황을 everything이라는 패키지가 악용 했다고 한다.

npm에 있는 모든 패키지를 순서대로 의존성에 넣어두면 어떻게 될까라는 호기심에서 시작했다고 한다. 모든 패키지를 의존성으로 갖기위해 청크 단위로 쪼개고 쪼개 npm에 올라온 모든 패키지를 의존성으로 두는데 성공 했다고 한다.

그리고 이 패키지를 npm에 업로드 하게 된다.

이 장난 같은 작업으로 인해 대부분의 패키지가 삭제가 안되는 문제가 생겼고, 모든 버전의 패키지에 영향을 주게 되었다고 한다. 이걸 해결하기 위해 결국 깃허브 저장소와 패키지를 삭제하는 방식으로 마무리 되었다고 한다.

문제를 해결하기 위해 추가한 규칙으로 전체의 시스템이 영향을 받다니, 레거시 코드를 수정할 때 생기는 문제 처럼 이런 시스템 적인 요소에서도 단순하지만 고려해야 될 점이 정말 많은 경우를 볼 수 있었던 것 같다.

1.3.3 is-promise: 잘못된 부 버전 업데이트가 만들어낸 사태

is-promise는 인수를 하나 받아 Promise 객체 인지 여부를 boolean으로 반환 해준다고 한다.

module.exports = isPromise
module.exports.default = isPromise

function isPromise(obj) {
	return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then ==
	'function'
}

생각보다 이 간단한 코드에서 패키지 관리자는 CommonJS와 ESModule을 모두 지원하기 위해서 커밋을 올렸고 부 버전을 2.1.0에서 2.2.0으로 올렸다고 한다.

그냥 읽어 봤을 때도 패키지 사용에는 문제가 없어 보인다고 생각했는데, 수정한 사항에 문제가 있었다.

위와 같이 관리자가 수정했을 때 “./index.js”같은 상대 경로로 적지 않음으로써 문제가 생겼다고 한다. 가장 큰 피해를 본 프로젝트가 바로 리액트를 처음 시작할 때 사용했던 create-react-app이라고 한다.

create-react-app → inquirer → run-async 순으로 참조해서 사용하고 있었기 때문에 새로운 버전이 나오더라도 create-react-app도 버전업을 해야 한다.

이를 해결하기 위해 1) run-async가 is-promise를 사용하지 않는다. 2) run-async가 is-promise가 수정된 버전을 올리면 그걸 사용하는 등의 방법이 있었다고 한다.

실제로는 후자로 적용이 되었다고 한다.

이 외에도 faker.js/color.js의 개발자가 5.x.x에서 6.x.x로 버전업을 하고 제대로 된 코드가 작동되지 않도록 한 사건, 악성 코드를 삽입한 경우 등이 있었다고 한다. (책에서 마저 읽어보시는 걸 추천 드립니다)

유의적 버전이 많은 도움을 주지만 동시에 많은 위험을 의도하고 발생시킬 수 있다는 점을 이러한 사례들을 통해서 알 수 있었던 것 같다.

1.3.6 유의적 버전 npm을 사용할 때 주의할 점

  1. 유의적 버전은 규약일 뿐이다.
  2. 실수 혹은 고의로 어길 수 있고, 그렇기 때문에 항상 사용할 때 주의를 기울여야 한다.
  3. 무조건 설치하는 것이 능사는 아니다.필요하다면 직접 만들어보는 것도 좋은 방법이다!
  4. 위에서 나온 사건들 처럼 간단한 코드 지만 설치해서 외부에 의존하게 되면 위험성이 추가로 생긴다는 것, 정말로 대체 불가능한지, 사용할 수 있을 만큼 검증 되었는지, 타당한 dependecies를 가졌는 지를 기준으로 판단하자
  5. 락 파일 변경에 주의를 기울이기
  6. diff를 확인하기가 어렵기 때문에 PR 과정에서 lock 파일을 확인하기가 쉽지 않다. 그로 인해서 변경사항이 있어도 잘 확인하지 않게 된다. 앞의 예제 처럼 락 파일의 변경은 설치 되는 실제 버전의 변경이므로 확인을 하는 것이 좋다. 확인하기 어려운 npm ci를 사용해 락 파일이 변경 되지 않도록 해야 한다.
  7. 보안 취약점에 귀 기울이기
    1. snyk
    2. dependabot → github에서 제공해주는 서비스
    3. 이건 실제로 프로젝트를 올려두면 github에서 메일, 코멘트로 달아주는 걸 확인할 수 있다.
  8. 자바스크립트로 개발하는 과정에서 결국 상당 부분을 오픈소스에 의존하게 된다. 그 과정에서 생기는 취약점을 알려주는 다양한 서비스를 활용해보자

마무리하며

npm은 우리가 하루에도 수십 번씩 사용하는 도구이지만, 그 내부에서 작동하는 규칙과 구조는 놀랍도록 복잡하다는 것을 느꼈다. 
이번 스터디를 통해 단순히 명령어만 사용하는 것이 아니라, 왜 이런 방식으로 동작하는지, 어떤 신뢰 체계 위에 오픈소스 생태계가 유지되고 있는지를 배울 수 있었던 것 같다. 

728x90
반응형