第10講

배열 메서드(map/filter/reduce)

5 閲覧 1

map, filter, reduce, forEach, every, some, flatMap 등 배열 고차함수의 동작 원리와 체이닝 패턴을 완전히 이해한다. 실무에서 for문 대신 고차함수를 써야 하는 이유를 익힌다.

고차함수 — 함수를 인수로 받는 함수

고차함수(Higher-Order Function)는 다른 함수를 인수로 받거나 함수를 반환하는 함수입니다. 배열의 고차함수들(map, filter, reduce 등)은 현대 자바스크립트에서 for문을 대체하는 핵심 도구입니다.

고차함수를 쓰면 무엇을 하는가(what)에 집중할 수 있고, 어떻게 하는가(how)를 신경 쓸 필요가 줄어듭니다.

forEach — 각 요소에 작업 수행

const fruits = ["apple", "banana", "cherry"];

fruits.forEach((fruit, index, array) => {
  console.log(index, fruit);
  // 0 "apple", 1 "banana", 2 "cherry"
});

// 반환값 없음 (undefined), break 불가
// 부수 효과(콘솔 출력, DOM 변경)가 목적일 때 사용

map — 변환: 새 배열 생성

const numbers = [1, 2, 3, 4, 5];

// 각 요소를 변환해 새 배열 반환
const doubled = numbers.map(n => n * 2);
// [2, 4, 6, 8, 10]

const squared = numbers.map(n => n ** 2);
// [1, 4, 9, 16, 25]

// 객체 배열 변환
const users = [
  { id: 1, name: "Kim", age: 30 },
  { id: 2, name: "Lee", age: 25 },
];
const names = users.map(u => u.name);
// ["Kim", "Lee"]

const displayUsers = users.map(u => ({
  ...u,
  displayName: `${u.name}(${u.age})`
}));
// [{ id: 1, name: "Kim", age: 30, displayName: "Kim(30)" }, ...]

// index 활용
const indexed = ["a", "b", "c"].map((val, i) => `${i + 1}. ${val}`);
// ["1. a", "2. b", "3. c"]

filter — 걸러내기: 조건에 맞는 요소만

const numbers = [1, 2, 3, 4, 5, 6, 7, 8];

const evens = numbers.filter(n => n % 2 === 0);
// [2, 4, 6, 8]

const odds = numbers.filter(n => n % 2 !== 0);
// [1, 3, 5, 7]

// 객체 배열 필터
const products = [
  { name: "노트북", price: 1200000, inStock: true },
  { name: "마우스", price: 30000, inStock: false },
  { name: "키보드", price: 80000, inStock: true },
];
const available = products.filter(p => p.inStock);
const affordable = products.filter(p => p.price < 100000);

// 중복 제거
const nums = [1, 2, 2, 3, 3, 4];
const unique = nums.filter((n, i, arr) => arr.indexOf(n) === i);
// [1, 2, 3, 4]
// 또는: [...new Set(nums)]

reduce — 집계: 배열을 하나의 값으로

// 기본 구조
array.reduce((누산기, 현재값, 인덱스, 배열) => 새누산기, 초기값)

const numbers = [1, 2, 3, 4, 5];

// 합계
const sum = numbers.reduce((acc, n) => acc + n, 0);
// acc: 0 → 1 → 3 → 6 → 10 → 15

// 최대값
const max = numbers.reduce((acc, n) => n > acc ? n : acc, -Infinity);
// 5

// 빈도 카운트
const words = ["a", "b", "a", "c", "b", "a"];
const freq = words.reduce((acc, w) => {
  acc[w] = (acc[w] ?? 0) + 1;
  return acc;
}, {});
// { a: 3, b: 2, c: 1 }

// 배열을 객체로 변환
const usersById = users.reduce((acc, user) => {
  acc[user.id] = user;
  return acc;
}, {});
// { 1: {id:1, name:"Kim"}, 2: {id:2, name:"Lee"} }

// 중첩 배열 평탄화
const nested = [[1, 2], [3, 4], [5]];
nested.reduce((acc, arr) => acc.concat(arr), []);
// [1, 2, 3, 4, 5]

some과 every — 조건 검사

const numbers = [1, 3, 5, 7, 8];

// some: 하나라도 조건 충족하면 true
numbers.some(n => n % 2 === 0);    // true (8이 있음)
numbers.some(n => n > 100);        // false

// every: 모두 조건 충족해야 true
numbers.every(n => n > 0);         // true
numbers.every(n => n % 2 !== 0);   // false (8이 짝수)

// 실용 예시
const cart = [
  { name: "노트북", inStock: true },
  { name: "마우스", inStock: true },
];
const canCheckout = cart.every(item => item.inStock); // true

flatMap — map + flat 결합

const sentences = ["Hello World", "Foo Bar"];

// map 후 flat
sentences.map(s => s.split(" ")).flat();
// ["Hello", "World", "Foo", "Bar"]

// flatMap으로 한 번에
sentences.flatMap(s => s.split(" "));
// ["Hello", "World", "Foo", "Bar"]

// 조건부 확장
const data = [1, 2, 3, 4];
data.flatMap(n => n % 2 === 0 ? [n, n * 10] : [n]);
// [1, 2, 20, 3, 4, 40]

메서드 체이닝 — 조합의 힘

const transactions = [
  { id: 1, type: "income", amount: 500000 },
  { id: 2, type: "expense", amount: 30000 },
  { id: 3, type: "income", amount: 300000 },
  { id: 4, type: "expense", amount: 80000 },
];

// 수입 합계 계산
const totalIncome = transactions
  .filter(t => t.type === "income")
  .map(t => t.amount)
  .reduce((sum, amount) => sum + amount, 0);
// 800000

// 지출 상위 1개 찾기
const topExpense = transactions
  .filter(t => t.type === "expense")
  .sort((a, b) => b.amount - a.amount)
  .at(0);
// { id: 4, type: "expense", amount: 80000 }

for문 vs 고차함수 선택 기준

// 고차함수 사용 (권장):
const result = items
  .filter(item => item.active)
  .map(item => item.value)
  .reduce((sum, v) => sum + v, 0);

// for문이 더 나은 경우:
// 1. break/continue가 필요할 때
// 2. async/await와 함께 순서대로 실행할 때
//    → forEach 내 async는 await가 작동 안 함!
for (const item of items) {
  await processItem(item); // 순서 보장
}

관련 검색어  ·  map filter reduce, 자바스크립트 고차함수, 배열 메서드 체이닝, forEach vs map, some every 사용법, flatMap

채용정보
공지사항
인사이트
MY