JavaScript

JavaScript 배열 기초 정리: 핵심 개념부터 유용한 메서드까지

Chrysans 2025. 3. 6. 11:43
728x90
반응형

자바스크립트 배열 구조 다이어그램 - 인덱스 0부터 5까지와 해당 요소(2, 4, 10, 5, 15, 3)를 보여주는 시각적 표현

 

JavaScript 배열 기초 정리: 핵심 개념부터 유용한 메서드까지

안녕하세요! 오늘은 자바스크립트에서 가장 많이 사용되는 데이터 구조 중 하나인 배열(Array)에 대해 심도 있게 다뤄보려고 합니다. 웹 개발을 하다 보면 배열을 다루지 않는 날이 없을 정도로 자주 사용하게 되는데, 이 강력한 도구를 제대로 이해하고 활용한다면 코드의 품질과 성능이 크게 향상될 수 있습니다.

이 글에서는 자바스크립트 배열의 기본 개념부터 시작해 실무에서 바로 활용할 수 있는 다양한 메서드, 최신 ES6+ 문법을 활용한 테크닉등을 다룰 예정입니다. 


목차

  1. 자바스크립트 배열 기초
  2. 배열 생성 방법
  3. 기본 배열 메서드
  4. ES6+ 배열 메서드
  5. 배열과 함수형 프로그래밍
  6. 배열 성능 최적화
  7. 실무 응용 사례
  8. 마무리

 

자바스크립트 배열 기초

 

자바스크립트의 배열은 다른 프로그래밍 언어와 비교하면 독특한 특성을 갖고 있습니다. 자바스크립트 배열은 실제로는 특수한 객체이며, 인덱스를 키로 사용하는 해시 테이블과 유사합니다. 이런 특성 때문에 자바스크립트 배열은 다음과 같은 특징을 갖습니다:

  • 다양한 데이터 타입을 하나의 배열에 저장할 수 있습니다.
  • 동적으로 크기가 조절됩니다.
  • 배열 요소는 연속적인 메모리 공간에 저장되지 않을 수 있습니다.
  • 숫자가 아닌 키도 사용할 수 있습니다(권장하지는 않음).
// 다양한 타입을 포함하는 배열
const mixedArray = [1, "Hello", true, { name: "John" }, [1, 2, 3]];
console.log(mixedArray); // [1, "Hello", true, {name: "John"}, [1, 2, 3]]

 

 


 

배열 생성 방법

자바스크립트에서 배열을 생성하는 방법은 여러 가지가 있습니다. 가장 일반적인 방법부터 살펴보겠습니다.

1. 배열 리터럴

가장 간단하고 일반적인 방법으로, 대괄호([])를 사용합니다.

const fruits = ["Apple", "Banana", "Cherry"];

2. Array 생성자

Array() 생성자를 사용하여 배열을 만들 수 있습니다.

const numbers = new Array(1, 2, 3, 4, 5);
console.log(numbers); // [1, 2, 3, 4, 5]

// 주의: 인자가 하나의 숫자인 경우 배열의 길이로 해석됩니다
const emptySlots = new Array(5);
console.log(emptySlots); // [empty × 5]

3. Array.of()

ES6에서 도입된 메서드로, Array 생성자의 혼란스러운 동작을 방지합니다.

const numbers = Array.of(5); // [5] (단일 요소 배열)
const mixedArray = Array.of(1, "two", true);
console.log(mixedArray); // [1, "two", true]

4. Array.from()

이터러블 객체나 유사 배열 객체로부터 새 배열을 만듭니다.

// 문자열에서 배열 생성
const charArray = Array.from("Hello");
console.log(charArray); // ["H", "e", "l", "l", "o"]

// 두 번째 인자로 매핑 함수 사용
const numbers = Array.from([1, 2, 3], x => x * 2);
console.log(numbers); // [2, 4, 6]

// DOM 노드 리스트를 배열로 변환 (실제 DOM이 있을 경우)
const divs = Array.from(document.querySelectorAll('div'));

 

 


 

기본 배열 메서드

 

자바스크립트 배열에는 다양한 내장 메서드가 있어 배열을 쉽게 조작할 수 있습니다. 가장 많이 사용되는 메서드부터 살펴보겠습니다.

배열 요소 추가/제거 메서드

push()

배열 끝에 하나 이상의 요소를 추가하고, 새 배열 길이를 반환합니다.

const fruits = ["Apple", "Banana"];
const newLength = fruits.push("Cherry", "Date");
console.log(fruits); // ["Apple", "Banana", "Cherry", "Date"]
console.log(newLength); // 4

pop()

배열 끝에서 요소를 제거하고 그 요소를 반환합니다.

const fruits = ["Apple", "Banana", "Cherry"];
const lastFruit = fruits.pop();
console.log(fruits); // ["Apple", "Banana"]
console.log(lastFruit); // "Cherry"

unshift()

배열 앞에 하나 이상의 요소를 추가하고, 새 배열 길이를 반환합니다.

const fruits = ["Banana", "Cherry"];
const newLength = fruits.unshift("Apple");
console.log(fruits); // ["Apple", "Banana", "Cherry"]
console.log(newLength); // 3

shift()

배열 앞에서 요소를 제거하고 그 요소를 반환합니다.

const fruits = ["Apple", "Banana", "Cherry"];
const firstFruit = fruits.shift();
console.log(fruits); // ["Banana", "Cherry"]
console.log(firstFruit); // "Apple"

splice()

배열의 요소를 추가, 제거 또는 교체합니다.

const fruits = ["Apple", "Banana", "Cherry", "Date"];

// 인덱스 1부터 2개 요소 제거
const removed = fruits.splice(1, 2);
console.log(fruits); // ["Apple", "Date"]
console.log(removed); // ["Banana", "Cherry"]

// 인덱스 1에 새 요소 추가
fruits.splice(1, 0, "Banana", "Cherry");
console.log(fruits); // ["Apple", "Banana", "Cherry", "Date"]

// 인덱스 2의 요소를 다른 요소로 교체
fruits.splice(2, 1, "Elderberry");
console.log(fruits); // ["Apple", "Banana", "Elderberry", "Date"]

배열 탐색 메서드

indexOf()

배열에서 지정된 요소를 찾아 첫 번째 인덱스를 반환합니다. 요소가 없으면 -1을 반환합니다.

const fruits = ["Apple", "Banana", "Cherry", "Banana"];
console.log(fruits.indexOf("Banana")); // 1
console.log(fruits.indexOf("Grape")); // -1

lastIndexOf()

배열에서 지정된 요소의 마지막 인덱스를 반환합니다.

const fruits = ["Apple", "Banana", "Cherry", "Banana"];
console.log(fruits.lastIndexOf("Banana")); // 3

includes()

배열에 특정 요소가 포함되어 있는지 확인합니다(ES7).

const fruits = ["Apple", "Banana", "Cherry"];
console.log(fruits.includes("Banana")); // true
console.log(fruits.includes("Grape")); // false

배열 변환 메서드

slice()

배열의 일부를 새 배열로 추출합니다(원본 배열은 변경되지 않음).

const fruits = ["Apple", "Banana", "Cherry", "Date", "Elderberry"];
const citrus = fruits.slice(1, 3);
console.log(citrus); // ["Banana", "Cherry"]
console.log(fruits); // ["Apple", "Banana", "Cherry", "Date", "Elderberry"] (원본 유지)

concat()

두 개 이상의 배열을 병합하여 새 배열을 만듭니다.

const fruits = ["Apple", "Banana"];
const moreFruits = ["Cherry", "Date"];
const allFruits = fruits.concat(moreFruits, ["Elderberry"]);
console.log(allFruits); // ["Apple", "Banana", "Cherry", "Date", "Elderberry"]
console.log(fruits); // ["Apple", "Banana"] (원본 유지)

join()

배열의 모든 요소를 문자열로 연결합니다.

const fruits = ["Apple", "Banana", "Cherry"];
console.log(fruits.join()); // "Apple,Banana,Cherry"
console.log(fruits.join(" - ")); // "Apple - Banana - Cherry"
console.log(fruits.join("")); // "AppleBananaCherry"

 


 

ES6+ 배열 메서드

 

ES6 이후 자바스크립트에는 더 강력한 배열 메서드들이 추가되었습니다. 이 메서드들은 함수형 프로그래밍 스타일을 지원하며, 코드를 더 간결하고 읽기 쉽게 만들어 줍니다.

map()

배열의 모든 요소에 함수를 적용하고 그 결과로 새 배열을 만듭니다.

const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
console.log(numbers); // [1, 2, 3, 4, 5] (원본 유지)

filter()

조건을 만족하는 요소만 포함하는 새 배열을 만듭니다.

const numbers = [1, 2, 3, 4, 5];
const evenNumbers = numbers.filter(num => num % 2 === 0);
console.log(evenNumbers); // [2, 4]

reduce()

배열의 각 요소에 대해 주어진 리듀서 함수를 실행하고 단일 결과값을 반환합니다.

const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
console.log(sum); // 15

// 객체로 변환하는 예
const fruits = ["Apple", "Banana", "Cherry"];
const fruitObj = fruits.reduce((obj, fruit) => {
  obj[fruit.toLowerCase()] = fruit;
  return obj;
}, {});
console.log(fruitObj); // {apple: "Apple", banana: "Banana", cherry: "Cherry"}

find()

제공된 테스트 함수를 만족하는 첫 번째 요소를 반환합니다.

const users = [
  { id: 1, name: "John" },
  { id: 2, name: "Jane" },
  { id: 3, name: "Jack" }
];
const user = users.find(user => user.id === 2);
console.log(user); // {id: 2, name: "Jane"}

findIndex()

제공된 테스트 함수를 만족하는 첫 번째 요소의 인덱스를 반환합니다.

const users = [
  { id: 1, name: "John" },
  { id: 2, name: "Jane" },
  { id: 3, name: "Jack" }
];
const index = users.findIndex(user => user.name === "Jack");
console.log(index); // 2

some()

배열의 어떤 요소라도 제공된 함수를 통과하는지 테스트합니다.

const numbers = [1, 2, 3, 4, 5];
const hasEven = numbers.some(num => num % 2 === 0);
console.log(hasEven); // true

every()

배열의 모든 요소가 제공된 함수를 통과하는지 테스트합니다.

const numbers = [1, 2, 3, 4, 5];
const allPositive = numbers.every(num => num > 0);
console.log(allPositive); // true

const allEven = numbers.every(num => num % 2 === 0);
console.log(allEven); // false

flat()

중첩 배열을 평탄화합니다(ES2019).

const nestedArray = [1, [2, 3], [4, [5, 6]]];
console.log(nestedArray.flat()); // [1, 2, 3, 4, [5, 6]]
console.log(nestedArray.flat(2)); // [1, 2, 3, 4, 5, 6]

flatMap()

map() 후 결과를 평탄화합니다(ES2019).

const sentences = ["Hello world", "Welcome to JavaScript"];
const words = sentences.flatMap(sentence => sentence.split(" "));
console.log(words); // ["Hello", "world", "Welcome", "to", "JavaScript"]

 


 

배열과 함수형 프로그래밍

 

현대 자바스크립트에서는 배열 메서드를 활용한 함수형 프로그래밍 스타일이 인기를 끌고 있습니다. 다음은 함수형 프로그래밍 스타일을 활용한 몇 가지 일반적인 패턴입니다.

메서드 체이닝

여러 배열 메서드를 연결하여 복잡한 데이터 변환을 간결하게 표현할 수 있습니다.

const products = [
  { id: 1, name: "Laptop", price: 1000, category: "Electronics" },
  { id: 2, name: "Shirt", price: 25, category: "Clothing" },
  { id: 3, name: "Coffee Maker", price: 150, category: "Kitchen" },
  { id: 4, name: "Headphones", price: 80, category: "Electronics" }
];

// 전자제품만 선택하여 가격 할인 후 이름만 추출
const discountedElectronics = products
  .filter(product => product.category === "Electronics")
  .map(product => ({
    ...product,
    price: product.price * 0.9
  }))
  .map(product => product.name);

console.log(discountedElectronics); // ["Laptop", "Headphones"]

파이프라인 패턴

재사용 가능한 함수를 조합하여 데이터 변환 파이프라인을 구축할 수 있습니다.

// 함수 정의
const filterByCategory = category => products => 
  products.filter(product => product.category === category);

const applyDiscount = percentage => products => 
  products.map(product => ({
    ...product,
    price: product.price * (1 - percentage / 100)
  }));

const extractNames = products => 
  products.map(product => product.name);

// 함수 합성
const getDiscountedElectronicsNames = products => 
  extractNames(applyDiscount(10)(filterByCategory("Electronics")(products)));

console.log(getDiscountedElectronicsNames(products)); // ["Laptop", "Headphones"]

 

 


 

배열 성능 최적화

 

대용량 데이터를 다룰 때는 배열 작업의 성능을 고려하는 것이 중요합니다. 다음은 몇 가지 성능 최적화 팁입니다.

1. 적절한 메서드 선택

목적에 맞는 가장 효율적인 메서드를 선택하세요.

const numbers = [1, 2, 3, 4, 5, ...]; // 대용량 배열

// 나쁜 예: forEach와 조건문
let firstEven = null;
numbers.forEach(num => {
  if (firstEven === null && num % 2 === 0) {
    firstEven = num;
  }
});

// 좋은 예: find 사용
const firstEven = numbers.find(num => num % 2 === 0);

2. 불필요한 반복 피하기

여러 작업을 한 번의 반복으로 처리하세요.

const users = [/* 대용량 사용자 데이터 */];

// 나쁜 예: 여러 번 반복
const activeUsers = users.filter(user => user.active);
const activeUserNames = activeUsers.map(user => user.name);

// 좋은 예: 한 번의 반복으로 처리
const activeUserNames = users.reduce((names, user) => {
  if (user.active) {
    names.push(user.name);
  }
  return names;
}, []);

3. 배열 길이 캐싱

반복문에서 배열 길이를 매번 계산하지 마세요.

const arr = [/* 대용량 배열 */];

// 나쁜 예: 매 반복마다 length 계산
for (let i = 0; i < arr.length; i++) {
  // 작업 수행
}

// 좋은 예: length 캐싱
for (let i = 0, len = arr.length; i < len; i++) {
  // 작업 수행
}

4. 희소 배열 피하기

희소 배열(empty slots이 있는 배열)은 성능과 예측 가능성 측면에서 문제가 될 수 있습니다.

// 나쁜 예: 희소 배열 생성
const sparse = new Array(10000);
sparse[0] = 'first';
sparse[9999] = 'last';

// 좋은 예: 필요한 요소만 포함하는 밀집 배열 사용
const dense = ['first', ...필요한 요소들, 'last'];

5. TypedArray 활용하기

수치 데이터를 다룰 때는 TypedArray를 고려하세요.

// 일반 배열 대신
const floats = new Float64Array(1000);
for (let i = 0; i < floats.length; i++) {
  floats[i] = Math.random();
}

 


 

실무 응용 사례

 

실무에서 배열 메서드를 활용하는 몇 가지 일반적인 시나리오를 살펴보겠습니다.

데이터 변환: JSON API 응답 처리

// API에서 받은 사용자 데이터
const apiResponse = [
  { id: 1, name: "John Doe", email: "john@example.com", role: "admin" },
  { id: 2, name: "Jane Smith", email: "jane@example.com", role: "user" },
  { id: 3, name: "Bob Johnson", email: "bob@example.com", role: "user" }
];

// 사용자 인터페이스에 맞게 데이터 변환
const uiData = apiResponse.map(user => ({
  id: user.id,
  displayName: user.name,
  isAdmin: user.role === "admin",
  contactInfo: { email: user.email }
}));

console.log(uiData);
/*
[
  { id: 1, displayName: "John Doe", isAdmin: true, contactInfo: { email: "john@example.com" } },
  { id: 2, displayName: "Jane Smith", isAdmin: false, contactInfo: { email: "jane@example.com" } },
  { id: 3, displayName: "Bob Johnson", isAdmin: false, contactInfo: { email: "bob@example.com" } }
]
*/

복잡한 필터링 및 정렬

// 상품 데이터
const products = [
  { id: 1, name: "Laptop", price: 1200, stock: 15, category: "Electronics" },
  { id: 2, name: "Desktop", price: 1500, stock: 0, category: "Electronics" },
  { id: 3, name: "Phone", price: 800, stock: 7, category: "Electronics" },
  { id: 4, name: "Shirt", price: 25, stock: 20, category: "Clothing" },
  { id: 5, name: "Pants", price: 35, stock: 10, category: "Clothing" }
];

// 재고가 있는 전자제품을 가격 오름차순으로 정렬
const availableElectronics = products
  .filter(product => product.category === "Electronics" && product.stock > 0)
  .sort((a, b) => a.price - b.price);

console.log(availableElectronics);
/*
[
  { id: 3, name: "Phone", price: 800, stock: 7, category: "Electronics" },
  { id: 1, name: "Laptop", price: 1200, stock: 15, category: "Electronics" }
]
*/

데이터 그룹화 및 통계

// 학생 성적 데이터
const students = [
  { name: "Alice", grade: "A", subject: "Math", score: 94 },
  { name: "Bob", grade: "B", subject: "Math", score: 82 },
  { name: "Charlie", grade: "C", subject: "Math", score: 71 },
  { name: "Alice", grade: "A", subject: "Science", score: 90 },
  { name: "Bob", grade: "A", subject: "Science", score: 92 },
  { name: "Charlie", grade: "B", subject: "Science", score: 84 }
];

// 과목별 평균 점수 계산
const subjectAverages = students.reduce((acc, student) => {
  if (!acc[student.subject]) {
    acc[student.subject] = { totalScore: 0, count: 0 };
  }

  acc[student.subject].totalScore += student.score;
  acc[student.subject].count += 1;

  return acc;
}, {});

// 평균 계산 완료
Object.keys(subjectAverages).forEach(subject => {
  subjectAverages[subject].average = 
    subjectAverages[subject].totalScore / subjectAverages[subject].count;
});

console.log(subjectAverages);
/*
{
  Math: { totalScore: 247, count: 3, average: 82.33 },
  Science: { totalScore: 266, count: 3, average: 88.67 }
}
*/

 


 

마무리

자바스크립트 배열과 그 메서드들은 웹 개발에서 데이터를 조작하고 처리하는 데 필수적인 도구입니다. 기본적인 메서드부터 ES6+ 기능, 고급 패턴과 성능 최적화까지, 배열의 다양한 기능을 활용하면 더 효율적이고 유지보수하기 쉬운 코드를 작성할 수 있습니다.

배열은 단순한 데이터 구조 이상의 의미를 가지며, 자바스크립트 생태계에서 가장 강력한 기능 중 하나입니다.

 

 

전문 용어 설명

  • 이터러블(Iterable): 반복 가능한 객체로, for...of 반복문으로 순회할 수 있는 객체입니다. String, Array, Map, Set 등이 여기에 해당합니다.
  • 유사 배열 객체(Array-like Object): 배열처럼 length 속성이 있고 인덱스로 접근할 수 있지만 배열 메서드를 가지고 있지 않은 객체입니다. 예: DOM NodeList, arguments 객체.
  • 희소 배열(Sparse Array): 일부 인덱스에 값이 할당되지 않은 배열로, 'empty' 슬롯이 포함된 배열입니다.
  • 밀집 배열(Dense Array): 모든 인덱스에 값이 할당된 배열입니다.
  • 리듀서(Reducer): 배열의 각 요소에 함수를 적용하여 단일 값으로 줄이는 함수입니다.
  • 함수형 프로그래밍(Functional Programming): 상태 변경을 최소화하고 데이터 변환에 중점을 둔 프로그래밍 패러다임입니다.
  • 메서드 체이닝(Method Chaining): 여러 메서드를 연속적으로 호출하는 프로그래밍 패턴입니다.
  • TypedArray: 바이너리 데이터를 다루기 위한 배열 같은 객체로, 고정된 타입의 요소만 포함할 수 있습니다.

 

주요 배열 메서드

  1. 요소 추가/제거
    • push(): 배열 끝에 요소 추가
    • pop(): 배열 끝의 요소 제거 및 반환
    • unshift(): 배열 앞에 요소 추가
    • shift(): 배열 앞의 요소 제거 및 반환
    • splice(): 요소 추가, 제거, 교체
  2. 순회/변환
    • forEach(): 각 요소에 함수 실행
    • map(): 각 요소를 변환하여 새 배열 생성
    • filter(): 조건에 맞는 요소만 새 배열로 생성
    • reduce(): 배열 요소를 단일 값으로 줄임
    • find(): 조건에 맞는 첫 요소 반환
    • some(): 하나라도 조건에 맞는지 검사
    • every(): 모든 요소가 조건에 맞는지 검사
  3. 정렬/조작
    • sort(): 배열 요소 정렬
    • reverse(): 배열 요소 순서 반전
    • concat(): 여러 배열 결합
    • slice(): 배열 일부분 추출
    • join(): 배열 요소를 문자열로 결합

 

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array

 

Array - JavaScript | MDN

다른 프로그래밍 언어의 배열과 마찬가지로, Array 객체는 여러 항목의 컬렉션을 단일 변수 이름 아래 저장할 수 있고, 일반적인 배열 연산을 수행하기 위한 멤버가 있습니다.

developer.mozilla.org

 

https://ko.javascript.info/array

 

배열

 

ko.javascript.info

 

https://css-tricks.com/an-illustrated-and-musical-guide-to-map-reduce-and-filter-array-methods/

 

An Illustrated (and Musical) Guide to Map, Reduce, and Filter Array Methods | CSS-Tricks

Map, reduce, and filter are three very useful array methods in JavaScript that give developers a ton of power in a short amount of space. Let’s jump right

css-tricks.com

 

728x90
반응형