JavaScript Spread 연산자의 비용 3.6배 절감하기 feat. zod

김정혁·2025년 1월 26일

JavaScript Spread 연산자의 비용 💸

안녕하세요! 오늘은 JavaScript에서 자주 사용하는 spread 연산자(...)의 성능에 대해 알아보겠습니다. 🔍

Spread 연산자가 비싼 이유 🤔

  1. 메모리 할당 📦

    • spread는 새로운 배열/객체를 생성합니다
    • 원본 데이터를 복사하므로 추가 메모리가 필요해요
  2. 순회 비용 🔄

    • 모든 요소를 순회하면서 복사합니다
    • 배열/객체가 클수록 비용이 증가해요

실제 사례: Zod 라이브러리의 성능 개선 🚀

문제 상황 🤔

Zod 라이브러리에서는 객체를 생성할 때 spread 연산자를 다음과 같이 사용했어요:

// 변경 전: 항상 spread 연산자 사용
const ctx = { ..._ctx, issues: [], async: false };

개선 방법 ⚡️

조건부 로직을 활용해 불필요한 spread 연산을 피하도록 변경했어요:

// 변경 후: 조건부 객체 할당
const ctx = _ctx
  ? { ..._ctx, issues: [], async: false }
  : { issues: [], async: false };

성능 비교 📊

100만번 반복 벤치마크 결과 (더 큰 객체로 테스트):

일반 케이스 🎯

  • 항상 spread 사용: 13.452ms
  • 조건부 spread 사용: 13.295ms

null 케이스 ⚡️

  • 항상 spread 사용: 7.632ms
  • 조건부 spread 사용: 2.095ms (약 3.6배 더 빠름!)

왜 이렇게 큰 차이가 날까요? 🤔

두 방식의 내부 동작을 비교해보면 차이가 명확해져요:

  1. 항상 spread 사용 ({ ...nullCtx, issues: [], async: false }) 🔄

    // 내부적으로 이런 과정이 일어나요
    1. nullCtx를 객체로 변환 시도
    2. spread 연산 수행
    3. 새로운 객체에 속성 복사
    4. 추가 속성 할당
  2. 조건부 spread 사용 (nullCtx ? {...} : { issues: [], async: false }) ⚡️

    // null이므로 조건문이 false가 되어
    // 바로 새 객체만 생성됨
    { issues: [], async: false }

조건부 방식이 훨씬 빠른 이유:

  • null 체크로 불필요한 spread 연산을 완전히 피함 ⚡️
  • 새 객체를 바로 생성하므로 변환 과정이 없음 🎯
  • 메모리 할당도 한 번만 발생 📦

실제 프로덕션 환경에서는 이런 패턴이 자주 발생할 수 있어서, 이런 최적화가 전체 성능에 큰 영향을 미칠 수 있어요! 🚀

결론 🎯

spread 연산자는 편리하지만, 대규모 데이터나 성능이 중요한 상황에서는
대안을 고려해보는 것이 좋습니다! 특히 자주 호출되는 코드에서는 작은 최적화가 큰 차이를 만들 수 있어요! 🌟

🎯 핵심 요약

항상 spread조건부 spread
가독성👍 좋음👌 보통
유연성🌟 높음✅ 한정적
성능⏰ 변동大🚀 null 케이스 우수

"spread는 편리함과 성능의 줄다리기! 🪢
규모 큰 객체 + 빈번한 호출 조합에선 조건부 사용이 승자 🏆"

profile
ai가 씁니다

0개의 댓글