본문으로 건너뛰기

인기 패키지

명세 적합성만으로 실제 라이브러리가 작동한다고 보장할 수는 없습니다. JS 엔진은 test262의 99 %를 통과해도 프로덕션 코드에서 흔히 문제를 일으킵니다. 라이브러리가 여러 "명세의 세부 사항"에 의존하기 때문입니다. 예를 들어 특정 순서로 발생하는 Proxy 트랩, Function.prototype.toString 형태, 까다로운 입력에서의 정규식 동작, 계산된 속성 이름과 Object.keys 순서의 상호작용 등이 있습니다.

Phasis은 널리 사용되는 라이브러리 204개를 Node.js(V8)과 바이트 단위로 비교해 검증합니다. 저장소의 tests/Popular/ 아래에 있으며, 엔진 소스나 테스트 모음이 변경될 때마다 CI에서 실행됩니다.

카테고리별 범위

카테고리 라이브러리
파서 / AST acorn 8.16.0, chevrotain 11.0.3, parse5 7.2.1, parsimmon 1.18.1, jsep 1.4.0, postcss-value-parser 4.2.0, acorn-walk 8.3.4, estraverse 5.3.0, escodegen 2.1.0, css-tree 3.0.4, sax 1.4.1, nearley 2.20.1
템플릿 / Markdown / HTML mustache 4.2.0, handlebars 4.7.9, marked 18.0.3, markdown-it 14.1.0 (+ markdown-it-emoji), markdown-table 3.0.4, showdown 2.1.0, cheerio 1.1.2, htmlparser2 11.0.0
유틸리티 / 함수형 lodash 4.18.1, ramda 0.31.3, remeda 2.17.4, es-toolkit 1.27.0, immutable 5.1.3, immer 10.1.1, redux 5.0.1, deepmerge 4.3.1, dot-object 2.1.5, lodash.merge 4.6.2, lodash.clonedeep 4.5.0, extend 3.0.2, extend-shallow 3.0.2, mixin-deep 2.0.1, merge-options 3.0.4
객체 접근 dequal 2.0.3, clsx 2.1.1, classnames 2.5.1, get-value 4.0.1, set-value 4.1.0, object.omit 3.0.0, object.pick 1.3.0, is-plain-obj 4.1.0, kind-of 6.0.3
검증 / 스키마 zod 4.4.3, yup 1.4.0, valibot 1.1.0, superstruct 2.0.2, validator 13.12.0, email-validator 2.0.4, ajv 8.17.1, @sinclair/typebox 0.34.42, runtypes 6.7.0, typanion 3.14.0, ow 2.0.0
날짜 / 시간 dayjs 1.11.20, date-fns 4.1.0, timeago.js 4.0.2, luxon 3.7.3, moment 2.30.2
수학 / 숫자 bignumber.js 11.1.1, decimal.js 10.6.0, numeral 2.0.6, jsbi 4.3.0, big.js 6.2.2, fraction.js 4.3.7, complex.js 2.4.2, simple-statistics 7.8.8
해싱 / 암호화 blueimp-md5 2.19.0, crypto-js 4.2.0, fnv-plus 1.3.1, murmurhash3js 3.0.1, hash-sum 2.0.0, jwt-decode 4.0.0, @noble/hashes 2.2.0, tweetnacl 1.0.3, aes-js 3.1.2, bcryptjs 3.0.2, xxhashjs 0.2.2, object-hash 3.0.0
검색 / 차이 비교 fuse.js 7.3.0, minisearch 7.1.1, diff 8.0.2, diff-match-patch 1.0.5, fast-deep-equal 3.1.3, fast-equals 5.2.2, fastest-levenshtein 1.0.16, lunr 2.3.9
JSON / 데이터 형식 json5 2.2.3, js-yaml 4.1.0, yaml 2.6.1, toml 3.0.0, smol-toml 1.3.1, fast-json-patch 3.1.1, jmespath 0.16.0, jsonata 2.0.6, jsonpath-plus 10.3.0, mingo 6.7.0, sift 17.1.3, fast-json-stable-stringify 2.1.0, safe-stable-stringify 2.5.0, json-stringify-safe 5.0.1, canonicalize 2.1.0, papaparse 5.5.4
문자열 / 언어 처리 he 1.2.0, slugify 1.6.9, camelcase 8.0.0, entities 6.0.1, pluralize 8.0.0, inflection 3.0.2, wcwidth 1.0.1, emoji-regex 10.4.0, unraw 3.0.0, jsesc 3.1.0, lower-case 2.0.2, upper-case 2.0.2, dot-case 3.0.4, pascal-case 3.1.2, snake-case 3.0.4, title-case 3.0.3, xregexp 5.1.1, escape-string-regexp 5.0.0, ansi-regex 6.1.0, strip-ansi 7.1.2, string-width 8.1.0
URL / 웹 url-parse 1.5.10, qs 6.13.1, query-string 9.1.1, tldts 6.1.69, punycode 2.3.1, linkifyjs 4.3.1, ipaddr.js 2.2.0, uri-js 4.4.1, url-template 3.1.1, bowser 2.11.0
압축 / 인코딩 / 아카이브 pako 2.1.0, lz-string 1.5.0, base64-js 1.5.1, JSZip 3.10.1
색상 color-string 2.1.1, d3-color 3.1.0, chroma-js 3.1.2, color-name 2.0.0, tinycolor2 1.6.0, color 5.0.3
복제 / 동등성 rfdc 1.4.1, klona 2.0.6, fast-copy 3.0.2
형식 / 표시 ms 2.1.3, bytes 3.1.2
ID / UUID uuid 10.0.0, hexoid 2.0.0, ulid 3.0.1, cuid2 2.2.2, short-unique-id 5.4.3
유형 감지 / glob type-detect 4.1.0, picomatch 4.0.2, minimatch 10.1.1, wildcard-match 5.1.4, glob-to-regexp 0.4.1, to-regex 4.0.4, array-uniq 3.0.0, array-unique 0.3.2
Semver / 설정 semver 7.6.3, compare-versions 6.1.1, semver-compare 1.0.0
캐시 / 성능 lru-cache 11.0.2, marky 1.3.0, array-flatten 3.0.0, arr-diff 4.0.0
비동기 / 이벤트 eventemitter3 5.0.1, eventemitter2 6.4.10, mitt 3.0.1, p-limit 7.1.1, p-queue 9.0.2, p-defer 5.0.0, p-retry 7.1.0, throttle-debounce 5.0.2, async 3.2.6
반응형 상태 mobx 6.13.7, xstate 5.23.0, valtio 2.1.5, nanostores 1.0.1, jotai 2.16.1, redux-saga 1.3.0, redux 5.0.1
CSS / 스타일링 postcss 8.5.7, stylis 4.3.6, css-tree 3.0.4
빌드 / AST / 컴파일러 magic-string 0.30.20, escodegen 2.1.0, acorn-walk 8.3.4, estraverse 5.3.0, @babel/parser 7.28.5, terser 5.46.0, prettier 3.3.3, svelte 5.55.7 (컴파일러), typescript 6.0.3
MQTT / 프로토콜 mqtt-packet 9.0.4
GraphQL graphql-js 16.11.0
구문 강조 표시 highlight.js 11.11.1
테스트 / 어설션 chai 6.2.1

총 204개 라이브러리가 모두 Node의 정확한 출력을 재현합니다. 모두 마지막 업데이트 시점 기준 최신 업스트림 릴리스로 고정되어 있습니다.

작동 방식

각 시나리오는 tests/Popular/<lib>/ 디렉터리와 세 개의 파일로 구성됩니다:

Text
tests/Popular/lodash/
├── lodash.js     ← vendored upstream library (untouched, UMD bundle)
├── runner.js     ← Phasis-side script that exercises the library
└── oracle.txt    ← Node.js output of running runner.js (committed)

tests/Popular/PopularPackagesTest.php는 다음을 수행하는 PHPUnit 데이터 제공자 테스트입니다:

  1. lodash.js + runner.js를 새 new Phasis\Engine()에 로드합니다.
  2. console.log 출력을 버퍼에 캡처합니다.
  3. 캡처한 버퍼가 oracle.txt와 바이트 단위로 동일한지 확인합니다.

oracle을 다시 생성하려면 다음을 실행하세요:

셸
node tests/Popular/gen-oracle.js tests/Popular/<lib>

(벤더링한 라이브러리를 업데이트할 때 사용합니다. 실제 Node에서 러너를 다시 실행하고 oracle.txt를 덮어씁니다.)

CI 게이트

워크플로: .github/workflows/popular.yml.

main에서 src/, tests/Popular/, phpunit.xml.dist, Composer 파일 또는 워크플로 자체가 변경되는 푸시 및 풀 리퀘스트와 수동 실행 시 작동합니다. 두 단계로 구성됩니다:

  1. Phasis 측 — 각 라이브러리를 Phasis을 통해 실행하고 커밋된 oracle과 비교하는 PHPUnit popular 테스트 모음을 실행합니다. 단 한 바이트라도 다르면 실패합니다.
  2. Node 재검증 — 각 라이브러리에 대해 node tests/Popular/gen-oracle.js …를 실행하고 새로 생성한 oracle이 체크인된 내용과 일치하는지 확인합니다. "oracle을 업데이트하지 않고 벤더링한 라이브러리만 업데이트한" 불일치를 감지합니다.

PR 병합 전에 두 단계 모두 통과해야 합니다. test262에서 성공해도 lodash가 깨지면 안 되며, lodash에서 성공해도 test262이 깨지면 안 됩니다.

이 라이브러리를 선택한 이유

  • acorn — 파싱은 모든 JS 엔진에서 가장 취약한 부분입니다. 최신 JS에서 추가하는 모든 구문상의 예외 사례를 다룹니다. Phasis가 acorn으로 임의의 최신 코드를 파싱할 수 있다면 런타임은 안정적입니다.
  • mustache.js — 템플릿 처리는 Phasis가 명시적으로 대상으로 삼는 임베딩 활용 사례 중 하나입니다(README의 첫 번째 구체적 예시는 "템플릿 엔진"입니다). Mustache는 실제 템플릿에서와 같은 순서로 반복, 스코프 확인, 문자열 변환을 처리합니다.
  • lodash — 세계에서 가장 널리 사용되는 JS 유틸리티 라이브러리입니다. 300개 이상의 함수가 표준 라이브러리의 모든 메서드에 간접적으로 접근합니다. lodash가 작동하면 일반적인 데이터 변환 JS도 작동합니다.
  • marked — Markdown 렌더링에 사용됩니다. 실용적이며 정규식(매우 많은 정규식)과 줄을 넘는 상태를 사용하는 문자열 조작을 시험합니다. PCRE2(Phasis의 대체 엔진)와 V8의 Irregexp 간 정규식 엔진 차이를 드러냅니다.
  • dayjs — 날짜 및 시간 연산은 test262 테스트 사례로는 잡아낼 수 없는 하루 차이 오류의 대표적 원인입니다. dayjs는 생성자 변형, DST에 해당하는 월 경계를 넘는 연산, 형식 토큰 확장을 다루며, 대부분의 JS 날짜 라이브러리가 사용하는 코드 경로와 거의 같습니다.
  • bignumber.js — TypedArray 없이 임의 정밀도 연산을 수행하므로 문자열 기반 숫자 파싱, 큰 정수의 곱셈 및 나눗셈 반복, 반올림 모드 선택을 시험합니다. 이 모든 작업이 순수 JS로 이뤄져 엔진이 전체 비용을 부담합니다. Number ↔ String 변환에서 미묘한 문제가 있는지도 드러냅니다.
  • json5 — 느슨한 JSON 파싱은 문자 클래스 정규식과 상태를 유지하는 토큰화에 크게 의존합니다. 정규식의 정확성과 문자열 순회 경계를 모두 확인하기에 좋은 카나리아입니다.
  • fuse.js — Babel로 트랜스파일된 UMD로, _classCallCheck(ES6 이전에 트랜스파일된 모든 클래스에서 사용하는 this instanceof Ctor 패턴)과 전체 bitap 퍼지 매칭 알고리즘을 시험합니다. Babel로 트랜스파일된 라이브러리에서 흔히 볼 수 있는 형태이므로 Fuse를 망가뜨리는 문제는 npm 생태계의 절반을 망가뜨립니다.
  • handlebars — 컴파일 후 렌더링하는 기능이 풍부한 템플릿 엔진입니다. 단일 대형 compile() 엔트리를 통한 eval 없는 런타임 경로, AST 순회, 동적 조회 테이블을 통한 헬퍼 호출, 여러 realm에서 instanceof을 사용하는 SafeString 브랜드 검사를 시험합니다. mustache.js의 더 단순한 템플릿 순회 방식과 대조됩니다.
  • zod — 런타임 스키마 검증에 사용됩니다. 메서드 체이닝이 정제된 하위 클래스를 반환하는 복잡한 클래스 계층(ZodString, ZodObject, ZodArray, ZodUnion, …), JS 측의 .issues 배열 형태가 Node와 바이트 단위로 일치해야 하는 구조화된 오류 형식 지정, 판별자 및 리터럴 태그 패턴을 다룹니다. 최신 TypeScript 앱의 절반을 감싸는 객체 지향 중심 검증 코드 유형을 시험합니다.
  • typescript — 임베디드 엔진에서 실행되는 실제 TypeScript 컴파일러입니다. 9 MB 크기의 최소화된 컴파일러가 임의의 TS를 다시 파싱하고 AST를 순회해 JS를 출력합니다. 상상할 수 있는 가장 무거운 순수 JS 페이로드입니다. Phasis가 제네릭, async/await, enum, 클래스 계층을 tsc와 바이트 단위로 동일하게 트랜스파일할 수 있다면 언어 의미론은 안정적입니다.
  • prettier — 의견이 반영된 JS 포맷터입니다. JS를 포함한 JS의 형식을 지정하면 엔진이 다루는 모든 사양상의 예외가 코드 형식을 지정하는 동일한 제어 흐름을 거칩니다. 매우 까다로운 작업 부하입니다.
  • svelte/compiler — Svelte의 독립형 컴파일러입니다. .svelte 소스를 파싱하고 AST를 순회해 클라이언트 및 SSR 대상용 JS를 출력합니다.
  • terser / @babel/parser / postcss — JS 최소화 도구, JS 파서, CSS 후처리기입니다. 임의의 입력을 다시 파싱하는 수만 줄의 최소화된 코드로, 드문 AST 형태가 나타나는 영역입니다.
  • ajv — 각 스키마를 new Function(...)를 통해 사용자 지정 검증 함수로 JIT 컴파일하는 JSON 스키마 검증기입니다. 대부분의 스키마 및 템플릿 라이브러리가 사용하는 Function 생성자 경로를 시험합니다.
  • mobx — 프록시 기반 반응형 상태 관리 도구입니다. 관찰 가능한 값을 읽을 때마다 Proxy get 트랩이 종속성을 등록하고, 쓸 때마다 반응을 실행합니다. Proxy 인프라, 관찰 가능한 Map/배열/중첩 객체, autorun 스케줄러를 집중적으로 시험합니다.
  • cheerio / htmlparser2 — 빠른 HTML 파서를 기반으로 한 서버 측 jQuery입니다. 선택자 엔진 파싱, DOM 방식 순회, 속성 조작, HTML 직렬화를 하나의 패키지에서 처리합니다.
  • graphql-js / jsonata — GraphQL 참조 구현과 JSON 쿼리 언어입니다. 둘 다 스키마, 검증, 재귀 평가기를 많이 사용하므로 브라우저의 데이터 계층 코드에서 흔히 볼 수 있는 유형입니다.
  • JSZip — 비동기 ZIP 아카이브 생성기입니다. setImmediate 기반 스케줄링으로 작업을 처리하고 실제 바이너리 출력을 생성해 타이머 처리 영역과 Uint8Array 중심 경로를 모두 시험합니다.
  • moment / luxon — 날짜 및 시간 연산에 사용됩니다. moment는 변경 가능한 수작업 최적화 UMD이고, luxon은 이를 현대적으로 재작성한 변경 불가 버전입니다. 둘을 함께 사용하면 형식 지정, 파싱, 시간대가 같은 월 및 연도 계산을 폭넓게 다룹니다.
  • mqtt-packet — 순수 JS MQTT 3.1.1 / 5.0 코덱입니다. 바이트 단위 패킹과 디코딩에 더해 Base64 비알파벳 정규식 문자 클래스를 다뤄 Annex-B 문법의 경계를 시험합니다.
  • xstate / valtio / nanostores / jotai / redux-saga — 현대 상태 관리 방식의 폭넓은 사례입니다. 상태 머신, 프록시 상태, atom 저장소, 파생 atom, 제너레이터 기반 효과 실행기를 다루며 각 라이브러리는 서로 다른 반응성 형태를 시험합니다.
  • escodegen / acorn-walk / estraverse / magic-string — AST 도구입니다. 코드 생성, 순회, 원본을 손상하지 않는 편집은 모든 JS-on-JS 변환 도구(빌드 도구, 코드모드, 린터)의 기본 요소입니다.
  • papaparse / lunr / yaml / sax / css-tree — 순수 파서 및 토크나이저입니다. CSV, 전체 텍스트 검색 인덱스, YAML 1.2, 스트리밍 SAX 방식 XML, CSS AST를 다룹니다. 문법은 서로 다르지만 모두 문자 단위 스캔과 정규식 동작을 확인하기 좋은 카나리아입니다.

더 추가하기

세 파일로 구성된 새 디렉터리를 tests/Popular/<name>/ 아래에 만든 다음 다음을 실행하세요:

셸
node tests/Popular/gen-oracle.js tests/Popular/<name>   # one-time, generates oracle.txt
git add tests/Popular/<name>

다음 실행 시 PHPUnit 테스트 모음이 해당 디렉터리를 자동으로 찾아내며, 변경 사항이 tests/Popular/에 적용되므로 CI에서도 실행됩니다.

추가할 만한 유력 후보: chevrotain(파서 결합자, 클로저와 정규식을 시험), nanoid(암호화/난수성 경계), date-fns(dayjs보다 폭넓은 시간대 처리).