개요
Array.prototype.reduce는 배열을 하나의 값으로 축약하는 표준 API 배열의 각 요소에 대해 리듀서 함수를 순차 실행하고 누산기 값을 반환 집계, 변환, 그룹핑, 파이프라인 구성 등 다양한 패턴에 사용
구문
arr.reduce(callback[, initialValue])
- callback에 누산 로직 정의
- initialValue가 있으면 누산기의 시작값으로 사용, 없으면 배열의 첫 요소가 시작값
매개변수
- callback(accumulator, currentValue, currentIndex, array)
- accumulator: 누산된 값
- currentValue: 현재 요소 값
- currentIndex: 현재 인덱스
- array: 원본 배열
- initialValue (옵션)
- 누산기의 초기값
- 제공하지 않으면 배열 첫 요소가 초기값이 되어 콜백은 두 번째 요소부터 시작
반환값
- 축약 결과로 얻은 최종 누산값
동작 방식
- 왼쪽에서 오른쪽으로 순회하며 callback을 한 번씩 호출
- initialValue 미제공
- 빈 배열이면 TypeError 발생
- 요소가 하나뿐이면 그 요소를 그대로 반환하며 callback은 호출되지 않음
- initialValue 제공
- 배열이 비어 있어도 initialValue를 그대로 반환하며 callback은 호출되지 않음
- 희소 배열의 빈 슬롯은 건너뜀
- 누산기는 어떤 타입도 가능하며 객체, 맵, 프라미스 등으로 확장 가능
주의 사항과 베스트 프랙티스
- 가능한 항상 initialValue 지정 권장
- 빈 배열 입력 시 예외 방지, 타입 안정성 확보
- 누산기 불변성 유지 권장
- 객체 누산 시 얕은 복사 또는 구조 분해 사용 고려
- 콜백은 순수 함수 지향
- 외부 상태 변경 최소화, 테스트 용이성 확보
- 읽기 어려운 과도한 축약 로직은 map, filter, for…of 등으로 분리 고려
- 희소 배열에서 빈 슬롯은 콜백이 호출되지 않음에 유의
- 오른쪽에서 왼쪽으로 처리해야 하면 reduceRight 사용
간단 예시
합계 계산
[0, 1, 2, 3].reduce((acc, cur) => acc + cur, 0)
초기값의 차이
[].reduce((acc, cur) => acc + cur)→ TypeError[].reduce((acc, cur) => acc + cur, 0)→ 0
빈 슬롯은 건너뜀
[1, , 3].reduce((acc, cur) => acc + cur, 0) // 4
객체 배열 합계
items.reduce((sum, it) => sum + it.value, 0)
중첩 배열 평탄화
nested.reduce((acc, cur) => acc.concat(cur), [])
빈도수 집계
names.reduce((m, n) => ((m[n] = (m[n] || 0) + 1), m), {})
프라미스 순차 실행
fns.reduce((p, fn) => p.then(fn), Promise.resolve(input))
map을 reduce로 구현 가능하지만 가독성 저하 가능
arr.reduce((res, v, i, a) => (res[i] = fn(v, i, a), res), [])
동작 예시 해설
초기값 없이 합계 계산 시 첫 요소가 누산기가 되고 두 번째 요소부터 콜백 실행
[0, 1, 2, 3, 4].reduce((acc, cur) => acc + cur)의 호출 순서 개념
- 1회차 acc=0, cur=1 → 1
- 2회차 acc=1, cur=2 → 3
- 3회차 acc=3, cur=3 → 6
- 4회차 acc=6, cur=4 → 10 최종 반환값 10
초기값을 10으로 주면 인덱스 0부터 시작하여 5회 호출되고 최종 20 반환
에지 케이스 체크리스트
- 빈 배열 + initialValue 미지정 → TypeError
- 단일 요소 배열 + initialValue 미지정 → 콜백 미호출, 단일 요소 반환
- 빈 배열 + initialValue 지정 → 콜백 미호출, initialValue 반환
- 희소 배열의 빈 슬롯은 미호출
- 누산기가 참조 타입일 때 의도치 않은 공유/변경 주의
성능 팁
- 불필요한 배열 복사 최소화 전략 설계
- 평탄화 시 concat보다 push + 전개 연산자 혼용 비용 고려
- 대규모 데이터 처리 시 순수 반복문 대비 오버헤드 존재 가능
- 가독성과 유지보수 이점을 우선하되, 병목 구간은 프로파일링 후 대체 고려
함께 보면 좋은 API
- reduceRight: 오른쪽에서 왼쪽으로 축약
- map, filter: 전처리 또는 필터링과 조합하여 파이프라인 구성 용이
- Set, Array.from: 중복 제거 시 대안
마무리
reduce는 배열을 하나의 값으로 축약하는 범용 도구 initialValue 지정과 콜백의 순수성 확보가 안전한 사용의 핵심 읽기 쉬운 축약 로직과 타입 일관성을 유지하면 대부분의 집계·변환 문제를 간결하게 해결 가능