배열 메서드 총정리 — map, filter, reduce, find, some, every
배열 메서드는 자바스크립트 코딩 테스트와 면접의 단골 주제입니다. 특히
map,filter,reduce는 함수형 프로그래밍의 기본이기도 해서, 동작 원리를 정확히 이해하고 있어야 합니다.
map — 변환
배열의 각 요소를 변환해서 같은 길이의 새 배열 을 반환합니다.
const numbers = [1, 2, 3, 4, 5];
// 각 요소를 두 배로
const doubled = numbers.map((n) => n * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
// 객체 배열에서 특정 필드만 추출
const users = [
{ name: "홍길동", age: 25 },
{ name: "이순신", age: 30 },
];
const names = users.map((user) => user.name);
console.log(names); // ["홍길동", "이순신"]
**주의 **: map은 항상 원본 배열과 같은 길이의 배열을 반환합니다. 필터링이 필요하면 filter를 써야 합니다.
filter — 필터링
조건에 맞는 요소만 모아 ** 새 배열 **을 반환합니다.
const numbers = [1, 2, 3, 4, 5, 6];
// 짝수만 필터링
const evens = numbers.filter((n) => n % 2 === 0);
console.log(evens); // [2, 4, 6]
// falsy 값 제거
const mixed = [0, "hello", "", null, 42, undefined, "world"];
const truthy = mixed.filter(Boolean);
console.log(truthy); // ["hello", 42, "world"]
filter(Boolean) 패턴은 실무에서 정말 자주 쓰이니 기억해두면 좋습니다.
reduce — 누적
배열을 순회하면서 ** 하나의 값으로 축소 **합니다. 가장 범용적이지만 가장 어렵습니다.
const numbers = [1, 2, 3, 4, 5];
// 합계
const sum = numbers.reduce((acc, cur) => acc + cur, 0);
console.log(sum); // 15
// 최댓값
const max = numbers.reduce((acc, cur) => Math.max(acc, cur), -Infinity);
console.log(max); // 5
// 빈도수 세기 — 면접 단골!
const fruits = ["사과", "바나나", "사과", "딸기", "바나나", "사과"];
const count = fruits.reduce((acc, fruit) => {
acc[fruit] = (acc[fruit] || 0) + 1;
return acc;
}, {});
console.log(count); // { 사과: 3, 바나나: 2, 딸기: 1 }
reduce로 map과 filter 구현하기
면접에서 종종 나오는 질문입니다.
// reduce로 map 구현
const mapped = [1, 2, 3].reduce((acc, n) => {
acc.push(n * 2);
return acc;
}, []);
// reduce로 filter 구현
const filtered = [1, 2, 3, 4].reduce((acc, n) => {
if (n % 2 === 0) acc.push(n);
return acc;
}, []);
reduce는 만능이지만, map이나 filter로 충분한 경우에는 그것들을 쓰는 게 가독성이 좋습니다.
find — 첫 번째 매칭 요소
조건에 맞는 첫 번째 요소 를 반환합니다. 없으면 undefined입니다.
const users = [
{ id: 1, name: "홍길동" },
{ id: 2, name: "이순신" },
{ id: 3, name: "김유신" },
];
const user = users.find((u) => u.id === 2);
console.log(user); // { id: 2, name: "이순신" }
// 없는 경우
const notFound = users.find((u) => u.id === 99);
console.log(notFound); // undefined
filter와의 차이: find는 하나만 반환, filter는 배열을 반환합니다.
findIndex
요소 대신 인덱스가 필요하면 findIndex를 사용합니다.
const index = users.findIndex((u) => u.name === "이순신");
console.log(index); // 1
some — 하나라도 만족하는가
배열 요소 중 하나라도 조건을 만족하면 true를 반환합니다.
const ages = [15, 22, 17, 30];
const hasAdult = ages.some((age) => age >= 18);
console.log(hasAdult); // true
// 빈 배열에서 some은 항상 false
console.log([].some(() => true)); // false
every — 모두 만족하는가
배열의 ** 모든 요소 **가 조건을 만족하면 true를 반환합니다.
const ages = [20, 22, 25, 30];
const allAdults = ages.every((age) => age >= 18);
console.log(allAdults); // true
// 빈 배열에서 every는 항상 true (vacuous truth)
console.log([].every(() => false)); // true ← 주의!
[].every(() => false)가 true인 이유는 수학의 "공허한 참(vacuous truth)" 개념 때문입니다. 면접에서 이걸 아는지 물어보는 경우도 있습니다.
메서드 체이닝
실무에서는 이 메서드들을 체이닝해서 사용하는 경우가 많습니다.
const products = [
{ name: "노트북", price: 1200000, inStock: true },
{ name: "키보드", price: 80000, inStock: true },
{ name: "마우스", price: 50000, inStock: false },
{ name: "모니터", price: 350000, inStock: true },
];
// 재고 있는 상품 이름을 가격순으로 정렬
const result = products
.filter((p) => p.inStock)
.sort((a, b) => a.price - b.price)
.map((p) => p.name);
console.log(result); // ["키보드", "모니터", "노트북"]
비교 표
| 메서드 | 반환값 | 용도 | 원본 변경 |
|---|---|---|---|
map | 새 배열 (같은 길이) | 변환 | X |
filter | 새 배열 (같거나 짧음) | 필터링 | X |
reduce | 단일 값 | 누적/집계 | X |
find | 요소 또는 undefined | 검색 | X |
some | boolean | 존재 확인 | X |
every | boolean | 전체 검증 | X |
자주 함께 쓰이는 배열 메서드
// flatMap — map + flat
const sentences = ["Hello World", "Foo Bar"];
const words = sentences.flatMap((s) => s.split(" "));
console.log(words); // ["Hello", "World", "Foo", "Bar"]
// includes — 포함 여부
[1, 2, 3].includes(2); // true
// at — 음수 인덱스
[1, 2, 3].at(-1); // 3 (마지막 요소)
** 기억하기 **:
map은 변환,filter는 필터링,reduce는 누적입니다. 이 세 가지의 차이를 확실히 알고 있으면 코딩 테스트에서 배열 문제를 만났을 때 어떤 메서드를 써야 할지 바로 판단할 수 있습니다.