
Dual package hazard 해결부터 최신 Node.js 스펙 활용까지, 사내 패키지 관리 단순화 전략
토스뱅크 기술그룹에서 공통 라이브러리 운영 시 발생하던 Dual package hazard 및 타입 유실 문제를 고찰하고, ESM-only 패키지 제공 체계로 전환한 배경과 이점을 공유합니다. 통제 가능한 사내 환경의 강점과 최신 Node.js 모듈 스펙을 연계하여 개발 생산성을 끌어올린 실무 사례입니다.
모노레포나 사내 라이브러리를 구축 및 유지보수하면서 모듈 시스템 및 타입스크립트 export 설정으로 어려움을 겪는 웹 엔지니어에게 추천합니다.
기존의 Dual package(ESM과 CJS 동시 제공) 방식은 모듈 로드 방식에 따라 동일한 패키지의 상태가 이중화되는 Dual package hazard 문제와 CJS 경로에서 타입을 찾지 못해 타입 안정성이 깨지는 문제를 유발했습니다.
Node.js 22.12.0부터 지원되는 require(esm) 기능과 제어 가능한 사내 환경의 특성을 활용하여 기존 Dual package 빌드를 제거하고 표준 모듈 시스템인 ESM-only로 통합하였습니다.
패키지 제작자는 두 포맷의 실행 코드 및 타입을 이중 관리할 필요가 없어졌고, 사용자는 로드된 모듈 추적 및 상태 분리 오류 없이 안정적인 개발 체계를 확보했습니다.
Trade-off
구버전 Node.js 환경에 대한 하위 호환성을 포기해야 하며, CJS에서 require()로 불러오는 ESM 모듈 및 의존성에 최상위 await이 없어야 하는 실행 환경 제약이 존재합니다.
동일한 패키지의 ESM과 CJS 구현체가 한 애플리케이션 내에 동시 로드되어 모듈 내부의 상태나 싱글톤 객체, 캐시가 이중으로 생성되는 현상입니다.
JavaScript의 공식 표준 모듈 시스템으로, import 및 export 구문을 사용하며 정적 분석을 통한 효율적인 트리 셰이킹을 지원합니다.
package.json 내에서 모듈의 진입점을 사용 환경(ESM/CJS, TypeScript 등) 조건에 따라 매핑하도록 지정하는 Node.js 명세입니다.