JavaScript 배열 메서드 성능 비교 - forEach vs for vs for...of

문제 상황

사용자 데이터 15만 건을 가공하는 배치 스크립트의 실행 시간이 3분을 넘어갔다. 프로파일링 결과 배열 순회 로직이 병목이었다.

기존 코드는 forEach를 사용하고 있었다.

users.forEach(user => {
  processedData.push({
    id: user.id,
    name: normalizeString(user.name),
    score: calculateScore(user.activities)
  });
});

성능 측정

15만 건 기준으로 각 방식을 측정했다.

// 1. forEach
console.time('forEach');
users.forEach(user => transform(user));
console.timeEnd('forEach');
// 결과: 287ms

// 2. for loop
console.time('for');
for (let i = 0; i < users.length; i++) {
  transform(users[i]);
}
console.timeEnd('for');
// 결과: 98ms

// 3. for...of
console.time('for-of');
for (const user of users) {
  transform(user);
}
console.timeEnd('for-of');
// 결과: 102ms

결론

전통적인 for 루프가 가장 빨랐다. forEach는 함수 호출 오버헤드가 있어 대량 데이터에서 약 3배 느렸다.

for...of는 가독성과 성능의 균형이 좋았다. Iterator 프로토콜을 사용하지만 실제 성능은 for와 비슷했다.

최종적으로 배치 스크립트는 for 루프로 변경했고, 실행 시간이 1분 10초로 단축됐다. 일반적인 비즈니스 로직에서는 forEachfor...of의 가독성이 더 중요하지만, 성능이 critical한 경우는 여전히 전통적인 방식이 유효했다.

참고사항

  • Node.js 8.11 환경
  • V8 엔진 최적화는 계속 개선되므로 주기적 재측정 필요
  • map, filter 등은 체이닝 가능하지만 중간 배열 생성으로 메모리 사용량 증가
JavaScript 배열 메서드 성능 비교 - forEach vs for vs for...of