JavaScript 배열에는 주류 언어 중 가장 풍부한 메서드 API 중 하나가 있습니다. 하지만 대부분의 튜토리얼은 억지스러운 예제로 map과 filter만 가르칩니다 — 배열의 숫자를 두 배로 만들거나 짝수를 필터링하는 예시 — 그리고 나머지는 스스로 알아내도록 남겨둡니다. 실제 프로덕션 코드에서 등장하는 메서드들을 현실적인 데이터: 상품, 주문, 사용자 레코드를 사용해 살펴보겠습니다.
사용할 데이터셋
예제를 현실적으로 유지하기 위해 이 글 전체에서 현실적인 상품 카탈로그를 사용하겠습니다:
const products = [
{ id: 1, name: 'Wireless Keyboard', category: 'electronics', price: 79.99, rating: 4.5, inStock: true },
{ id: 2, name: 'Mechanical Keyboard', category: 'electronics', price: 149.99, rating: 4.8, inStock: true },
{ id: 3, name: 'USB-C Hub', category: 'electronics', price: 49.99, rating: 4.2, inStock: false },
{ id: 4, name: 'Standing Desk', category: 'furniture', price: 499.99, rating: 4.6, inStock: true },
{ id: 5, name: 'Desk Lamp', category: 'furniture', price: 39.99, rating: 4.1, inStock: true },
{ id: 6, name: 'Monitor Arm', category: 'electronics', price: 89.99, rating: 4.7, inStock: false },
];map() — 모든 항목 변환
Array.prototype.map()은 각 요소에 함수를 적용해 새 배열을 만듭니다. UI에 필요한 형식으로 API 응답을 재구성하는 데이터 변환의 핵심 도구입니다:
// Extract just the display data for a product list component
const productCards = products.map(product => ({
id: product.id,
name: product.name,
price: `$${product.price.toFixed(2)}`,
badge: product.inStock ? 'In Stock' : 'Out of Stock',
stars: '★'.repeat(Math.round(product.rating))
}));
// productCards[0] → { id: 1, name: 'Wireless Keyboard', price: '$79.99', badge: 'In Stock', stars: '★★★★★' }
// Apply a discount to all prices
const discounted = products.map(p => ({
...p,
price: parseFloat((p.price * 0.9).toFixed(2)),
originalPrice: p.price
}));map()은 원래 배열을 절대 변경하지 않습니다 — 항상 새 배열을 반환합니다. 그래서 체인으로 연결하기 안전하고, 변환이 목적일 때 for 루프보다 선호해야 합니다.
filter() — 부분 집합 얻기
filter()는 콜백이 true를 반환하는 요소만 포함하는 새 배열을 반환합니다:
const inStockProducts = products.filter(p => p.inStock);
const electronicsOnly = products.filter(p => p.category === 'electronics');
const affordableInStock = products.filter(p => p.inStock && p.price < 100);
// Chain map + filter to get display-ready affordable in-stock electronics
const featuredItems = products
.filter(p => p.inStock && p.rating >= 4.5)
.map(p => ({ id: p.id, name: p.name, price: `$${p.price}` }));reduce() — 만능 칼
Array.prototype.reduce()는 시그니처가 복잡해 보여서 개발자들이 피하는 메서드입니다. 하지만 이해하고 나면 항상 손이 가게 됩니다. 배열을 단일 값으로 "줄입니다" — 그 값은 숫자, 객체, 다른 배열 무엇이든 될 수 있습니다. 현실적인 사용 사례: 배열에서 조회 맵 만들기:
// Group products by category (the pattern that makes reduce click)
const byCategory = products.reduce((acc, product) => {
const cat = product.category;
if (!acc[cat]) acc[cat] = [];
acc[cat].push(product);
return acc;
}, {}); // starting value is an empty object
// byCategory.electronics → [Wireless Keyboard, Mechanical Keyboard, USB-C Hub, Monitor Arm]
// byCategory.furniture → [Standing Desk, Desk Lamp]
// Build an id → product lookup (O(1) access instead of .find() on every render)
const productById = products.reduce((acc, p) => {
acc[p.id] = p;
return acc;
}, {});
const keyboard = productById[2]; // instant lookup
// Calculate total cart value
const cart = [{ productId: 1, qty: 2 }, { productId: 4, qty: 1 }];
const cartTotal = cart.reduce((total, item) => {
const product = productById[item.productId];
return total + (product.price * item.qty);
}, 0);
// 79.99 * 2 + 499.99 * 1 = 659.97reduce()를 사용한다면 더 깔끔한 대안을 고려하세요: products.reduce((sum, p) => sum + p.price, 0)는 간단한 경우에 괜찮습니다. 하지만 그룹핑과 인덱싱에서는 reduce()가 최고입니다.find()와 findIndex() — 첫 번째 일치에서 멈추기
매우 흔한 실수는 항목 하나만 필요할 때 filter()를 사용하는 것입니다. filter()는 항상 전체 배열을 스캔합니다. find()는 일치하는 것을 찾는 즉시 멈춥니다 — 최선의 경우 O(1) vs filter의 O(n):
// ❌ Returns an array, scans everything even after finding a match
const found = products.filter(p => p.id === 3)[0];
// ✅ Returns the item directly, stops at first match
const product = products.find(p => p.id === 3);
// { id: 3, name: 'USB-C Hub', ... }
// findIndex() — gives you the position (useful for updates and deletions)
const idx = products.findIndex(p => p.id === 3);
// Update immutably:
const updated = [
...products.slice(0, idx),
{ ...products[idx], inStock: true },
...products.slice(idx + 1)
];some()과 every() — 불리언 검사
배열 내용에 대해 예/아니오 답이 필요할 때, some()과 every()는 필터링하고 길이를 확인하는 것보다 훨씬 깔끔합니다:
const hasOutOfStock = products.some(p => !p.inStock); // true
const allHighRated = products.every(p => p.rating >= 4.0); // true
const allInStock = products.every(p => p.inStock); // false
// Common pattern: form validation
const formFields = [
{ name: 'email', value: '[email protected]', valid: true },
{ name: 'password', value: '', valid: false },
{ name: 'username', value: 'dev123', valid: true }
];
const isFormValid = formFields.every(field => field.valid); // false
const hasAnyError = formFields.some(field => !field.valid); // trueflat()과 flatMap() — 중첩 배열 처리
API가 중첩 배열을 반환할 때, flat()과 flatMap()이 하나의 레벨로 평탄화합니다. flatMap()은 map 연산이 입력당 0개, 1개, 또는 여러 항목을 생성할 수 있을 때 특히 유용합니다:
// flat() — collapse one level of nesting
const orderLines = [
['Wireless Keyboard', 'USB-C Hub'],
['Standing Desk'],
['Mechanical Keyboard', 'Monitor Arm', 'Desk Lamp']
];
const allItems = orderLines.flat();
// ['Wireless Keyboard', 'USB-C Hub', 'Standing Desk', 'Mechanical Keyboard', ...]
// flatMap() — map + flat in one pass (more efficient than chaining)
const ordersWithTags = [
{ id: 101, items: ['keyboard', 'hub'], tags: ['electronics'] },
{ id: 102, items: ['desk', 'lamp'], tags: ['furniture', 'sale'] },
];
// Get all unique tags across all orders
const allTags = ordersWithTags.flatMap(order => order.tags);
// ['electronics', 'furniture', 'sale']
// Filter-and-extract in one pass with flatMap
const expensiveNames = products.flatMap(p =>
p.price > 100 ? [p.name] : [] // return empty array to skip, or [value] to include
);
// ['Mechanical Keyboard', 'Standing Desk']Array.from() — 배열 유사 객체 변환
Array.from()은 이터러블을 실제 배열로 변환합니다. DOM NodeList, Set, Map, 제너레이터 결과와 함께 자주 사용됩니다:
// Convert a NodeList to an array so you can use .map() and .filter()
const checkboxes = Array.from(document.querySelectorAll('input[type="checkbox"]'));
const checkedValues = checkboxes
.filter(el => el.checked)
.map(el => el.value);
// Deduplicate an array using Set → Array.from
const tags = ['electronics', 'sale', 'electronics', 'new', 'sale'];
const unique = Array.from(new Set(tags));
// ['electronics', 'sale', 'new']
// Create a range (like Python's range())
const range = Array.from({ length: 5 }, (_, i) => i + 1);
// [1, 2, 3, 4, 5]
// Extract Map entries for further processing
const priceMap = new Map(products.map(p => [p.id, p.price]));
const prices = Array.from(priceMap.values()); // [79.99, 149.99, ...]올바른 정렬
기본 sort()는 모든 것을 문자열로 변환합니다. 숫자 정렬이 잘못되고 비ASCII 문자의 문자열 정렬이 깨진다는 의미입니다. 항상 비교 함수를 전달하세요:
// ❌ Default sort — wrong for numbers
[10, 9, 100, 2].sort(); // [10, 100, 2, 9] ← string order
// ✅ Numeric sort
[10, 9, 100, 2].sort((a, b) => a - b); // [2, 9, 10, 100] ascending
[10, 9, 100, 2].sort((a, b) => b - a); // [100, 10, 9, 2] descending
// Sort products by price ascending
const byPrice = [...products].sort((a, b) => a.price - b.price);
// Sort by name — use localeCompare for proper string ordering
const byName = [...products].sort((a, b) =>
a.name.localeCompare(b.name, 'en', { sensitivity: 'base' })
);
// Multi-key sort: category first, then rating descending
const sorted = [...products].sort((a, b) => {
if (a.category !== b.category) return a.category.localeCompare(b.category);
return b.rating - a.rating;
});sort()는 원래 배열을 변경합니다. 원래 순서를 유지해야 한다면 항상 먼저 스프레드하세요 ([...products].sort(...)).Object.groupBy() — ES2024 그룹핑
ES2024 이전에는 배열을 그룹화하기 위해 reduce()를 사용했습니다(앞서 보여준 대로). 이제 내장 메서드가 생겼습니다: Object.groupBy(). 간단한 그룹핑 사례에서 더 깔끔합니다:
// Group products by category — ES2024
const grouped = Object.groupBy(products, p => p.category);
// {
// electronics: [Wireless Keyboard, Mechanical Keyboard, USB-C Hub, Monitor Arm],
// furniture: [Standing Desk, Desk Lamp]
// }
// Group by stock status
const byStock = Object.groupBy(products, p => p.inStock ? 'available' : 'unavailable');
// Group orders by month
const orders = [
{ id: 1, date: new Date('2026-01-15'), total: 129.99 },
{ id: 2, date: new Date('2026-01-22'), total: 49.99 },
{ id: 3, date: new Date('2026-02-05'), total: 89.99 },
];
const byMonth = Object.groupBy(orders, o =>
o.date.toLocaleString('en', { month: 'long', year: 'numeric' })
);Object.groupBy()는 Node.js 21+ 및 2024년 중반 기준 모든 최신 브라우저에서 사용할 수 있습니다. 현재 호환성은 MDN groupBy 참고 문서에서 확인하세요. 오래된 환경에서는 reduce() 패턴이 여전히 동작합니다.
유용한 도구
API에서 가져온 JSON 데이터 배열을 다룰 때 이 도구들이 실제로 시간을 절약해 줍니다: JSON 포맷터로 깊이 중첩된 페이로드를 검사하고, JSON Path로 큰 배열에서 특정 필드를 쿼리하고, JS 포맷터로 메서드 체인 코드를 정리하세요. 전체 MDN 배열 참고 문서는 북마크할 가치가 있습니다 — 대부분의 개발자가 모르는 메서드들이 더 있습니다.
마무리
JavaScript의 배열 메서드는 유틸리티 라이브러리에서 찾던 대부분을 커버합니다. 변환과 부분 집합을 위한 map()과 filter(), 그룹핑과 인덱싱을 위한 reduce(), 조회를 위한 filter()[0] 대신 find(), 한 번에 필터링-변환을 위한 flatMap(), 그리고 현대적인 환경에서 깔끔한 그룹핑을 위한 Object.groupBy(). 핵심은 작업에 맞는 올바른 도구를 사용하는 것 — 그리고 대부분의 루프를 잘 선택한 메서드로 대체할 수 있다는 것을 아는 것입니다.