블로그로 돌아가기
Javascript

javascript map filter reduce 차이와 예제, 성능·사용법 완전 정리

javascript map filter reduce 차이와 각 메서드의 개념, 실무 적용 예제, 성능·안전 주의점을 한글로 정리합니다. 즉시 적용 가능한 코드와 판단 기준표, 체크리스트 포함.

array-methodsmapfilterreduce성능
자바스크립트 map filter reduce 차이를 설명하는 코드와 아이콘이 있는 기술 블로그 썸네일

javascript map filter reduce 차이이 필요한 상황

javascript map filter reduce 차이 문제를 마주하는 실무 개발자는 배열을 변형하거나 필터링하고 집계해야 할 때 가장 적절한 도구를 선택해야 합니다. 이 글에서는 각 메서드의 핵심 개념, 실무 예제, 성능·보안·운영 관점의 주의점, 언제 쓰면 좋은지/피해야 할지, 그리고 바로 적용 가능한 체크리스트를 제공합니다.

javascript map filter reduce 차이 핵심 개념

  • map: 입력 배열의 각 요소를 변환하여 같은 길이의 새 배열을 반환합니다. 부수효과 없이 변환하는 경우 적절합니다.
  • filter: 조건을 만족하는 요소만 골라 새 배열을 만듭니다. 길이는 입력보다 작거나 같을 수 있습니다.
  • reduce: 배열을 하나의 값(또는 객체/배열 등)으로 축약합니다. 초기값(accumulator)을 잘 설정해야 안전합니다.

예제: 간단한 사용법과 차이 비교

아래 코드는 map, filter, reduce 각각의 전형적인 사용 예제입니다.

// 데이터: 사용자 목록 const users = [ { id: 1, name: 'Alice', age: 28, active: true }, { id: 2, name: 'Bob', age: 34, active: false }, { id: 3, name: 'Carol', age: 23, active: true } ]; // map: 이름만 뽑아 새 배열 생성 const names = users.map(u => u.name); // ['Alice','Bob','Carol'] // filter: 활성 사용자만 const activeUsers = users.filter(u => u.active); // [{id:1,...},{id:3,...}] // reduce: 총 연령 합계 const totalAge = users.reduce((acc, u) => acc + u.age, 0); // 85 // 실무: 활성 사용자 이름을 쉼표로 연결 const activeNamesCsv = users .filter(u => u.active) .map(u => u.name) .join(', '); // 'Alice, Carol'

비교표: 언제 어떤 메서드를 선택할까

구분항목1항목2항목3
목적요소 변환 (같은 길이)조건으로 요소 선택배열을 하나의 값으로 축약
반환형배열배열어떤 타입도 가능 (숫자/객체/배열)
부수효과권장하지 않음권장하지 않음가능 (하지만 주의)

javascript map filter reduce 차이 실무 예제: 복합 처리와 가독성

실무에서는 map+filter를 체인으로 사용하거나 reduce 하나로 처리하는 방식이 흔합니다. 가독성과 성능을 균형있게 고려하세요.

예: 주문 목록에서 총 결제 금액(할인 적용, 활성 주문만)

const orders = [ { id:1, amount:100, discount:0.1, status:'paid' }, { id:2, amount:200, discount:0, status:'pending' }, { id:3, amount:50, discount:0.2, status:'paid' } ]; // 방법A: filter -> map -> reduce (가독성 우수) const paidTotalA = orders .filter(o => o.status === 'paid') .map(o => o.amount * (1 - o.discount)) .reduce((s, v) => s + v, 0); // 방법B: reduce로 한 번에 처리 (루프 한 번) const paidTotalB = orders.reduce((sum, o) => { if (o.status !== 'paid') return sum; return sum + o.amount * (1 - o.discount); }, 0); // 선택 기준은 데이터 크기와 가독성, 그리고 중간 배열 생성 비용

언제 쓰면 좋고 언제 피해야 할까

  • map을 쓸 때: 각 요소를 독립적으로 변환하여 동일한 길이 배열을 원할 때. 불변성을 지켜야 할 때.
  • map을 피할 때: 변환 대신 단순 부수효과(콘솔 출력, 외부 상태 변경) 목적이면 forEach나 for문 고려.
  • filter를 쓸 때: 조건에 따라 요소 일부만 골라낼 때.
  • filter를 피할 때: 조건 내부가 무거운 계산이라면 먼저 간단한 전처리로 분기 처리 고려.
  • reduce를 쓸 때: 집계, 누적 객체 생성, 하나의 값으로 축약할 때.
  • reduce를 피할 때: 가독성이 더 중요한 경우(複雑한 reduce는 유지보수 어려움), 단순 변환이나 필터링이면 map/filter가 낫다.

실무 체크리스트

  • 배열 크기와 성능 요구사항을 확인했는가? (수만~수십만 개 이상이면 중간 배열 비용 고려)
  • 부수효과를 사용하지 않는가? (순수 함수 권장)
  • reduce 초기값을 반드시 지정했는가? (특히 빈 배열 대비 안전성)
  • 중간 배열 생성 비용을 줄일 수 있는가? (파이프라인 대신 단일 reduce 고려)
  • 불변성(immutable) 규칙을 지키는가? (원본 배열 수정 금지)

성능·보안·운영 주의점

  • 성능: map/filter는 각각 새 배열을 생성하므로 체인을 많이 사용하면 메모리와 CPU 비용이 늘어납니다. 데이터가 클 경우 reduce 한 번으로 처리하거나 제너레이터/스트리밍 처리 고려.
  • 보안: 사용자 입력을 바로 배열 연산에 사용하면 XSS 등 출력 시 필터링 누락 가능. 출력 직전에 검증/이스케이프 수행.
  • 운영: 대량 데이터 배치 처리 시 Node.js 이벤트 루프 차단을 피하기 위해 동기 연산을 나누거나 워커로 분리.

자주 묻는 질문

Q1: map과 forEach 차이는 뭔가요? A1: map은 변환된 새 배열을 반환하고 순수하게 사용되는 반면, forEach는 반환값이 없고 부수효과(외부 값 변경)에 사용됩니다. 변환 결과가 필요하면 map을 쓰세요.

Q2: reduce를 항상 사용하면 성능이 좋나요? A2: 한 번의 순회로 작업을 끝내면 중간 배열 생성을 줄여 메모리 이점이 있지만, 복잡한 reduce는 가독성과 버그 위험을 높입니다. 데이터 크기와 유지보수성을 고려하세요.

Q3: 체이닝(map.filter.reduce)을 무조건 피해야 하나요? A3: 아니요. 소규모 데이터와 가독성이 중요하다면 체이닝이 좋습니다. 대규모 데이터나 성능 민감 작업에서는 중간 배열을 줄이는 설계가 필요합니다.

Q4: reduce에서 초기값을 안 주면 어떤 문제가 있나요? A4: 초기값을 주지 않으면 배열 첫 요소가 초기 누산값으로 사용되어 빈 배열일 경우 오류가 발생하거나 의도치 않은 타입 변환이 생길 수 있습니다.

정리

  • map은 요소 변환, filter는 요소 선별, reduce는 축약(집계)에 사용
  • 중간 배열 비용과 가독성을 보고 map+filter 체인 vs 단일 reduce 선택
  • reduce 초기값을 항상 설정하고 부수효과는 피할 것
  • 대용량 데이터는 메모리와 이벤트 루프 영향 고려하여 설계
  • 실무 체크리스트로 안전성·성능·유지보수성 점검