JavaScript 배열 메서드 체이닝 성능 비교

문제 상황

프로젝트에서 10만 건 정도의 주문 데이터를 필터링하고 변환하는 작업을 하게 되었다. 평소처럼 배열 메서드를 체이닝해서 작성했는데, 브라우저가 눈에 띄게 버벅이는 것을 발견했다.

const result = orders
  .filter(order => order.status === 'completed')
  .map(order => ({ ...order, total: order.price * order.quantity }))
  .filter(order => order.total > 10000)
  .map(order => order.userId);

성능 측정

배열 메서드 체이닝은 각 메서드마다 전체 배열을 순회한다. 위 코드는 최대 4번 순회하게 된다. 이를 단일 루프로 변경해봤다.

const result = [];
for (let i = 0; i < orders.length; i++) {
  const order = orders[i];
  if (order.status !== 'completed') continue;
  
  const total = order.price * order.quantity;
  if (total > 10000) {
    result.push(order.userId);
  }
}

10만 건 기준으로 Chrome 63에서 측정한 결과:

  • 체이닝: 약 45ms
  • for 루프: 약 12ms

결론

가독성과 성능 사이의 트레이드오프다. 데이터가 적으면 체이닝이 낫지만, 대량 데이터는 for 루프를 고려해야 한다. reduce로 한 번에 처리하는 방법도 있지만, 가독성이 떨어져서 팀 내 코드 리뷰에서 반려될 가능성이 높다.

실무에서는 데이터 크기에 따라 선택하는 게 답인 것 같다. 1만 건 이하면 체이닝, 그 이상이면 최적화를 고려한다.