← JavaScript 강의 목록으로
⚙️
함수형 · ES6
중급 · 선수: 10_화살표함수

11. 배열 고차함수

`forEach` 는 부수효과(로그, DOM 조작 등)에 쓰고 반환값이 없습니다. `map` 은 새 배열을 반환합니다.

mapfilterreduce고차 함수
소요 시간
약 1.5시간
난이도
📊 중급
선수 조건
🎯 단원 10
결과물
`forEach` 는 부수효과(로그, DOM 조작 등)에 쓰고 반환값이 없습니다. `map` 은 새 배열을 반환합니다.

이 강의에서 배우는 것

  • 1`forEach`, `map`, `filter`, `reduce`, `find`, `some`, `every` 를 구분해서 쓴다.
  • 2콜백의 매개변수 (요소, 인덱스, 배열) 를 안다.
  • 3메서드 체이닝으로 데이터 파이프라인을 만든다.
  • 4원본을 변경하지 않는 함수형 스타일을 선호한다.
  • 5적절한 초기값으로 `reduce` 를 안전하게 사용한다.

소개

`forEach` 는 부수효과(로그, DOM 조작 등)에 쓰고 반환값이 없습니다. `map` 은 새 배열을 반환합니다.

핵심 개념

1. forEach 와 map

`forEach` 는 부수효과(로그, DOM 조작 등)에 쓰고 반환값이 없습니다. `map` 은 새 배열을 반환합니다.

javascript
[1, 2, 3].forEach((x) => console.log(x));
const doubled = [1, 2, 3].map((x) => x * 2); // [2,4,6]

2. filter, find, some, every

조건을 만족하는 요소를 골라냅니다.

javascript
[1,2,3,4].filter((x) => x % 2 === 0); // [2,4]
[1,2,3].find((x) => x > 1);            // 2 (첫 매치)
[1,2,3].some((x) => x > 2);            // true
[1,2,3].every((x) => x > 0);           // true

3. reduce

배열을 하나의 값으로 접습니다. 초기값을 명시하는 습관을 들이세요.

javascript
const sum = [1,2,3,4].reduce((acc, x) => acc + x, 0);
const byLen = ["a","bb","ccc"].reduce((g, w) => {
  (g[w.length] ??= []).push(w);
  return g;
}, {});

4. 체이닝

함수형 파이프라인은 가독성이 뛰어납니다.

javascript
const users = [
  { name: "A", age: 17 },
  { name: "B", age: 22 },
  { name: "C", age: 30 },
];
const result = users
  .filter((u) => u.age >= 18)
  .map((u) => u.name)
  .join(", ");

핵심 예제

파일다루는 내용
`01_map.js`map 으로 변환
`02_filter.js`filter / find
`03_reduce.js`합계, 그룹핑
`04_chain.js`filter → map → reduce 체인

src/01_map.js

javascript
/**
 * map: 변환
 */
"use strict";

const nums = [1, 2, 3, 4];
const squares = nums.map((x) => x * x);
console.log(squares);

const users = [
  { name: "A", age: 20 },
  { name: "B", age: 25 },
];
console.log(users.map((u) => u.name));

src/02_filter.js

javascript
/**
 * filter, find
 */
"use strict";

const nums = [1, 2, 3, 4, 5, 6];
console.log("evens =", nums.filter((x) => x % 2 === 0));

const users = [
  { id: 1, active: false },
  { id: 2, active: true },
  { id: 3, active: true },
];
console.log("first active =", users.find((u) => u.active));
console.log("actives =", users.filter((u) => u.active));

src/03_reduce.js

javascript
/**
 * reduce: 합계, 그룹화
 */
"use strict";

const nums = [1, 2, 3, 4];
const sum = nums.reduce((acc, x) => acc + x, 0);
console.log("sum =", sum);

const words = ["js", "go", "rust", "py", "c"];
const byLen = words.reduce((g, w) => {
  (g[w.length] ??= []).push(w);
  return g;
}, {});
console.log("byLen =", byLen);

src/04_chain.js

javascript
/**
 * 체이닝
 */
"use strict";

const users = [
  { name: "A", age: 17, score: 80 },
  { name: "B", age: 22, score: 95 },
  { name: "C", age: 30, score: 60 },
  { name: "D", age: 25, score: 88 },
];

const avgAdultScore = users
  .filter((u) => u.age >= 18)
  .map((u) => u.score)
  .reduce((acc, s, _i, arr) => acc + s / arr.length, 0);

console.log("avg adult score =", avgAdultScore);

자주 하는 실수

  1. `reduce` 초기값 없이 호출했다가 빈 배열에서 TypeError.
  2. `map` 안에서 부수효과만 쓰고 반환값을 버린다 (`forEach` 가 적합).
  3. `filter` 가 boolean 이 아닌 truthy/falsy 도 통과시키는 것을 잊는다.
  4. 체이닝이 길어지면 성능 걱정 → 보통은 가독성이 우선.
  5. 콜백에서 `return` 누락으로 `undefined` 배열 생성.

FAQ

Q1. for 루프와 성능 차이?

대부분 무시할 만한 차이입니다. 가독성이 우선.

Q2. `flat`, `flatMap` 은?

중첩 배열을 펼치고 변환과 평탄화를 한 번에 합니다.

Q3. `map` 으로 비동기 작업은?

결과가 Promise 배열이 되므로 `Promise.all(arr.map(...))` 패턴을 씁니다.

과제

  • `homework_01.js` — 학생 배열에서 평균 점수를 reduce 로 계산하세요.
  • `homework_02.js` — 상품 배열에서 카테고리별 총액을 구하세요.

homework/README.md

## homework_01.js 학생 배열의 평균 점수를 reduce 로 구하세요.

text
[ { name:"A", score:80 }, { name:"B", score:90 }, { name:"C", score:70 } ]

## homework_02.js 상품 배열에서 카테고리별 총액을 객체로 반환하세요.

text
[ { name:"사과", category:"과일", price:1000 },
  { name:"바나나", category:"과일", price:1500 },
  { name:"우유", category:"유제품", price:2500 } ]
→ { 과일: 2500, 유제품: 2500 }

homework/answer/homework_01.js

javascript
/**
 * 과제 1: 평균 점수
 */
"use strict";

const students = [
  { name: "A", score: 80 },
  { name: "B", score: 90 },
  { name: "C", score: 70 },
];

const avg = students.reduce((acc, s, _i, arr) => acc + s.score / arr.length, 0);
console.log("avg =", avg); // 80

homework/answer/homework_02.js

javascript
/**
 * 과제 2: 카테고리별 총액
 */
"use strict";

const products = [
  { name: "사과", category: "과일", price: 1000 },
  { name: "바나나", category: "과일", price: 1500 },
  { name: "우유", category: "유제품", price: 2500 },
];

const totals = products.reduce((g, p) => {
  g[p.category] = (g[p.category] ?? 0) + p.price;
  return g;
}, {});

console.log(totals); // { 과일: 2500, 유제품: 2500 }

다음 단원

[12_클로저와_스코프](../12_클로저와_스코프/) — 함수와 상태.

예제 코드 / 강의 자료

전체 강의 자료와 예제 코드는 GitHub에서 자유롭게 받아볼 수 있습니다.

GitHub에서 보기 ↗