Computer >> 컴퓨터 >  >> 프로그래밍 >> JavaScript

JavaScript 배열 합계 성능 비교: 재귀 vs for 루프 vs ES6 메서드

개요

수많은 숫자 항목을 담고 있는 배열이 있을 때, 배열의 모든 요소를 합산하는 데 걸리는 시간을 세 가지 방식으로 비교해 보겠습니다. 바로 재귀(recursion), for 루프, 그리고 ES6 함수(reduce())입니다.

실제로 거대한 배열을 만드는 대신, 비교적 작은 배열을 약 1억 번(100,000,000회) 반복 실행하여 대용량 데이터 처리 상황을 시뮬레이션합니다. 목표는 각 방식이 배열 합산에 소요하는 시간의 대략적인 비율을 파악하는 것입니다.

방법 1: 재귀 접근 방식

재귀 함수는 자기 자신을 호출하며 배열을 순회합니다. 함수가 호출될 때마다 새로운 스택 프레임이 생성되므로 호출 오버헤드가 누적되어 상대적으로 느린 편입니다.

const recursiveSum = (arr, len = 0, sum = 0) => {
    if(len < arr.length){
        return recursiveSum(arr, len+1, sum + arr[len]);
    };
    return sum;
};

방법 2: for 루프 접근 방식

가장 전통적인 방식으로, 인덱스를 증가시키며 배열 요소를 하나씩 더합니다. 불필요한 오버헤드 없이 직접 순회하기 때문에 안정적인 성능을 보여줍니다.

const loopingSum = arr => {
    let sum = 0;
    for(let i = 0; i < arr.length; i++){
        sum += arr[i];
    };
    return sum;
};

방법 3: ES6 접근 방식

ES6에서 널리 사용되는 고차 함수 reduce()를 활용한 한 줄짜리 코드입니다. 내부적으로 최적화되어 있어 가독성과 성능 면에서 모두 유리합니다.

const ES6Sum = arr => arr.reduce((acc, val) => acc+val);

이제 console 객체의 time()과 timeEnd() 메서드를 사용해 세 함수의 성능을 측정하고 비교해 보겠습니다.

예제 코드

const ITERATIONS = 100000000;
const arr = [12, 65, 87, 2, 23, 87, 4, 66, 34, 89, 89, 32, 4];
const recursiveSum = (arr, len = 0, sum = 0) => {
    if(len < arr.length){
        return recursiveSum(arr, len+1, sum + arr[len]);
    };
    return sum;
};
const loopingSum = arr => {
    let sum = 0;
    for(let i = 0; i < arr.length; i++){
        sum += arr[i];
    };
    return sum;
};
const ES6Sum = arr => arr.reduce((acc, val) => acc+val);
console.time('recursive approach');
for(let k = 0; k < ITERATIONS; k++){
    recursiveSum(arr);
};
console.timeEnd('recursive approach');
console.time('looping approach');
for(let l = 0; l < ITERATIONS; l++){
    loopingSum(arr);
};
console.timeEnd('looping approach');
console.time('ES6 approach');
for(let m = 0; m < ITERATIONS; m++){
    ES6Sum(arr);
};
console.timeEnd('ES6 approach');

실행 결과

참고: 아래 결과는 어디까지나 예시입니다. 코드의 실제 성능은 시스템 사양과 실행 환경에 따라 크게 달라지지만, 세 함수 간 소요 시간의 비율은 어떤 환경에서든 대체로 비슷하게 나타납니다.

recursive approach: 13.774s
looping approach: 3.138s
ES6 approach: 2.493s

결론

특정 머신에서 대량의 반복 작업을 수행한 결과, 세 가지 접근 방식 간의 뚜렷한 성능 차이를 확인할 수 있습니다. 재귀 방식은 함수 호출 오버헤드로 인해 가장 느렸고, for 루프와 ES6의 reduce()는 훨씬 빠른 속도를 보였습니다.

결론적으로, 배열에 대한 단순하고 기본적인 연산을 수행할 때는 ES6 함수(reduce() 등)가 다른 어떤 방식보다 효율적이며 성능 면에서도 우수합니다.

팁: 더 정확한 벤치마크 결과를 얻으려면 온라인 IDE가 아닌 로컬 환경(Node.js 등)에서 테스트하는 것이 좋습니다.