728x90
자바스크립트 reduce() 함수 완벽 가이드
목차
개요
reduce()
메서드는 배열의 각 요소에 대해 주어진 리듀서(reducer) 함수를 실행하고, 하나의 결과값을 반환합니다. 배열을 기반으로 계산된 단일 값을 도출할 때 매우 유용한 함수형 프로그래밍 도구입니다.
기본 문법
array.reduce(callback(accumulator, currentValue[, currentIndex[, array]])[, initialValue])
매개변수 설명
callback
: 리듀서 함수accumulator
: 누산기. 콜백의 반환값을 누적currentValue
: 처리할 현재 요소currentIndex
: 처리할 현재 요소의 인덱스 (선택적)array
: reduce를 호출한 배열 (선택적)
initialValue
: 초기값 (선택적이지만 권장됨)
기본 예제
const numbers = [1, 2, 3, 4, 5];
// 배열의 모든 숫자 합산
const sum = numbers.reduce((acc, curr) => acc + curr, 0);
console.log(sum); // 15
// 초기값 없이 사용 (권장하지 않음)
const sumWithoutInitial = numbers.reduce((acc, curr) => acc + curr);
console.log(sumWithoutInitial); // 15
동작 원리
초기값이 있는 경우
const numbers = [1, 2, 3];
const result = numbers.reduce((acc, curr) => {
console.log(`누산값: ${acc}, 현재값: ${curr}`);
return acc + curr;
}, 0);
// 실행 로그:
// 누산값: 0, 현재값: 1
// 누산값: 1, 현재값: 2
// 누산값: 3, 현재값: 3
// 최종 결과: 6
초기값이 없는 경우
const numbers = [1, 2, 3];
const result = numbers.reduce((acc, curr) => {
console.log(`누산값: ${acc}, 현재값: ${curr}`);
return acc + curr;
});
// 실행 로그:
// 누산값: 1, 현재값: 2
// 누산값: 3, 현재값: 3
// 최종 결과: 6
기본 활용 예제
배열의 최대/최소값 찾기
const numbers = [5, 2, 9, 1, 7, 6, 3];
const max = numbers.reduce((acc, curr) => Math.max(acc, curr));
console.log(max); // 9
const min = numbers.reduce((acc, curr) => Math.min(acc, curr));
console.log(min); // 1
객체 배열 합산
const orders = [
{ product: '노트북', price: 1200000, quantity: 1 },
{ product: '마우스', price: 50000, quantity: 2 },
{ product: '키보드', price: 150000, quantity: 1 }
];
const totalAmount = orders.reduce((acc, curr) =>
acc + (curr.price * curr.quantity), 0
);
console.log(totalAmount); // 1450000
배열을 객체로 변환
const fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple'];
const fruitCount = fruits.reduce((acc, curr) => {
acc[curr] = (acc[curr] || 0) + 1;
return acc;
}, {});
console.log(fruitCount);
// { apple: 3, banana: 2, orange: 1 }
고급 활용 예제
중첩 배열 평탄화
const nestedArray = [[1, 2], [3, 4], [5, 6]];
const flattened = nestedArray.reduce((acc, curr) =>
acc.concat(curr), []
);
console.log(flattened); // [1, 2, 3, 4, 5, 6]
Promise 체이닝
const asyncTasks = [
() => Promise.resolve(1),
(a) => Promise.resolve(a + 2),
(a) => Promise.resolve(a + 3)
];
async function executeSequentially() {
const result = await asyncTasks.reduce(async (promise, task) => {
const accumulator = await promise;
return task(accumulator);
}, Promise.resolve(0));
return result;
}
executeSequentially().then(console.log); // 6
복잡한 데이터 구조 변환
const users = [
{ id: 1, name: '김철수', skills: ['JavaScript', 'React'] },
{ id: 2, name: '이영희', skills: ['Python', 'Django'] },
{ id: 3, name: '박지성', skills: ['JavaScript', 'Node.js'] }
];
const skillMap = users.reduce((acc, user) => {
user.skills.forEach(skill => {
if (!acc[skill]) {
acc[skill] = [];
}
acc[skill].push(user.name);
});
return acc;
}, {});
console.log(skillMap);
// {
// JavaScript: ['김철수', '박지성'],
// React: ['김철수'],
// Python: ['이영희'],
// Django: ['이영희'],
// 'Node.js': ['박지성']
// }
728x90
실전 활용 패턴
파이프라인 구현
const pipe = (...functions) =>
functions.reduce((acc, fn) => (...args) => fn(acc(...args)));
// 사용 예시
const add = x => x + 2;
const multiply = x => x * 3;
const divide = x => x / 4;
const compute = pipe(add, multiply, divide);
console.log(compute(5)); // ((5 + 2) * 3) / 4 = 5.25
상태 관리
const initialState = { count: 0, lastUpdated: null };
const actions = [
{ type: 'INCREMENT', payload: 1 },
{ type: 'DECREMENT', payload: 1 },
{ type: 'INCREMENT', payload: 2 }
];
const reducer = (state, action) => {
switch (action.type) {
case 'INCREMENT':
return {
...state,
count: state.count + action.payload,
lastUpdated: new Date()
};
case 'DECREMENT':
return {
...state,
count: state.count - action.payload,
lastUpdated: new Date()
};
default:
return state;
}
};
const finalState = actions.reduce(reducer, initialState);
성능과 주의사항
성능 최적화
// 비효율적인 방법
const numbers = Array.from({ length: 1000000 }, (_, i) => i);
const sum = numbers
.filter(n => n % 2 === 0)
.map(n => n * 2)
.reduce((acc, curr) => acc + curr, 0);
// 효율적인 방법
const optimizedSum = numbers.reduce((acc, curr) => {
if (curr % 2 === 0) {
return acc + (curr * 2);
}
return acc;
}, 0);
주의사항
// 빈 배열에서의 사용
const emptyArray = [];
// 오류 발생
try {
emptyArray.reduce((acc, curr) => acc + curr);
} catch (e) {
console.error('초기값 없이 빈 배열에서 reduce 사용 시 오류 발생');
}
// 안전한 사용
const safeResult = emptyArray.reduce((acc, curr) => acc + curr, 0);
실용적인 레시피
중복 제거
const array = [1, 2, 2, 3, 3, 4, 5, 5];
const unique = array.reduce((acc, curr) => {
if (!acc.includes(curr)) {
acc.push(curr);
}
return acc;
}, []);
console.log(unique); // [1, 2, 3, 4, 5]
그룹화
const people = [
{ age: 25, city: '서울' },
{ age: 30, city: '부산' },
{ age: 25, city: '서울' },
{ age: 35, city: '부산' }
];
const groupByCity = people.reduce((acc, person) => {
const { city } = person;
acc[city] = acc[city] || [];
acc[city].push(person);
return acc;
}, {});
console.log(groupByCity);
// {
// '서울': [{ age: 25, city: '서울' }, { age: 25, city: '서울' }],
// '부산': [{ age: 30, city: '부산' }, { age: 35, city: '부산' }]
// }
데이터 정규화
const normalizeData = (data, key) => {
return data.reduce((acc, item) => {
acc.byId[item[key]] = item;
acc.allIds.push(item[key]);
return acc;
}, {
byId: {},
allIds: []
});
};
const users = [
{ id: 1, name: '김철수' },
{ id: 2, name: '이영희' }
];
const normalized = normalizeData(users, 'id');
console.log(normalized);
// {
// byId: {
// 1: { id: 1, name: '김철수' },
// 2: { id: 2, name: '이영희' }
// },
// allIds: [1, 2]
// }
결론
reduce()
함수는 단순한 배열의 합산을 넘어서 복잡한 데이터 변환, 상태 관리, 비동기 작업 처리 등 다양한 용도로 활용할 수 있는 강력한 도구입니다. 초기값을 적절히 사용하고, 리듀서 함수를 명확하게 작성하면 코드의 가독성과 유지보수성을 크게 향상시킬 수 있습니다.
728x90
'IT 개발 > 자바스크립트' 카테고리의 다른 글
[JAVASCRIPT] 자바스크립트 map() 함수 완벽 가이드 (37) | 2025.02.26 |
---|---|
[JAVASCRIPT] 자바스크립트 filter() 함수 완벽 가이드 (42) | 2025.02.25 |
[JAVASCRIPT] 자바스크립트 비구조화 할당 (Destructuring Assignment) (41) | 2025.02.24 |