ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JavaScript] 자바스크립트 reduce 메서드 이해하기
    프로그래밍 이야기/JavaScript 공부 2021. 5. 5. 19:35

    Reduce 메서드란?

    영한사전에서 reduce는 줄이다.라는 의미로 해석된다.

    배열의 요소들을 하나씩 줄여가면서 연산하기 때문일까, 다양한 배열의 값들이 하나의 값으로 줄기 때문일까..?

    reduce 메서드는 map, forEach와 비슷하게 배열의 요소들을 순회하면서 반복적인 연산을 하는 메서드이지만, map과 forEach와는 조금 다른 부분들이 있다.

     

    문법

    // reduce
    const numbers = [1, 2, 3, 4];
    
    numbers.reduce((누산값, 현재요소값, 현재요소의index, 현재배열) => {
      return 다음누산값;
    }, 초기누산값);

    reduce 메서드는 위 코드와 같이 두 개의 파라미터를 가지고 있다.

    1. 콜백 함수

    첫 번째는 map과 forEach처럼 콜백 함수를 전달받는데, 이 콜백 함수의 파라미터가 map, forEach와 조금 다르다.

    reduce 메서드가 특별한 이유는 바로 이 콜백 함수의 첫 번째 파라미터인데, reduce 메서드에서 이 콜백 함수가 동작할 때 return 하는 값이 다음 콜백 함수의 첫 번째 파라미터로 전달되는 것이다.

    그러고 나서 마지막 콜백 함수가 동작한 이후의 return 값이 reduce 메서드의 return 값이 되는 것이다.

    나머지 2,3,4번째 파라미터는 map, forEach 메소드의 1,2,3번째 파라미터와 역할이 동일하다.

    그렇기 때문에 콜백 함수의 파라미터 생략은, 3,4번째 파라미터만 가능하다.

     

    2. 초기(누산) 값

    reduce 메서드의 두 번째 파라미터는 초기값이다. 콜백함수가 동작하면서 해당 함수의 리턴값이 다음 콜백함수의 첫번째 파라미터로 전달되는데, 이 원리대로라면 가장 첫 번째 동작하는 콜백함수의 첫 번째 파라미터는 전달 받는 값이 없다.

    그래서 reduce 메서드의 이 두번째 파라미터에, 첫 번째 콜백함수에서 동작할 누산값을 전달해 주는 것이다.

    그럼 직접 동작하는 코드로 정리해보자.

     

    예시 코드

    const numbers = [1, 2, 3, 4];
    
    const sum = numbers.reduce((acc, el, i) => {
      console.log(`${i}번째 콜백함수`)
      console.log(`acc: ${acc}`);
      console.log(`el: ${el}`);
    
      return el + acc;
    }, 0);
    
    console.log(`-----------`);
    console.log(`sum: ${sum}`);
    

    가장 간단하고 대표적인 reduce 예시는 다음과 같은 배열의 요소를 더하는 것이다.

    위 코드와 콘솔에 출력된 결과를 함께 보니 훨씬 더 reudce 메소드의 동작원리가 잘 드러나는 것 같다.

     

    응용

    reduce의 동작을 설명하기 가장 간단하고 쉬운 것이 요소 값 더하기지만, 사실 reduce의 두 파라미터(콜백 함수, 초기값)를 잘 활용하면, 다양하게 활용할 수가 있다. 

    const votes = ['엄마', '아빠', '아빠', '아빠', '엄마',
       '엄빠', '아마', '아마', '엄빠', '엄마', '아빠'];
    
    const result = votes.reduce((acc, el, i) => {
      console.log(`${i}번째 콜백함수`)
      console.log(`acc:`, acc);
      console.log(`el:`, el);
    
      acc[el] = (acc[el] || 0) + 1;
    
      return acc;
    }, {});
    
    console.log('---------------')
    console.log('result:', result);

    위 코드처럼 초기값을 빈 객체로 두고, 배열을 돌면서 중복된 요소를 카운트하는 데에도 충분히 활용할 수가 있다.

     

    참고

    참고로 reduce 메서드에서 초기값이라 불리는 두 번째 파라미터는 생략이 가능하다.

    만약 두번째 파라미터를 생략하고 콜백 함수만 전달할 경우, 배열의 첫 번째 요소(0번 index)가 초기값이 되어 동작하게 된다.

    const numbers = [1, 2, 3, 4];
    
    const sum = numbers.reduce((acc, el, i) => {
      console.log(`${i}번째 콜백함수`)
      console.log(`acc: ${acc}`);
      console.log(`el: ${el}`);
    
      return el + acc;
    });
    
    console.log(`-----------`);
    console.log(`sum: ${sum}`);
    

    단, 방금 설명한 것처럼 0번 index가 초기값이 되기 때문에, 콘솔에 출력된 결과처럼 0번째 콜백 함수는 동작하지 않게 되는 현상이 발생한다. 

    다시 말해, "배열의 길이 - 1"만큼 콜백 함수가 동작하는 것이다. 이래나 저래나 결과가 똑같다면 상관없겠지만 콜백 함수의 동작 횟수에 따라 결과에 차이가 있을법한 경우라면 오류로 이어질 수 있기 때문에, 생략은 가능하지만 생략하지 않는 것이 권장된다.

     

    참고 2

    배열의 요소를 반대방향으로 순회하는 reduceRight라는 메서드도 있다.

    const numbers = [1, 2, 3, 4];
    
    const sum = numbers.reduceRight((acc, el, i) => {
      console.log(`index: ${i}`)
      console.log(`acc: ${acc}`);
      console.log(`el: ${el}`);
    
      return el + acc;
    }, 0);
    
    console.log(`-----------`);
    console.log(`sum: ${sum}`);
    
    

     

    마무리

    reduce 메서드는 현재 콜백 함수의 리턴값이 다음 콜백함수의 동작에 영향을 끼칠 수 있는 독특한 동작 방식을 가진 메서드이다. 

    reduce 메서드가 꼭 필요한 경우가 흔치 않을 수도 있겠지만, 꼭 필요한 경우가 아니더라도 다양한 상황에서 유용하게 활용될 수 있을 것 같다.

    댓글

Designed by BigTop.