자바스크립트 배열 메서드 중에서도 가장 강력한 메서드를 뽑으라면, 단연 reduce()를 꼽을 수 있습니다.
하지만 범용적으로 쓰일 수 있는 만큼 이해하기도 쉽지 않아서 많은 초보 개발자들이 어려움을 겪곤 합니다.
이번 글에서는 reduce() 메서드의 기본 사용법과 실전 활용법을 쉽게 설명해보겠습니다.
reduce() 기본 사용법
reduce() 메서드는 배열의 각 요소에 대해 콜백 함수를 실행하여 누적된 하나의 결과값을 반환합니다.
기본 문법은 다음과 같습니다:
array.reduce(<콜백 함수>, <초기값>);
콜백 함수에는 총 4개의 인자가 전달됩니다:
- accumulator: 이전 요소에서 누적된 결과값
- currentValue: 현재 요소의 값
- currentIndex: 현재 요소의 인덱스 (선택사항)
- array: reduce()를 호출한 배열 자체 (선택사항)
대부분의 경우 첫 두 개의 인자만 사용되지만, 필요한 경우 나머지 인자를 활용하여 더 복잡한 연산을 수행할 수 있습니다.
초기값은 누적 계산을 시작할 때의 기본값입니다.
이를 설정하지 않으면 배열의 첫 번째 요소가 초기값으로 사용됩니다. 만약 초기값을 설정하지 않고 빈 배열에 대해 reduce()를 호출하게 되면 오류가 발생하므로 주의가 필요합니다.
reduce() 메서드로 누적 계산하기
가장 간단한 예시는 배열의 모든 숫자를 더하는 것입니다.
const numbers = [2, 4, 3, 1];
const sum = numbers.reduce((acc, num) => acc + num, 0); // 초기값을 0으로 설정하여 모든 요소를 더함
console.log(sum); // 10
여기서 acc는 누적자(Accumulator)로, 이전의 계산 결과를 가지고 있습니다. num은 현재 요소의 값을 의미합니다.
이 함수는 배열의 모든 요소를 순회하며 누적 계산을 수행합니다.
위의 코드는 reduce() 메서드를 사용하지 않고 반복문으로 작성할 수도 있지만, 코드가 더 장황해집니다
const numbers = [2, 4, 3, 1];
let sum = 0; // 합을 저장할 변수
for (const num of numbers) {
sum += num; // 각 요소를 누적해서 더함
}
console.log(sum); // 10
reduce()를 사용하면, sum 변수를 const로 선언하여 값의 변경을 방지할 수 있기 때문에 더 견고한 코드를 작성할 수 있습니다.
최소값과 최대값 찾기
reduce()는 최소값이나 최대값을 찾는 데도 사용할 수 있습니다. 각 요소를 순회하면서 조건에 따라 누적값을 갱신합니다.
const numbers = [2, 4, 3, 1];
const min = numbers.reduce((min, num) => (min < num ? min : num), Number.MAX_VALUE); // 초기값을 Number.MAX_VALUE로 설정
console.log(min); // 1
const max = numbers.reduce((max, num) => (max > num ? max : num), Number.MIN_VALUE); // 초기값을 Number.MIN_VALUE로 설정
console.log(max); // 4
초기값을 지정하지 않으면 배열의 첫 번째 값이 기본값으로 사용됩니다. 만약 빈 배열에 reduce()를 사용하려 한다면 오류가 발생하므로 항상 초기값을 설정하는 습관을 가지는 것이 좋습니다.
객체의 개수 세기
reduce()는 배열 내 각 원소의 개수를 세는 데도 유용하게 사용됩니다. 예를 들어, 과일의 개수를 세어보겠습니다:
const fruits = ["apple", "banana", "apple", "orange", "banana", "apple"];
const fruitCounts = fruits.reduce((counter, fruit) => {
// 객체에서 해당 과일이 이미 존재하는지 확인하고 존재하면 1을 더하고, 그렇지 않으면 1로 초기화
counter[fruit] = (counter[fruit] || 0) + 1;
return counter;
}, {}); // 초기값을 빈 객체로 설정하여 각 과일의 개수를 세기 시작함
console.log(fruitCounts); // { apple: 3, banana: 2, orange: 1 }
위 코드에서는 객체를 사용하여 각 과일의 개수를 저장하고 있습니다.
counter[fruit] = (counter[fruit] || 0) + 1을 통해 이미 존재하는 키는 값을 증가시키고, 없는 키는 1로 초기화하는 방식입니다.
배열 평탄화
reduce()를 사용하여 2차원 배열을 1차원 배열로 평탄화(flatten) 할 수 있습니다. 이는 중첩된 배열 구조를 단순화하는 데 유용합니다.
const nested = [
[1, 2],
[3, 4],
[5, 6]
];
const flattened = nested.reduce((acc, val) => acc.concat(val), []); // 초기값을 빈 배열로 설정하여 중첩 배열을 합침
console.log(flattened); // [1, 2, 3, 4, 5, 6]
여기서는 concat()을 사용해 각 내부 배열을 누적 배열에 합쳐서 평탄화하고 있습니다.
최신 자바스크립트에서는 flat() 메서드를 사용해 더 간단하게 해결할 수도 있지만, reduce()를 사용하면
더욱 구체적인 컨트롤이 가능합니다.
데이터 그룹화
reduce()를 사용하면 데이터를 특정 기준으로 그룹화할 수 있습니다. 예를 들어, 사용자 배열을 국가별로 그룹화해보겠습니다:
const users = [
{ name: "John", age: 25, country: "US" },
{ name: "Jane", age: 30, country: "KR" },
{ name: "Robin", age: 22, country: "CA" },
{ name: "Doe", age: 13, country: "US" },
{ name: "Smith", age: 20, country: "KR" }
];
const usersByCountry = users.reduce((acc, user) => {
const country = user.country;
// 해당 국가가 아직 누적 객체에 없으면 빈 배열로 초기화
if (!acc[country]) {
acc[country] = [];
}
// 해당 국가 배열에 사용자 추가
acc[country].push(user);
return acc;
}, {}); // 초기값을 빈 객체로 설정하여 각 국가별 사용자 그룹화 시작
console.log(usersByCountry);
출력 결과는 다음과 같이 국가별로 사용자 목록을 나눈 객체가 됩니다
{
US: [
{ name: "John", age: 25, country: "US" },
{ name: "Doe", age: 13, country: "US" }
],
KR: [
{ name: "Jane", age: 30, country: "KR" },
{ name: "Smith", age: 20, country: "KR" }
],
CA: [
{ name: "Robin", age: 22, country: "CA" }
]
}
이 예제에서는 사용자 객체의 country 속성을 기준으로 사용자들을 그룹화하고 있습니다. 초기값으로 빈 객체 {}를 설정하여 결과를 축적합니다.
원소 분류하기
특정 조건에 따라 배열의 요소를 여러 범주로 분류하고 싶을 때도 reduce()를 사용할 수 있습니다. 예를 들어 짝수와 홀수로 숫자 배열을 나누어보겠습니다
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const groupedNumbers = numbers.reduce(
(acc, num) => {
// 숫자가 짝수인지 확인하고 해당 배열에 추가
if (num % 2 === 0) {
acc.even.push(num);
} else {
acc.odd.push(num);
}
return acc;
},
{ even: [], odd: [] } // 초기값으로 짝수와 홀수 배열을 각각 빈 배열로 설정
);
console.log(groupedNumbers); // { even: [2, 4, 6, 8], odd: [1, 3, 5, 7, 9] }
이 예제에서는 초기값으로 { even: [], odd: [] } 객체를 사용하여, reduce()를 통해 짝수와 홀수를 각각의 배열에 추가하고 있습니다.
마무리하며
지금까지 reduce() 메서드의 기본 사용법과 다양한 활용 사례를 살펴보았습니다.
reduce()는 매우 강력한 도구지만, 코드가 복잡해질 수 있으므로 꼭 필요한 경우에 사용하는 것이 좋습니다.
특히, reduce()를 남용하면 오히려 가독성을 해칠 수 있기 때문에, 적절한 상황에서만 사용하는 것이 중요합니다.
처음에는 헷갈리겠지만, 여러 번 사용해보면서 익숙해지면 다양한 문제를 효과적으로 해결할 수 있는 도구가 될 것입니다.
댓글