toss

es-toolkit, 사내 작은 라이브러리가 전세계적인 라이브러리가 되기까지 (새 탭에서 열림)

es-toolkit은 오래되고 비효율적인 lodash를 현대 JavaScript 환경에 맞게 대체하기 위해 시작된 유틸리티 라이브러리입니다. 불필요한 호환 코드를 제거하고 핵심 사용 사례에 집중한 결과, 함수 성능은 최대 10배 이상 향상되고 번들 크기는 최대 30배 이상 줄었습니다. 이후 es-toolkit/compat과 오픈소스 커뮤니티의 기여를 통해 Yarn, Recharts, Storybook 등 다양한 프로젝트에 채택되며 주간 NPM 다운로드 2천만 회를 넘어섰습니다.

lodash의 한계와 es-toolkit의 시작

  • lodash는 오래된 브라우저와 Internet Explorer를 지원하기 위한 방어적 코드가 많이 포함되어 있습니다.
  • Array#map처럼 현대 브라우저가 기본 제공하는 기능도 직접 구현해 코드가 불필요하게 커졌습니다.
  • ECMAScript Modules를 지원하지 않아 Tree-shaking으로 필요한 코드만 포함하기 어려웠습니다.
  • lodash-es는 ESM만 추가했을 뿐, 기존 lodash의 낡고 비효율적인 구현 문제는 그대로였습니다.
  • 토스 내부에서도 @toss/utils를 직접 운영했지만, 유틸리티 함수의 다양한 엣지 케이스를 관리하는 데 부담이 있었습니다.
  • 이에 따라 “lodash의 불필요한 로직을 제거해 더 빠르고 작은 라이브러리를 만들자”는 목표로 es-toolkit이 시작되었습니다.

성능과 번들 크기 개선

  • lodash의 핵심 함수인 throttle, debounce, uniq 등을 현대적인 방식으로 다시 구현했습니다.
  • 함수별로 차이는 있지만 불필요한 로직을 제거한 결과 성능이 최소 2배에서 최대 10배 이상 향상되었습니다.
  • 오래된 브라우저 지원 코드와 중복 구현을 제거해 번들 크기가 최대 30배 이상 감소했습니다.
  • 현대적인 모듈 구조를 활용해 사용하는 함수만 번들에 포함할 수 있도록 했습니다.
  • 핵심 유스케이스에 집중해 모든 예외 상황을 처리하는 대신, 일반적인 사용 환경에서 작고 빠르게 동작하도록 설계했습니다.

오픈소스 커뮤니티의 확산

  • 토스 프론트엔드 SNS를 통해 첫 버전을 공개한 뒤 국내 개발자들의 관심과 기여가 이어졌습니다.
  • 기여자들은 누락된 함수 구현, 버그 수정, 성능 최적화 등을 Pull Request로 보완했습니다.
  • 해외 개발자 커뮤니티에 소개된 후 수만 명이 저장소를 확인하고, 구현 방식과 개선점에 대해 활발히 논의했습니다.
  • 커뮤니티에서는 lodash를 es-toolkit으로 바꾸는 번들러 플러그인과 다른 라이브러리의 의존성을 교체하는 작업도 자발적으로 진행했습니다.
  • 외부 기여자로 참여한 이다용 개발자는 지속적인 코드 리뷰와 기여를 통해 JavaScript 및 API 설계 경험을 쌓았고, 이후 토스뱅크 입사로 이어졌습니다.

es-toolkit/compat을 통한 마이그레이션

  • es-toolkit은 주요 사용 사례에 집중했기 때문에 lodash와 함수 동작이 다른 경우가 있었습니다.
  • 단순히 import 경로만 바꾸면 런타임 오류가 발생할 수 있어 기존 프로젝트의 마이그레이션 부담이 컸습니다.
  • 이를 해결하기 위해 lodash의 인터페이스와 동작을 최대한 호환하는 중간 계층인 es-toolkit/compat을 제공했습니다.
  • 기존 코드를 크게 수정하지 않고 import만 변경해도 내부 구현의 현대화 효과를 얻을 수 있도록 했습니다.
  • 이 접근 방식으로 Storybook, Mermaid, Yarn Berry, Recharts 등 대규모 오픈소스 프로젝트의 채택이 늘었습니다.
  • 결과적으로 es-toolkit은 주간 NPM 다운로드 2천만 회 이상을 기록했습니다.

앞으로의 확장 방향

  • 더 많은 JavaScript 라이브러리가 es-toolkit을 사용해 번들 크기와 실행 성능을 개선하도록 지원할 계획입니다.
  • MapSet의 필터링처럼 기존 내장 자료구조에서 다루기 불편한 기능을 추가하려고 합니다.
  • Promise 기반 비동기 코드에서 자주 사용하는 delay 같은 실용적인 함수도 제공합니다.
  • 브라우저뿐 아니라 Node.js, Deno, Bun 등 서버 환경을 위한 유틸리티로 영역을 넓히고 있습니다.
  • 최근 추가된 exec처럼 필요한 기능은 유지하면서도 경쟁 구현보다 작은 함수를 제공하는 것을 지향합니다.
  • 앞으로도 “80% 이상의 유스케이스에 최적화된 작고 빠른 구현”이라는 원칙을 유지할 계획입니다.

기존 lodash를 사용 중인 프로젝트라면 먼저 es-toolkit/compat으로 점진적인 교체를 검토하는 것이 현실적인 접근입니다. 이후 호환성이 필요 없는 코드부터 순수 es-toolkit 함수로 전환하면 성능과 번들 크기를 줄이면서도 마이그레이션 위험을 낮출 수 있습니다.