# JavaScript 비대화의 세 가지 축

> Clean Markdown view of GeekNews topic #27752. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=27752](https://news.hada.io/topic?id=27752)
- GeekNews Markdown: [https://news.hada.io/topic/27752.md](https://news.hada.io/topic/27752.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-03-23T09:55:50+09:00
- Updated: 2026-03-23T09:55:50+09:00
- Original source: [43081j.com](https://43081j.com/2026/03/three-pillars-of-javascript-bloat)
- Points: 10
- Comments: 2

## Summary

npm 생태계의 **의존성 비대화**는 여전히 개발자 경험을 느리게 만드는 핵심 문제로 지적됩니다. 오래된 런타임 호환성과 **원자적 패키지 구조**, 그리고 이미 모든 엔진이 지원하는 기능을 위한 낡은 ponyfill이 그 원인으로 꼽힙니다. 커뮤니티는 e18e, knip, module‑replacements 같은 도구를 통해 **불필요한 패키지를 네이티브 기능으로 치환**하며 트리를 정리하는 흐름을 만들고 있습니다.

## Topic Body

- npm 생태계에서 **의존성 트리의 비대화**가 주요 문제로 지적되며, 이는 오래된 런타임 지원, 원자적 패키지 구조, 오래된 ponyfill 사용에서 비롯됨
- 구형 엔진 호환성과 **cross-realm 안전성**을 이유로 유지되는 작은 유틸리티 패키지들이 현대 환경에서도 불필요하게 남아 있음
- **원자적 아키텍처**는 재사용성을 높이려 했으나, 실제로는 중복·보안·유지보수 비용을 증가시키는 비효율적 구조로 작용함
- 이미 모든 엔진이 지원하는 기능을 위한 **낡은 ponyfill 패키지**들이 제거되지 않아 불필요한 다운로드와 관리 부담을 초래함
- 커뮤니티는 e18e, knip, module-replacements 같은 도구를 통해 **불필요한 의존성 정리와 네이티브 기능 전환**을 추진 중임

---

### JavaScript 의존성 비대화의 세 가지 축
- **e18e 커뮤니티**의 성장과 함께 성능 중심의 기여가 늘어나며, 불필요하거나 유지되지 않는 패키지를 정리하는 **cleanup 활동**이 진행 중임
- npm 생태계에서 **의존성 트리의 비대화(dependency bloat)** 가 주요 문제로 지적되며, 오래된 런타임 지원, 원자적 패키지 구조, 오래된 ponyfill 사용이 핵심 원인으로 꼽힘

### 1. 오래된 런타임 지원 (안전성과 realm 포함)
- npm 트리에는 `is-string`, `hasown` 같은 **작은 유틸리티 패키지**들이 다수 존재하며, 이는 다음 세 가지 이유로 유지됨
  - 매우 오래된 엔진(예: **ES3, IE6/7, 초기 Node.js**) 지원
  - ### 전역 네임스페이스 변조 방지
    - **cross-realm 값 처리**
- ## 오래된 엔진 지원
  - ES3 환경에는 `Array.prototype.forEach`, `Object.keys`, `Object.defineProperty` 등 **ES5 기능이 존재하지 않음**
  - 이런 환경에서는 직접 구현하거나 polyfill을 사용해야 함
  - 가장 좋은 해결책은 **업그레이드**이지만, 일부 사용자는 여전히 구버전을 유지함
- ## 전역 네임스페이스 변조 방지
  - Node는 내부적으로 **primordials** 개념을 사용해 전역 객체를 초기 시점에 래핑하여 변조로부터 보호함
  - 예를 들어 `Map`을 재정의하면 Node 자체가 깨질 수 있으므로, Node는 원본 참조를 유지함
  - 일부 패키지 유지자는 이 방식을 일반 패키지에도 적용해 `math-intrinsics` 같은 **안전성 중심 패키지**를 사용함
- ## Cross-realm 값
  - iframe 간 객체 전달 시 `instanceof` 검사가 실패하는 문제 발생
  - 예: `window.RegExp !== iframeWindow.RegExp`
  - `chai` 같은 테스트 프레임워크는 `Object.prototype.toString.call(val)` 방식으로 realm 간 타입 검사를 수행함
  - `is-string` 같은 패키지는 이런 **cross-realm 호환성**을 위해 존재함
- ## 문제점
  - 대부분의 개발자는 **현대 Node나 evergreen 브라우저**를 사용하므로 이런 호환성이 불필요함
  - 그러나 이들 패키지가 일반 의존성 트리의 “핫패스”에 포함되어 **모두가 비용을 지불**하게 됨

### 2. 원자적(Atomic) 아키텍처
- 일부 개발자는 패키지를 가능한 한 **작은 단위로 분리**해 재사용 가능한 빌딩 블록으로 구성해야 한다고 주장함
- 결과적으로 `shebang-regex`, `arrify`, `slash`, `path-key`, `onetime`, `is-wsl` 등 **극도로 세분화된 패키지**들이 다수 존재함
- 예: `shebang-regex`는 단 한 줄의 정규식만 포함 (`/^#!(.*)/`)
- ## 문제점
  - 대부분의 원자적 패키지는 **재사용되지 않거나 단일 소비자만 존재**
  - 예:
    - `shebang-regex` → `shebang-command`만 사용
    - `cli-boxes` → `boxen`, `ink`만 사용
    - `onetime` → `restore-cursor`만 사용
  - 이런 경우 인라인 코드와 동일하지만 **npm 요청, 압축 해제, 대역폭** 등의 추가 비용이 발생
- ## 중복 문제
  - 예: `nuxt@4.4.2` 의존성 트리에서 `is-docker`, `is-stream`, `is-wsl`, `path-key` 등이 **2개 버전씩 중복 존재**
  - 인라인 코드로 대체하면 버전 충돌이나 해상 비용이 사라져 **중복 비용이 거의 없음**
- ## 공급망 위험 확대
  - 패키지 수가 많을수록 **보안·유지보수 리스크** 증가
  - 실제로 한 유지자가 다수의 작은 패키지를 관리하다 계정이 해킹되어 **수백 개 패키지가 동시에 손상**된 사례 존재
  - 단순한 코드(`Array.isArray(val) ? val : [val]`)는 별도 패키지로 둘 필요 없이 인라인으로 처리 가능
- ## 결론
  - 원자적 아키텍처는 의도와 달리 **비효율적이고 위험한 구조**로 변질
  - 대부분의 사용자에게 실질적 이득 없이 **전체 생태계가 비용을 부담**

### 3. 오래된 Ponyfill
- **Polyfill**은 엔진이 지원하지 않는 기능을 환경에 추가하는 코드이며,
  **Ponyfill**은 환경을 수정하지 않고 **직접 import**하여 사용하는 대체 구현임
- 예: `@fastly/performance-observer-polyfill`은 polyfill과 ponyfill을 모두 제공
- ## 문제점
  - Ponyfill은 과거에는 유용했으나, **대상 기능이 이미 모든 엔진에서 지원됨에도 제거되지 않음**
  - 예시:
    - `globalthis` (2019년부터 지원, 주간 4,900만 다운로드)
    - `indexof` (2010년부터 지원, 주간 230만 다운로드)
    - `object.entries` (2017년부터 지원, 주간 3,500만 다운로드)
  - 이런 패키지는 대부분 **단순히 제거되지 않았기 때문**에 남아 있음
  - 모든 LTS 엔진이 기능을 지원하면 **ponyfill은 제거되어야 함**

### 비대화 해소 방안
- **의존성 트리의 깊은 중첩**으로 인해 정리 작업은 어렵지만, 커뮤니티 협력으로 개선 가능
- 각 개발자는 “이 패키지가 정말 필요한가?”를 자문하고, 불필요하다면 **이슈를 제기하거나 대체 패키지 탐색** 필요
- [module-replacements](https://e18e.dev/docs/replacements/) 프로젝트는 **네이티브 기능으로 대체 가능한 패키지 목록**을 제공
- ## knip 사용
  - [knip](https://knip.dev/)은 **사용되지 않는 의존성 및 죽은 코드 탐지 도구**
  - 직접적인 해결책은 아니지만, **정리의 출발점**으로 유용
- ## e18e CLI 활용
  - `@e18e/cli analyze` 명령으로 **대체 가능한 의존성 탐지** 가능
  - 예: `chalk` → `picocolors`로 자동 마이그레이션
  - 향후에는 환경에 따라 **Node의 `styleText` 같은 네이티브 기능 추천** 예정
- ## npmgraph 활용
  - [npmgraph.js.org](https://npmgraph.js.org/)는 **의존성 트리 시각화 도구**
  - 예: `eslint@10.1.0` 트리에서 `find-up` 브랜치가 고립되어 있음
  - 단순한 파일 탐색 기능에 6개 패키지가 필요하지 않으므로, `empathic` 같은 **더 작은 대안** 사용 가능
- ## module replacements 프로젝트
  - 커뮤니티가 **대체 가능한 패키지와 네이티브 기능 매핑 데이터셋**을 유지
  - [codemods 프로젝트](https://github.com/es-tooling/module-replacements-codemods)를 통해 **자동 마이그레이션**도 지원

### 결론
- 현재의 비대화는 **소수의 구형 호환성·특이한 구조를 유지하려는 사용자** 때문에 전체가 비용을 부담하는 구조
- 과거에는 불가피했지만, **현대 엔진과 API가 충분히 발전한 지금은 불필요한 부담**
- 앞으로는 이 소수가 별도의 스택을 유지하고, 나머지는 **가볍고 현대적인 코드 기반**을 사용하는 방향으로 전환 필요
- **e18e**와 **npmx** 같은 프로젝트가 문서화·도구화를 통해 이를 지원 중이며,
  각 개발자도 자신의 의존성을 점검하고 “왜 필요한가?”를 질문해야 함
- **모두가 함께 정리할 수 있음**

## Comments



### Comment 53633

- Author: click
- Created: 2026-03-23T11:22:15+09:00
- Points: 1

저도 라이브러리 만들 때 아직 cjs 빌드를 제공하기는 하지만  
2026년에 esm 예시조차 없고 전부 require 기반인 라이브러리들은 좀 업데이트를 했으면 좋겠긴 합니다.

### Comment 53613

- Author: neo
- Created: 2026-03-23T09:55:50+09:00
- Points: 1

###### [Hacker News 의견들](https://news.ycombinator.com/item?id=47473718) 
- 요즘은 **의존성 없는 JavaScript**로 개발하는 게 가장 좋은 방향이라 생각함  
  JS/CSS 표준 라이브러리도 훌륭하고, 정적 분석(TypeScript의 JSDoc 체크), ES 모듈, 웹 컴포넌트 등도 충분히 강력함  
  사람들은 이 방식이 확장성이나 유지보수에 불리하다고 하지만, 내 경험상 오히려 단순하고 변경이 쉬운 구조를 유지할 수 있었음
  - 나도 몇 년째 이 접근을 실험 중이며, [plainvanillaweb.com](https://plainvanillaweb.com)이라는 튜토리얼 사이트도 만들었음  
    프레임워크나 빌드 도구가 하는 일 대부분은 브라우저 내장 기능과 **바닐라 패턴**으로 대체 가능함  
    다만 이런 방식은 아직 생소한 영역이라, 대부분의 튜토리얼 생태계가 대형 프레임워크 중심으로 돌아가는 게 문제임  
    실제로 React 코드를 완전 바닐라로 옮겨도 모듈성은 유지되고 코드 길이는 약 1.5배 정도 늘 뿐, 의존성이 없어서 성능은 오히려 좋아짐  
    물론 의존성이 나쁘다는 건 아님. 다만 많은 개발자가 “반드시 써야 한다”는 **고정관념**에 갇혀 있음
  - 단순한 마케팅 페이지라면 가능하지만, 기능이 많은 앱이라면 의존성이 필수적인 경우가 많음  
    예를 들어 나는 지도 기능이 많은 사이트를 만드는데, **mapbox/maplibre/openlayers** 같은 대안 없는 라이브러리를 써야 함
  - 2022년에 이 방식으로 프로젝트를 진행했는데, CVE나 버전 마이그레이션 관련 문제는 전혀 없었음  
    클라이언트도 마이그레이션 비용을 한 푼도 내지 않았음
  - 컴포넌트 렌더링은 쉽지만, 프레임워크의 핵심은 **모델의 반응형 업데이트** 제공임  
    [이 글](https://mjswensen.com/blog/the-single-most-important-factor-...)처럼 모델 업데이트를 어떻게 처리하는지 궁금함
  - 20년 가까이 JS를 다뤄왔는데, 결국 최소한의 의존성만 두고 나머지는 직접 만드는 방식으로 정착했음  
    오히려 **대규모 코드베이스**를 적은 인원으로 유지하기가 더 편해졌음  
    요즘 도구들 덕분에 예전보다 직접 구현이 훨씬 쉬워졌고, **agentic engineering**과도 잘 맞음

- 글이 잘 쓰였고, 감정적이지 않으면서 문제를 명확히 설명함  
  JS가 “**표준 라이브러리**”를 제대로 갖추지 못한 게 이런 상황의 일부 원인이라 생각함
  - 요즘 JS 표준 라이브러리가 꽤 방대해졌는데, 아직 어떤 기능이 부족하다고 보는지 궁금함
  - 나는 오히려 **격한 글(rant)** 을 좋아함. 사람들의 감정뿐 아니라 그 이유를 이해하는 데 도움이 됨

- 좋은 글이지만, 문제의 근본은 **불필요한 추가(=bloat)** 자체라고 생각함  
  “완벽함은 더 이상 추가할 게 없을 때가 아니라, 더 이상 뺄 게 없을 때 이루어진다”는 생텍쥐페리의 말을 인용하고 싶음  
  대부분의 소프트웨어는 “어떻게 더 우아하게 만들까?”보다 “어떻게 더 쉽게 추가할까?”를 묻는 식으로 작성됨  
  답은 언제나 `npm i more-stuff`임
  - 커트 보니것의 글쓰기 규칙처럼, “모든 문장은 캐릭터를 드러내거나 행동을 전진시켜야 한다”는 원칙을 떠올림  
    **데모스테네스와 키케로**의 대비처럼, 덜어낼 수 없는 코드가 좋은 코드임
  - 모든 소프트웨어에 불필요한 부분이 있지만, 특히 npm 패키지와 웹앱이 심함  
    JS는 과거와 미래 브라우저 호환성을 모두 고려해야 하고, UI 중심 언어라 접근성·국제화·모바일 지원 등으로 **부피가 커짐**

- 많은 경우 이건 숨겨진 **기술 부채** 문제로 보임  
  컴파일 타깃을 ESx로 안 올리고, 패키지나 구현을 업데이트하지 않는 게 원인임  
  ES5는 이미 13년째 모든 브라우저에서 지원됨 ([caniuse.com/es5](https://caniuse.com/es5))
  - 실제로는 오래된 JS 엔진을 지원하려는 사람과, 수많은 **미니 패키지**를 만드는 사람이 있음  
    둘 다 자신들의 행동을 기능이라 여기고, 인기 패키지를 많이 유지함  
    그래서 바뀌기 어려움. 가끔 커뮤니티가 비판하지만, 그들도 나름 논리를 갖고 있음
  - ES6 이하 호환성을 유지하려는 욕심이 이상하게 느껴짐  
    Babel로 구버전으로 트랜스파일하면 코드가 **비대하고 느려지며**, 정작 옛 브라우저에서는 CSS나 JS 기능 한계로 안 돌아감  
    심지어 **polyfill**이 문제를 일으킨 적도 있었음 (BigInt를 처리 못한 지수 연산자 polyfill)
  - 오래된 브라우저뿐 아니라 **이상한 브라우저** 지원도 필요함  
    콘솔, TV, 구형 안드로이드, iPod touch, Facebook 내장 브라우저 등 다양한 환경이 존재함  
    그래서 외부 모듈 하나만 두고, 나머지는 트랜스파일러 설정으로 해결함
  - 웹은 “지금 배포하고 나중에 고치자”는 문화가 강해서, **낡은 의존성**이 오래 남음
  - Angular의 설계 결정처럼, 과거의 구조가 현재의 **비효율**을 초래하는 경우도 있음  
    예전엔 비동기 추적을 위해 setTimeout 등을 오버라이드했지만, 이제는 **signals**로 훨씬 단순하게 처리 가능함

- 일부 패키지 저자들이 **다운로드 수를 늘리기 위해** 의존 트리를 인위적으로 쪼갠다고 생각함  
  7줄짜리 패키지가 존재하는 건 말이 안 됨. lockfile 메타데이터가 코드보다 큼  
  예전에 create-react-app 의존성 중 5%가 한 저자의 미니 패키지였음  
  [has-symbols](https://www.npmjs.com/package/has-symbols), [is-string](https://www.npmjs.com/package/is-string), [ljharb](https://github.com/ljharb) 같은 사례가 있음
  - 이런 행위가 단순한 **자존심**인지, 실제로 이익이 있는지 궁금함  
    예를 들어 Anthropic은 npm 다운로드 수가 많은 오픈소스 유지보수자에게 **무료 Claude**를 제공함
  - [immich.app/cursed-knowledge](https://immich.app/cursed-knowledge) 글처럼, “하위 호환성”을 이유로 50개 패키지를 추가하는 사람도 있음
  - 보안 측면에서도 심각함. 이런 **마이크로 패키지** 하나하나가 공격 표면이 됨  
    다운로드 수 경쟁은 오히려 위험을 키움
  - 예전에 어떤 사람이 조직에 침투해 자기 패키지를 의존성에 추가해 **이력서용 스타 수**를 올린 사례도 있었음
  - 문화적 문제도 있음. JS 커뮤니티에서는 7줄짜리 코드를 직접 붙여 넣는 걸 “**바퀴 재발명**”이라 비판함  
    하지만 다른 문화에서는 그게 오히려 좋은 일로 여겨짐

- JS 생태계를 비판하기 전에 [30 years of br tags](https://www.artmann.co/articles/30-years-of-br-tags)를 읽어보면 좋음  
  JS와 도구의 **진화 과정**을 이해할 수 있음  
  단순히 “JS 개발자들이 문제다”라고 말하는 건 공학적 사고의 결여임
  - 나쁜 현실을 이해하려는 태도는 좋지만, **과도한 수용**은 패배주의임  
    우리는 항상 더 나은 이론과 실천을 고민해야 함  
    소프트웨어 세계는 빠르게 변하므로, 스스로 “가짜 장례식”을 치르며 낡은 관행을 버릴 필요가 있음
  - 이 글은 개발자를 비난하기보다, 현 상태를 **합리적으로 비판**하는 글로 느껴졌음

- 9년 된 Node.js 코드베이스를 관리 중인데, 의존성은 8개뿐이고 모두 **하위 의존성 없음**  
  Node 내장 기능을 우선 활용하고, 필요한 부분만 직접 구현함  
  예전보다 훨씬 안정적이고 스트레스가 적음  
  Deno의 **표준 라이브러리**도 훌륭해서, 런타임 기본 기능과 함께라면 몇 개 패키지로도 충분히 앱을 만들 수 있음  
  JS는 **신중하게 접근하면 꽤 괜찮은 언어**임

- `is-string` 같은 패키지의 **cross-realm 안전성** 주장은 이해하지만, 실제로 그런 상황은 드묾  
  npm이 너무 쉽게 배포를 허용하면서 “모듈을 쪼개서 배포하자”는 철학이 **과잉 확장**된 게 문제임  
  소비자는 의존 트리를 감사하지 않고 그냥 설치하므로, 선택적 비용이 기본 비용이 되어버림  
  **ponyfill** 문제는 자동화로 해결 가능함  
  예를 들어 Node LTS 버전에서 이미 지원되는 기능을 자동 감지해 제거하는 **Renovate 스타일 봇**이 도움이 될 것 같음

- 사내 PWA의 원칙은 단 하나임:  
  “**Chrome 최신 버전으로 업그레이드**하라. 그래도 문제가 있으면 그때 본다”
  - 내부용이라면 이게 맞는 접근임. 회사가 지원 브라우저를 정하면 관리가 쉬움  
    Safari가 메모리를 덜 쓰는 건 이해하지만, 정책적으로 통일하는 게 효율적임
  - 단순하게 유지하는 게 결국 **가장 큰 이득**을 줌

- “ES3(IE6/7 수준)까지 지원해야 한다”는 말은 정말 이해하기 힘듦  
  보안상 은행 사이트조차 그런 구형 브라우저를 막아야 함
  - 이런 팀은 대부분 2015년쯤 세팅한 **빌드 도구를 아직도 안 바꾼** 경우임  
    Webpack, Babel, polyfill 스택을 업그레이드하는 건 큰 일이라 그냥 그대로 둠  
    “고장 나지 않았으면 고치지 말자”식 문화임
  - 실제로 그런 구버전 지원을 주장하는 **특정 인물**이 있고, 그가 많은 저수준 패키지를 유지함
  - 참고로 **Deutsche Bahn**이 아직 Windows 3.1을 쓴다는 이야기도 들었음
