프론트엔드 개발을 하다 보면 한 번쯤 이런 질문이 떠오릅니다. “reduce랑 map 중에 뭐가 더 빠를까?”
결론부터 말하자면, 일반적인 상황에서는 map이 더 빠르게 동작하는 경우가 많습니다. 다만 이 질문에는 중요한 전제가 하나 빠져 있습니다. 사실 이 둘은 엄밀히 말해 성능 비교의 대상이 아닙니다.
왜 그런지, 그리고 실무에서는 어떤 기준으로 선택해야 하는지 차근차근 풀어보겠습니다.
JavaScript map reduce 차이: 애초에 역할이 다르다
map과 reduce는 모두 배열을 순회하지만, 목적 자체가 다릅니다.
- map: 배열 → 배열 (형태 유지)
- reduce: 배열 → 하나의 값 또는 전혀 다른 구조
이 차이를 무시하고 “뭐가 더 빠르냐”만 따지는 건, 망치와 드라이버를 놓고 무게를 비교하는 것과 비슷합니다.
그럼에도 성능 차이가 나는 이유는 내부 동작 방식에서 찾을 수 있습니다.
map reduce 성능 비교: map이 유리한 이유
map은 매우 단순한 작업을 수행합니다.
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((x) => x * 2);
// [2, 4, 6, 8, 10]
이 과정에서 자바스크립트 엔진은 다음을 명확히 알 수 있습니다.
- 결과 배열의 길이가 미리 정해져 있음
- 각 요소의 변환이 서로 독립적임
- 누적 상태를 유지할 필요가 없음
이런 특성 덕분에 map은 엔진 최적화에 매우 유리한 패턴입니다.
실제로 V8 같은 엔진에서는 이런 반복 패턴을 적극적으로 최적화합니다.
이론적으로는 병렬 처리 가능성도 열려 있고, 예측 실패 가능성도 낮습니다.
reduce 느린 이유: 순차적 의존성의 한계
reduce는 본질적으로 다릅니다.
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((acc, curr) => acc + curr, 0);
// 15
reduce의 핵심은 누적값(accumulator) 입니다.
- 이전 단계 결과가 다음 단계 계산에 영향을 줌
- 각 반복이 순차적으로 연결됨
- 중간 상태를 계속 유지해야 함
이런 구조 때문에 reduce는 map처럼 단순 최적화가 어렵습니다.
병렬 처리도 사실상 불가능하고, 콜백 내부 로직이 복잡해질수록 엔진 입장에서는 예측 비용이 커집니다.
그래서 같은 양의 단순 변환 작업이라면 map이 reduce보다 빠르게 나오는 경우가 많습니다.
map 함수 언제 사용해야 할까
다음 질문이 자연스럽게 이어집니다.
“그럼 실무에서는 언제 map을 써야 할까?”
배열의 형태를 유지하면서 값만 바꿀 때
// 숫자를 문자열로 변환
const strings = [1, 2, 3].map((n) => n.toString());
// 객체 배열에서 특정 속성만 추출
const names = users.map((user) => [user.name](<http://user.name/>));
- 결과는 항상 배열
- 길이도 동일
- 각 요소는 독립적
이 조건에 해당한다면 고민할 필요 없이 map입니다.
reduce 함수 사용 시점은 명확하다
reduce는 “만능 메서드”가 아니라, 의도가 분명할 때 강력한 도구입니다.
하나의 값으로 집계할 때
const total = prices.reduce((sum, price) => sum + price, 0);
배열을 객체나 다른 구조로 변환할 때
const userMap = users.reduce((map, user) => {
map[[user.id](<http://user.id/>)] = user;
return map;
}, {});
조건부 집계나 복합 로직이 필요할 때
const adultCount = people.reduce((count, person) => {
return person.age >= 18 ? count + 1 : count;
}, 0);
이처럼 “배열을 줄인다”는 개념이 맞을 때만 reduce를 쓰는 것이 이상적입니다.
프론트엔드 실무 기준: 성능보다 중요한 것
실무에서 수십만 건 이상의 데이터를 다루지 않는 이상, map과 reduce의 성능 차이는 거의 체감되지 않습니다.
그래서 기준은 단순합니다.
- 명확한 변환 → map
- 집계, 압축, 구조 변경 → reduce
특히 다음 패턴은 피하는 것이 좋습니다.
// ❌ reduce로 map 흉내내기
const doubled = numbers.reduce((arr, n) => {
arr.push(n * 2);
return arr;
}, []);
// ✅ 의도가 드러나는 map
const doubled = numbers.map((n) => n * 2);
성능 최적화를 이유로 가독성을 희생하면, 나중에 유지보수 비용으로 반드시 되돌아옵니다.
결론: 빠른 도구보다 맞는 도구를 선택하자
map이 일반적으로 빠른 것은 사실이지만, 속도보다 중요한 것은 코드의 의도와 역할입니다.
- 배열을 배열로 바꾸는가? → map
- 배열을 요약하거나 다른 구조로 바꾸는가? → reduce
성능이 정말 문제가 되는 시점이라면, 그때는 추측이 아니라 프로파일링으로 판단하면 됩니다.
자주 묻는 질문 (FAQ)
Q1. reduce 하나로 map, filter 다 대체하는 게 좋은 코드일까요?
A. 아닙니다. 가능하다는 것과 좋은 코드인 것은 다릅니다. 의도가 흐려지면 유지보수가 어려워집니다.
Q2. map과 reduce를 체이닝하면 성능이 나쁠까요?
A. 일반적인 데이터 크기에서는 거의 문제되지 않습니다. 가독성이 더 중요합니다.
Q3. 성능이 중요한 경우 어떤 기준으로 선택해야 할까요?
A. 실제 병목 구간에서만 벤치마크와 프로파일링을 통해 판단하는 것이 가장 안전합니다.
map과 reduce의 성능 차이는 존재하지만, 중요한 것은 속도가 아니라 역할입니다.
배열 변환에는 map, 집계와 구조 변경에는 reduce를 선택하는 것이 가장 합리적인 기준입니다.