자바스크립트 교재 · 9편 / 26편

배열 다루기 — push·map·filter·reduce

매일 쓰는 배열 메서드 7개와 함수형 패턴의 기본.

기초읽는 시간 7분2026-05-17
배열이 map filter reduce 를 거쳐 변환되는 흐름 일러스트

배열은 JS 에서 가장 자주 만나는 자료구조입니다. ES5 이전에는 for 루프로 일일이 돌렸지만, 지금은 함수형 메서드 — map·filter·reduce 가 표준. 9편은 매일 쓰게 될 7개를 골라 정리합니다.

변형(mutate) vs 새 배열 — 가장 큰 분기

분류메서드반환
원본 변경 ⚠️push, pop, shift, unshift, splice, sort, reverse변경된 원본 일부 또는 길이
새 배열 ✅map, filter, slice, concat, flat, toSorted(ES2023)새 배열
단일 값find, findIndex, includes, some, every, reduce값/boolean/누적

실수 1번지. React·상태 관리에서는 원본 변경 메서드가 함정입니다. state.push(x) 가 화면 리렌더를 안 일으키죠. 새 배열 메서드나 spread([...arr, x]) 를 쓰세요. ES2023 의 toSorted/toReversed/with 는 sort/reverse 의 불변 버전.

map — 변환

const nums = [1, 2, 3, 4];

// 두 배로
const doubled = nums.map(n => n * 2);    // [2, 4, 6, 8]

// 객체 변환
const users = [{name: "A", age: 30}, {name: "B", age: 25}];
const names = users.map(u => u.name);     // ["A", "B"]

// 인덱스도 받기
nums.map((n, i) => `${i}: ${n}`);         // ["0: 1", "1: 2", ...]

filter — 거르기

nums.filter(n => n > 2);          // [3, 4]
nums.filter(n => n % 2 === 0);    // [2, 4]

// Boolean 필터링 — null/undefined/0/"" 모두 제거
const arr = [1, null, 2, undefined, 3, "", 4, 0];
arr.filter(Boolean);              // [1, 2, 3, 4]

map + filter 체이닝. "변환한 다음 거른다" 가 자주 나옵니다. users.map(u => u.age).filter(a => a >= 18) 같은 패턴. 한 줄로 의도가 보입니다.

reduce — 누적

// 합계
const sum = nums.reduce((acc, n) => acc + n, 0);   // 10

// 최댓값
const max = nums.reduce((acc, n) => n > acc ? n : acc, -Infinity);

// 그룹화 (객체로)
const users = [
  {name: "A", role: "admin"},
  {name: "B", role: "user"},
  {name: "C", role: "admin"},
];
const grouped = users.reduce((acc, u) => {
  (acc[u.role] ??= []).push(u);
  return acc;
}, {});
// { admin: [A, C], user: [B] }

// ES2024: Object.groupBy 가 새로 표준화
const grouped2 = Object.groupBy(users, u => u.role);

reduce 의 함정. 두 번째 인자(초기값) 를 빠뜨리면 첫 원소가 누적값이 되어 인덱스가 1부터 시작. 빈 배열에 reduce 호출하면 TypeError. 항상 초기값을 명시하세요.

find · findIndex · includes — 검색

// 조건 맞는 첫 원소 (없으면 undefined)
users.find(u => u.name === "A");          // {name: "A", ...}
users.findIndex(u => u.name === "A");     // 0
users.findLast(u => u.age > 18);          // 마지막 매치

// 단순 포함 검사
nums.includes(3);                          // true
nums.indexOf(3);                           // 인덱스 또는 -1

// 객체 배열의 includes 는 참조 비교 (안 됨) → find/some 사용

some · every — 논리

nums.some(n => n > 3);       // true (하나라도)
nums.every(n => n > 0);      // true (전부)
[].every(...)                 // true ← 빈 배열은 항상 every == true

spread · 구조 분해 · 배열 복제

// 펴기 (concat 대체)
const a = [1, 2], b = [3, 4];
const c = [...a, ...b];                   // [1,2,3,4]
const d = [0, ...a, 99, ...b];            // [0,1,2,99,3,4]

// 얕은 복제 (push 안전)
const copy = [...nums];

// 구조 분해
const [first, second, ...rest] = nums;    // 1, 2, [3, 4]
const [, , third] = nums;                 // 3 (앞 둘 skip)

// 객체 배열 → 두 그룹
const adults = users.filter(u => u.age >= 18);
const minors = users.filter(u => u.age < 18);
// ES2024 후보: Array.prototype.partition (제안 단계)

flat · flatMap — 중첩 펼치기

[1, [2, 3], [4, [5, 6]]].flat();         // [1,2,3,4,[5,6]]
[1, [2, 3], [4, [5, 6]]].flat(2);        // [1,2,3,4,5,6]
[1, [2, 3], [4, [5, 6]]].flat(Infinity); // 다 펴기

// map + flat 합친 것 (자주 씀)
const tags = ["a,b", "c", "d,e,f"];
tags.flatMap(s => s.split(","));         // ["a","b","c","d","e","f"]

sort — 항상 비교 함수와 함께

// ❌ 인자 없으면 문자열 변환 후 비교
[10, 2, 30, 4].sort();                   // [10, 2, 30, 4] → ["10","2","30","4"] sort
                                          // → [10, 2, 30, 4]  ← 문자열 정렬

// ✅ 비교 함수 명시
[10, 2, 30, 4].sort((a, b) => a - b);    // [2, 4, 10, 30]
[10, 2, 30, 4].sort((a, b) => b - a);    // 내림차순

// 객체 정렬
users.sort((a, b) => a.age - b.age);

// 원본 보존 (ES2023)
const sorted = users.toSorted((a, b) => a.age - b.age);

10편 — 객체 다루기

객체 리터럴·구조 분해·Object.keys/values/entries 의 핵심 패턴.

📚 쉽게 배우는 자바스크립트 교재
이전: 8편 함수 · 현재: 9편 (기초) · 다음 → 10편 객체 · 진행: 9/26

© 2026 주나이테크(주) @JUNAITECH