관리자가 사용 중단을 권고한 패키지도 매달 수천만 번 다운로드될 수 있다. 반대로 유지보수가 계속되는데도 새 프로젝트가 같은 일을 하는 데 더는 필수적이지 않은 패키지도 있다. npm 다운로드 수만 보면 두 변화 모두 알아채기 어렵다.

어떤 라이브러리와 유틸리티가 역할을 잃고 있으며, 무엇을 남겨야 할까? ‘구식 패키지 순위’로는 답하기 어렵다. 중요한 질문은 이 의존성을 설치했던 이유가 지금도 존재하는가, 존재한다면 누구를 위해 어떤 책임을 맡고 있는가이다.

내 판단으로는 플랫폼의 빈자리를 채우면서 그 이상의 복잡성을 계속 감당하지 않는 도구가 필요성을 잃기 쉽다. 작은 패키지를 모두 삭제하거나 기본 API가 언제나 더 낫다는 뜻은 아니다. 2026년 10월 8일에 확인한 공식 문서, 관리자의 설명, npm 데이터를 바탕으로 다섯 종류의 대체 압력을 살펴보고, 확인된 사실과 내 추론을 구분하려 한다.

다운로드 수는 트래픽이지, 선택 자체가 아니다

Request의 README에는 2020년 2월 11일부터 deprecated 상태라고 명시되어 있다. inflight의 메타데이터는 지원 중단과 메모리 누수를 경고한다. Moment는 다르다. 기능 확장을 목표로 삼지 않으면서 유지보수를 계속한다. 셋을 모두 ‘죽은 패키지’로 묶으면 중요한 차이를 놓친다. Request 설명, inflight 정보, Moment의 현행 정책

npm 공식 Downloads API에서 2026년 9월 전체를 공통 기간으로 조회했다. 이 세 사례는 지원 중단이나 유지보수 모드가 다운로드 소멸을 뜻하는지 확인하려고 의도적으로 골랐다. 무작위 표본도, 생태계 점유율 조사도 아니다.

사용 중단 권고와 유지보수 모드에도 다운로드는 계속된다

npm Downloads API · 2026-09-01–2026-09-30

세 패키지 모두 2026년 9월에 많은 다운로드를 기록했다. 막대는 새 프로젝트의 채택 의사를 나타내지 않는다.

백만 다운로드 (근삿값) / 2026년 9월
  • request (deprecated)59.699
  • moment (유지보수 모드)149.03
  • inflight (deprecated)392.617
npm 다운로드 데이터 표 보기
사용 중단 권고와 유지보수 모드에도 다운로드는 계속된다 · 백만 다운로드 (근삿값) / 2026년 9월
패키지와 유지보수 상태백만 다운로드 (근삿값) / 2026년 9월
request (deprecated)59.699
moment (유지보수 모드)149.03
inflight (deprecated)392.617

npm 공식 API, 2026년 9월 1~30일, UTC 기준이며 양 끝 날짜를 포함한다. 수치는 백만 회 단위로 소수점 셋째 자리까지 반올림했으며 정확한 횟수는 출처에 있다. 한 달의 스냅샷으로 증가나 감소를 증명하지 않는다. 횟수는 사람이나 프로젝트 수가 아니며, 신규 채택·간접 의존성·자동 설치를 구분하거나 각각의 비중을 계산할 수 없다.

출처

API는 기간 내 다운로드 총수를 반환할 뿐, 개발자가 의도적으로 선택했는지 알려 주지 않는다. 가령 오래된 도구가 Request에 간접 의존하고 캐시 없는 환경에서 다시 빌드된다면, 누구도 설계를 재평가하지 않아도 재다운로드가 발생할 수 있다. 이는 가능한 메커니즘을 보여 주는 가정이며, 이번 총수의 몇 퍼센트가 그 결과인지는 알 수 없다. npm API와 날짜 정의

따라서 네 질문을 나눠야 한다. 기능이 아직 희소한가? 관리자는 무엇을 약속하는가? 새 프로젝트가 선택하는가? 기존 시스템이 떠날 수 있는가? 사용 중단 공지는 두 번째 일부를, API 비교는 첫 번째를 설명한다. 월간 다운로드 총수로 나머지 두 질문에 답할 수는 없다.

이것이 글의 범위이기도 하다. 일부 용도에서 필요성이 줄어든다고 논할 근거는 있지만, 다섯 범주 모두의 신규 채택률이 감소한다고 단정할 데이터는 없다.

1. 실행 환경에 표준 기능을 보충하는 호환 계층

node-fetch의 원래 역할은 분명하다. Fetch API를 Node.js로 가져오는 것이었다. 실행 환경 자체에 안정적인 fetch가 있으면 기본 HTTP 요청만을 위해 별도 패키지를 설치할 이유는 약해진다. Node.js 문서는 v21부터 Fetch가 실험적 기능이 아니라고 기록한다. 여기서는 Node 24 문서를 기능의 기준으로 삼는다. Node.js Fetch

확인되는 것은 플랫폼의 기능 흡수이지 node-fetch 사용량의 감소가 아니다. import를 지우면 마이그레이션이 끝난다는 뜻도 아니다. node-fetch의 응답 본문은 Node stream이고 기본 Fetch는 Web Stream을 쓴다. agent 옵션과 Node 기본 Fetch의 dispatcher도 다른 인터페이스다. 스트림 소비 방식, 연결 설정, 취소 동작을 실제 사용 방식과 비교해야 한다. node-fetch 문서

HTTP 클라이언트의 가치는 전송보다 상위에 있을 수 있다. 오류 분류, 재시도 정책, 인증 정보, 관측 기록을 통일하려면 공통 추상화가 여전히 합리적이다. 기본 fetch는 모든 HTTP 오류 상태를 자동으로 Promise 거부로 바꾸지 않는다. 응답 처리 방식은 애플리케이션이 정해야 한다. 쓰기 요청 재시도도 반복문만 추가할 것이 아니라 중복 실행을 고려해야 한다. Fetch 표준

또한 Node의 Fetch 구현은 Undici에 기반한다. 명시적으로 설치하는 패키지가 줄어도 그 아래의 유지보수 작업은 사라지지 않을 수 있다. 런타임이 맡았을 뿐일 수 있다. 약해지는 것은 별도로 설치할 이유이며, 그 안에 축적된 엔지니어링 지식의 가치는 아닐 수 있다.

2. 일상적인 문법을 편리하게 감싸는 도구 모음

배열 검색, 순회, 중복 제거는 범용 유틸리티를 도입하는 중요한 이유였다. 이제 Array.prototype.find, map, Set은 언어의 일부다. 단순한 문자열 배열의 중복을 제거하는 것이 전부라면, 추가 의존성이 정당화해야 할 몫은 줄어든다. ECMAScript 배열과 컬렉션

그러나 비슷하게 보이는 코드와 의미가 같은 코드는 다르다. 다음은 이를 드러내기 위해 만든 반례다.

const settings = { retries: null };
 
// _.get은 결과가 undefined일 때만 기본값을 사용한다.
_.get(settings, 'retries', 3); // null
 
// ??는 null과 undefined 모두에 기본값을 적용한다.
settings?.retries ?? 3; // 3

시스템에서 null이 ‘명시적으로 비활성화’를 뜻한다면 기계적 치환은 업무 규칙을 바꾼다. 첫 번째 계약은 Lodash 문서에 정의되어 있다. 유틸리티 검토는 글자 수 비교가 아니라 호출부가 의존하는 동작을 확인하는 데서 시작해야 한다. Lodash get

structuredClone도 여러 자료형과 순환 참조를 지원하지만 임의의 JavaScript 객체를 그대로 복제하지는 않는다. 함수, DOM 노드, 프로토타입, 속성 서술자에는 한계가 있다. 실제 값을 살피지 않고 모든 cloneDeep을 바꾸는 것은 충분한 이전 전략이 아니다. 구조화 복제 알고리즘

디바운스 역시 ‘나중에 실행’만은 아니다. Lodash의 debounce에는 leading, trailing, maxWait, cancel, flush가 있다. 그 상호작용에 의존한다면 열 줄짜리 자체 구현이 더 저렴하다고 할 수 없다. Lodash debounce

압력을 받는 것은 도구 모음 중 기본 기능과 겹치는 사용 영역이다. Lodash 전체가 무가치해졌다는 증거는 아니다. 하나의 라이브러리 안에서도 쉽게 바꿀 편의 기능과 유지할 만한 동작 계약이 공존한다. 대체 단위는 용도여야 하며, 처음부터 패키지 전체 삭제를 목표로 삼을 필요는 없다.

3. Node.js의 기본 파일 작업을 보충하는 도구

중첩 디렉터리 생성, 디렉터리 복사, 패턴 기반 파일 검색에는 별도 도구를 흔히 사용했다. Node 24에는 재귀적 mkdir, fs.cp, fs.glob이 있다. cp는 v22.3부터 실험 단계가 아니며, glob은 v24.0에서 안정화됐다. 런타임을 고정하는 새 스크립트라면 먼저 살펴볼 만하다. Node.js 파일 시스템 문서

다음은 가상의 빌드 스크립트 일부다. Node 24가 직접 수행할 수 있는 작업을 보여 줄 뿐, 모든 외부 도구와 완전히 같다고 주장하지 않는다.

import { mkdir, cp, glob } from 'node:fs/promises';
 
await mkdir('dist/assets', { recursive: true });
await cp('assets', 'dist/assets', { recursive: true });
 
for await (const file of glob('content/**/*.mdx')) {
  console.log(file);
}

애플리케이션은 Node 버전을 지정할 수 있지만 공개 라이브러리는 소비자의 최소 지원 버전을 고려해야 한다. 결정 조건이 다르다. 버전이 맞아도 심볼릭 링크, 덮어쓰기, 제외 규칙, 숨김 파일, 플랫폼별 경로를 비교해야 한다. API 이름이 같다고 외부 glob 도구의 모든 옵션이 일치하지는 않는다.

퇴장에는 세 관문이 있다. 플랫폼이 기능을 제공하고, 프로젝트가 호환 환경을 요구할 수 있으며, 이전 비용이 유지 비용보다 낮아져야 한다. 첫 관문을 넘었다고 나머지도 넘은 것은 아니다. ‘구식 의존성’이 남는 이유는 지원 범위와 위험의 배분에 있을 때가 많다.

4. 이전 세대 아키텍처의 계약을 보존하는 래퍼

Request와 Moment는 함께 거론되지만 유지보수 선택은 다르다. Request는 deprecated 상태이고, Moment는 가변 객체 API를 유지하며 보수를 계속한다. 새로운 대안이 있다는 말만으로는 기존 시스템을 옮기기 어려운 이유를 설명하지 못한다.

Moment는 2026년 8월 17일 정책을 수정했다. 사용자 대상 새 기능은 여전히 받지 않지만 기술적 유지보수는 가능하고, 호환성을 깨는 보수 릴리스로서의 3.0도 일괄 배제하지 않는다. 예전 공지의 ‘v3는 없다’를 현행 약속처럼 인용해서는 안 된다. Moment 정책 변경

이전 비용은 계약 속에 숨어 있다. 날짜 연산이 입력 객체를 수정한다는 데 의존하는 흐름을 가정해 보자. 새 객체를 반환하는 도구로 바꾸면 화면에는 그럴듯한 날짜가 나와도 다른 흐름은 옛값을 읽을 수 있다. 메서드 이름을 치환하기 전에 가변성, 파싱, 시간대, 출력 형식을 조사해야 한다.

기본 Intl.DateTimeFormat은 많은 표시 작업을 맡을 수 있다. 하지만 한 시점을 형식화하는 것은 모든 사람의 입력을 해석하거나 ‘다음 달 같은 날’, 일광 절약 시간 전환을 가로지르는 예약 규칙을 정의하는 것과 다르다. ECMA-402 날짜 형식화

Request 사용자도 쿠키, 프록시, 스트리밍 설정에 의존할 수 있다. 실제 애플리케이션의 계약부터 확인하고 새 클라이언트나 얇은 호환 계층을 선택해야 한다. 기한과 담당자를 정해 의존성을 잠시 유지하는 것도 엔지니어링 판단일 수 있다. ‘사용처를 더 늘리지 말자’와 ‘오늘 전부 지우자’는 다른 지시다.

5. 브라우저가 이제 직접 할 수 있는 일을 대신하는 도구

jQuery의 일부 입문 용도는 이제 querySelectorAll, classList, addEventListener로 구현할 수 있다. 요소가 뷰포트에 들어오는 감지는 Intersection Observer를 토대로 만들 수 있다. 이것이 패키지 가치의 전부라면 기본 기능이 필요성을 실제로 줄인다. DOM 표준, Intersection Observer 명세

그러나 jQuery는 2026년 1월 17일 4.0을 출시했다. 새 프로젝트에서 필요하지 않을 수 있다는 사실이 유지보수 중단을 뜻하지 않는다는 직접적인 반례다. 기존 플러그인, 통합, 팀의 숙련도는 여전히 유지 이유가 된다. jQuery 4.0 공지

기본 구성 요소가 완성된 제품은 아니다. 교차 상태를 관찰한다고 이미지 로딩 실패, 가상 목록, 초점 순서, 스크린 리더 상호작용까지 해결되지는 않는다. 프레임워크나 상위 컴포넌트가 그 책임을 맡으면 애플리케이션이 작은 유틸리티를 직접 설치하지 않더라도 그 일은 통합 계층에 남을 수 있다.

유형과 원래 역할이어받는 기능확인할 남은 요구
Fetch 호환 계층: Node에 Fetch 제공런타임의 Fetch스트림, 연결 설정, 최소 버전
범용 도구 모음: 데이터 조작 간소화배열 메서드, Set, 옵셔널 체이닝경계 의미, 깊은 데이터, 디바운스 계약
파일 도구: 생성·복사·검색Node mkdir, cp, glob경로, 링크, 제외, 지원 버전
기존 API 래퍼: HTTP·날짜 작업 통일새 클라이언트, Intl, 다른 날짜 도구가변성, 파싱, 시간대, 호환 약속
브라우저 보조: 선택·이벤트·가시성DOM과 Observer API플러그인, 통합, 완전한 상호작용

이 표는 대체의 경계이지 쇠퇴 순위가 아니다. 각 행에는 활발하게 유지되고 수요가 이어지는 제품이 들어갈 수 있다.

AI는 얇은 래퍼를 대체하면서 오래된 의존성을 연장할 수도 있다

여기부터는 메커니즘에 관한 내 추론이다. 몇 개의 안정적인 API를 감싸고, 요구 사항이 분명하며, 입력이 통제되고, 검증하기 쉬운 도구라면 AI가 국소적 구현 비용을 낮출수록 외부 의존성의 매력이 줄 수 있다. 팀은 패키지 전체 인터페이스와 업그레이드 주기를 받아들이는 대신 소량의 코드를 소유할 수 있다.

하지만 코드 생성이 책임을 없애지는 않는다. 패키지 작성자가 맡던 경계 조건, 테스트, 보안 수정, 버전 호환성이 자신의 저장소로 이동한다. 구현을 만들기 쉬워질수록 그것이 틀렸을 때 누가 알아볼 수 있는지 물어야 한다.

관리자는 반대 방향의 움직임도 관찰한다. Moment의 2026년 공지는 에이전트가 기존 코드와 문서에 익숙한 것이 새 사용을 유도할 가능성을 제시한다. 이는 성장 원인에 대한 관리 팀의 해석이지, AI의 인과 효과가 입증됐다는 뜻이 아니다. 이번 다운로드 데이터로도 검증할 수 없다. Moment의 에이전트 사용 관찰

따라서 ‘AI가 유틸리티를 없앤다’만으로 결론을 내리기는 어렵다. 간단한 구현을 직접 소유하기 쉽게 만드는 동시에, 예제와 오래된 지식을 통해 같은 의존성을 반복해서 도입할 수 있다. 현재 환경에 대한 적합성보다 역사적 노출 빈도가 자동 선택에 더 크게 작용할 가능성도 있다. 이는 관리할 위험이지, 이 조사에서 정량화한 시장 추세가 아니다.

도구 작성자라면 검증 가능한 정확성, 명확한 지원 범위, 신뢰할 수 있는 문서, 전문적인 실패 사례의 테스트를 축적하는 편이 중요하다고 본다. 얇은 편의 계층은 다시 만들기 쉽지만, 수년 동안 발견한 실패 조건은 같은 비용으로 얻기 어렵다.

남길 가치는 지속해서 맡는 복잡성에 있다

시간대 데이터는 정치적 결정에 따라 바뀐다. IANA는 UTC 오프셋, 시간대 경계, 일광 절약 시간 규칙의 변화를 반영해 데이터베이스를 수정한다고 설명한다. 첫 구현이 몇 개 함수로 끝났다고 이 작업이 끝나는 것은 아니다. IANA 시간대 데이터베이스

파서, 암호 구현, 복잡한 프로토콜, 접근성 컴포넌트도 같은 평가 방향을 제시한다. 실제 비용은 명세 추적, 악의적이거나 예상 밖인 입력 처리, 환경 간 테스트, 오류 수정에 있을 수 있다. 의존성을 선택할 때 확인할 책임이지, 특정 패키지의 안전성을 보장하는 말은 아니다.

몇십 줄 도구가 팀이 직접 맡기 싫은 미묘한 동작을 감쌀 수도 있다. 큰 도구 모음이 프로젝트에서 기본 기능 한 줄을 위해 쓰일 수도 있다. 크기와 가치는 일정하게 비례하지 않는다. 삭제한 뒤 남는 일을 플랫폼이 맡는지, 사실은 팀에 되돌아오는지 살펴야 한다.

나는 의존성 0개를 목표로 삼기보다 다음 행동으로 판단을 구체화하겠다.

현재 상황행동확인 기준
기본 기능으로 충분하고 환경이 고정되며 용도가 단순함직접 의존성을 점진적으로 대체실제 입력으로 성공·실패 동작 검증
기본 기능은 비슷하지만 의미가 다름우선 유지하거나 얇은 호환 계층 추가null, 오류, 취소, 시간대 등의 계약
사용 중단 권고 패키지를 직접 사용신규 사용을 제한하고 이전 계획 수립담당자, 대안, 롤백 지점 지정
상위 패키지가 해당 의존성을 가져옴상위 의존성을 추적하고 업그레이드·교체lockfile 수동 편집을 근본 해결로 취급하지 않기
변하는 전문 문제를 의존성이 담당함유지하며 계속 재평가보수 약속, 테스트, 지원 범위, 업데이트 역량

실행할 때는 먼저 패키지 관리자로 의존 경로를 확인하고, 실제 호출하는 기능을 검색한다. 최소 런타임 버전과 중요한 의미를 적고 작은 경로 하나를 교체한다. 기존 동작 테스트로 성공, 실패, 경계 입력을 비교한 뒤 프로덕션 빌드와 의존 트리를 확인한다. 직접 의존성 선언을 지워도 상위에서 가져온 다른 복사본이 남을 수 있다. lockfile을 삭제한다고 상위 패키지가 새 API를 쓰게 되는 것도 아니다.

계속 다운로드되는 패키지로 돌아가 보자. 중요한 기반일 수도 있고, 아직 끝나지 않은 이전의 흔적일 수도 있다. 숫자만으로는 결정할 수 없다.

추적할 만한 퇴장 신호는 패키지가 맡던 일에 더 적합하고 검증 가능한 담당자가 생겼다는 것이다. 플랫폼이 기본 기능을 흡수하면 도구는 더 깊은 전문성으로 가치를 증명해야 한다. 팀이 코드를 소유하기로 했다면 외부에 맡기던 책임도 넘겨받는다. 설치 패키지가 하나 줄어드는 것은 결과다. 남은 복잡성을 누가 맡는지 아는 것이 결정의 핵심이다.