본문 바로가기

Development/Javascript

모던 자바스크립트 입문 - Chapter 10: 배열의 다양한 기능 💻

안녕하세요! 이번 포스팅에서는 모던 자바스크립트 배열의 다양한 기능에 대해 정리해보겠습니다.

배열은 자바스크립트에서 가장 많이 사용되는 자료구조 중 하나니까 확실히 알아두면 정말 유용해요! 

📌 목차

  • 배열의 메서드
  • 다차원 배열
  • 유사 배열 객체
  • ES6 배열과 새로운 기능

📝 배열의 메서드

배열의 메서드는 크게 원본 배열을 변경하는 메서드새로운 배열을 반환하는 메서드로 나눌 수 있어요.

원본 배열을 변경하는 메서드 (수정 메서드)

push(), pop(), shift(), unshift()

let fruits = ["사과", "바나나"];

// 끝에 추가
fruits.push("오렌지");
console.log(fruits); // ["사과", "바나나", "오렌지"]

// 끝에서 제거
let lastFruit = fruits.pop();
console.log(lastFruit); // "오렌지"
console.log(fruits); // ["사과", "바나나"]

// 앞에서 제거
let firstFruit = fruits.shift();
console.log(firstFruit); // "사과"
console.log(fruits); // ["바나나"]

// 앞에 추가
fruits.unshift("딸기", "키위");
console.log(fruits); // ["딸기", "키위", "바나나"]

splice() - 가장 강력한 배열 조작 메서드

let numbers = [1, 2, 3, 4, 5];

// splice(시작인덱스, 제거할개수, 추가할요소들...)

// 요소 제거
let removed = numbers.splice(2, 2); // 인덱스 2부터 2개 제거
console.log(removed); // [3, 4]
console.log(numbers); // [1, 2, 5]

// 요소 추가
numbers.splice(2, 0, 10, 20); // 인덱스 2에 10, 20 추가
console.log(numbers); // [1, 2, 10, 20, 5]

// 요소 교체
numbers.splice(1, 1, 100); // 인덱스 1의 요소를 100으로 교체
console.log(numbers); // [1, 100, 10, 20, 5]

sort(), reverse()

let animals = ["코끼리", "사자", "원숭이", "고양이"];

// 정렬 (사전순)
animals.sort();
console.log(animals); // ["고양이", "사자", "원숭이", "코끼리"]

// 역순 정렬
animals.reverse();
console.log(animals); // ["코끼리", "원숭이", "사자", "고양이"]

// 숫자 배열 정렬
let scores = [85, 92, 78, 96, 87];
scores.sort((a, b) => a - b); // 오름차순
console.log(scores); // [78, 85, 87, 92, 96]

scores.sort((a, b) => b - a); // 내림차순
console.log(scores); // [96, 92, 87, 85, 78]

새로운 배열을 반환하는 메서드

map() - 배열의 각 요소를 변환

let numbers = [1, 2, 3, 4, 5];

// 각 요소에 2를 곱하기
let doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
console.log(numbers); // [1, 2, 3, 4, 5] (원본 배열은 그대로)

// 객체 배열 변환
let students = [
    { name: "김철수", score: 85 },
    { name: "이영희", score: 92 },
    { name: "박민수", score: 78 }
];

let names = students.map(student => student.name);
console.log(names); // ["김철수", "이영희", "박민수"]

filter() - 조건에 맞는 요소만 필터링

let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// 짝수만 필터링
let evenNumbers = numbers.filter(num => num % 2 === 0);
console.log(evenNumbers); // [2, 4, 6, 8, 10]

// 점수가 80 이상인 학생만 필터링
let students = [
    { name: "김철수", score: 85 },
    { name: "이영희", score: 92 },
    { name: "박민수", score: 78 },
    { name: "정수진", score: 88 }
];

let passedStudents = students.filter(student => student.score >= 80);
console.log(passedStudents);
// [{ name: "김철수", score: 85 }, { name: "이영희", score: 92 }, { name: "정수진", score: 88 }]

reduce() - 배열을 하나의 값으로 축약

let numbers = [1, 2, 3, 4, 5];

// 합계 구하기
let sum = numbers.reduce((acc, curr) => acc + curr, 0);
console.log(sum); // 15

// 최댓값 구하기
let max = numbers.reduce((acc, curr) => acc > curr ? acc : curr);
console.log(max); // 5

// 객체 배열에서 특정 값의 합계
let products = [
    { name: "노트북", price: 1200000 },
    { name: "마우스", price: 30000 },
    { name: "키보드", price: 80000 }
];

let totalPrice = products.reduce((acc, product) => acc + product.price, 0);
console.log(totalPrice); // 1310000

find(), findIndex()

let users = [
    { id: 1, name: "김철수", age: 25 },
    { id: 2, name: "이영희", age: 30 },
    { id: 3, name: "박민수", age: 28 }
];

// 조건에 맞는 첫 번째 요소 찾기
let user = users.find(user => user.age > 27);
console.log(user); // { id: 2, name: "이영희", age: 30 }

// 조건에 맞는 첫 번째 요소의 인덱스 찾기
let index = users.findIndex(user => user.name === "박민수");
console.log(index); // 2

some(), every()

let scores = [85, 90, 78, 92, 88];

// 하나라도 조건을 만족하는지
let hasHighScore = scores.some(score => score >= 90);
console.log(hasHighScore); // true

// 모든 요소가 조건을 만족하는지
let allPassed = scores.every(score => score >= 60);
console.log(allPassed); // true

let allExcellent = scores.every(score => score >= 90);
console.log(allExcellent); // false

📝 다차원 배열

다차원 배열은 배열 안에 배열이 들어있는 구조입니다.

2차원 배열 기본

// 2차원 배열 생성
let matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
];

// 요소 접근
console.log(matrix[0]); // [1, 2, 3]
console.log(matrix[1][2]); // 6

// 전체 순회
for (let i = 0; i < matrix.length; i++) {
    for (let j = 0; j < matrix[i].length; j++) {
        console.log(`matrix[${i}][${j}] = ${matrix[i][j]}`);
    }
}

3차원 배열

// 3차원 배열 예시: 빌딩의 층별, 호실별 정보
let building = [
    [ // 1층
        ["101호", "102호", "103호"],
        ["104호", "105호", "106호"]
    ],
    [ // 2층
        ["201호", "202호", "203호"],
        ["204호", "205호", "206호"]
    ],
    [ // 3층
        ["301호", "302호", "303호"],
        ["304호", "305호", "306호"]
    ]
];

// 2층 첫 번째 줄의 두 번째 호실
console.log(building[1][0][1]); // "202호"

// 전체 호실 출력
building.forEach((floor, floorIndex) => {
    console.log(`${floorIndex + 1}층:`);
    floor.forEach((row, rowIndex) => {
        console.log(`  ${rowIndex + 1}번째 줄: ${row.join(", ")}`);
    });
});

 


📝 유사 배열 객체

유사 배열 객체는 배열처럼 보이지만 실제로는 객체인 것들을 말해요.

유사 배열 객체의 특징

// 유사 배열 객체 예시
let arrayLike = {
    0: "첫 번째",
    1: "두 번째", 
    2: "세 번째",
    length: 3
};

console.log(arrayLike[0]); // "첫 번째"
console.log(arrayLike.length); // 3

// 하지만 배열 메서드는 사용할 수 없음
// arrayLike.push("네 번째"); // TypeError!

arguments 객체

function showArguments() {
    console.log(arguments); // 유사 배열 객체
    console.log(arguments.length); // 인수의 개수
    
    // 일반 for문은 사용 가능
    for (let i = 0; i < arguments.length; i++) {
        console.log(`인수 ${i}: ${arguments[i]}`);
    }
    
    // 배열 메서드는 직접 사용 불가
    // arguments.forEach(...); // TypeError!
}

showArguments("안녕", "하세요", 123);

DOM NodeList

// HTML에서 모든 p 태그를 가져온다면
// let paragraphs = document.querySelectorAll('p'); // NodeList (유사 배열)

// 유사 배열을 실제 배열로 변환하는 방법들
let arrayLike = {
    0: "첫 번째",
    1: "두 번째",
    2: "세 번째",
    length: 3
};

// 방법 1: Array.from() 사용
let realArray1 = Array.from(arrayLike);
console.log(realArray1); // ["첫 번째", "두 번째", "세 번째"]

// 방법 2: 스프레드 연산자 사용
let realArray2 = [...arrayLike];
console.log(realArray2); // ["첫 번째", "두 번째", "세 번째"]

// 방법 3: Array.prototype.slice.call() 사용
let realArray3 = Array.prototype.slice.call(arrayLike);
console.log(realArray3); // ["첫 번째", "두 번째", "세 번째"]

// 이제 배열 메서드 사용 가능
realArray1.forEach(item => console.log(item));

📝 ES6 배열과 새로운 기능

ES6부터 배열에 많은 유용한 기능들이 추가되었어요!

Array.from()

// 문자열을 배열로 변환
let str = "Hello";
let charArray = Array.from(str);
console.log(charArray); // ["H", "e", "l", "l", "o"]

// 길이가 정해진 빈 배열 생성 후 초기화
let numbers = Array.from({length: 5}, (_, index) => index + 1);
console.log(numbers); // [1, 2, 3, 4, 5]

// 매핑 함수와 함께 사용
let doubled = Array.from([1, 2, 3], x => x * 2);
console.log(doubled); // [2, 4, 6]

Array.of()

// Array() 생성자의 문제점
let arr1 = new Array(3); // [empty × 3] - 길이가 3인 빈 배열
let arr2 = new Array(1, 2, 3); // [1, 2, 3]

// Array.of()는 항상 인수들을 요소로 하는 배열 생성
let arr3 = Array.of(3); // [3]
let arr4 = Array.of(1, 2, 3); // [1, 2, 3]

console.log(arr1); // [empty × 3]
console.log(arr2); // [1, 2, 3]
console.log(arr3); // [3]
console.log(arr4); // [1, 2, 3]

includes() - 요소 포함 여부 확인

let fruits = ["사과", "바나나", "오렌지"];

// indexOf()의 개선된 버전
console.log(fruits.includes("바나나")); // true
console.log(fruits.includes("포도")); // false

// indexOf()와의 차이점: NaN 처리
let numbers = [1, 2, NaN, 4];
console.log(numbers.indexOf(NaN)); // -1 (찾을 수 없음)
console.log(numbers.includes(NaN)); // true (올바르게 찾음)

// 시작 인덱스 지정 가능
console.log(fruits.includes("사과", 1)); // false (인덱스 1부터 검색)

fill() - 배열을 특정 값으로 채우기

// 배열의 모든 요소를 같은 값으로 채우기
let arr1 = [1, 2, 3, 4, 5];
arr1.fill(0);
console.log(arr1); // [0, 0, 0, 0, 0]

// 특정 범위만 채우기
let arr2 = [1, 2, 3, 4, 5];
arr2.fill(9, 1, 4); // 인덱스 1부터 4 전까지
console.log(arr2); // [1, 9, 9, 9, 5]

// 새 배열 생성과 함께 사용
let zeros = new Array(5).fill(0);
console.log(zeros); // [0, 0, 0, 0, 0]

copyWithin() - 배열 내부에서 복사

let arr = [1, 2, 3, 4, 5, 6];

// copyWithin(복사할위치, 복사시작위치, 복사끝위치)
arr.copyWithin(0, 3, 5); // 인덱스 3~4의 요소를 인덱스 0부터 복사
console.log(arr); // [4, 5, 3, 4, 5, 6]

let arr2 = [1, 2, 3, 4, 5];
arr2.copyWithin(2, 0); // 인덱스 0부터 끝까지를 인덱스 2부터 복사
console.log(arr2); // [1, 2, 1, 2, 3]

스프레드 연산자 (...)

// 배열 복사
let original = [1, 2, 3];
let copied = [...original];
console.log(copied); // [1, 2, 3]
console.log(original === copied); // false (다른 배열)

// 배열 합치기
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
let combined = [...arr1, ...arr2];
console.log(combined); // [1, 2, 3, 4, 5, 6]

// 배열에 요소 추가
let numbers = [2, 3, 4];
let extended = [1, ...numbers, 5];
console.log(extended); // [1, 2, 3, 4, 5]

// 함수 인수로 전달
function sum(a, b, c) {
    return a + b + c;
}

let values = [1, 2, 3];
console.log(sum(...values)); // 6

디스트럭처링 할당

// 기본 디스트럭처링
let [first, second, third] = [1, 2, 3];
console.log(first); // 1
console.log(second); // 2
console.log(third); // 3

// 일부 요소 건너뛰기
let [a, , c] = [1, 2, 3];
console.log(a); // 1
console.log(c); // 3

// 기본값 설정
let [x = 10, y = 20] = [5];
console.log(x); // 5
console.log(y); // 20

// 나머지 요소 수집
let [head, ...tail] = [1, 2, 3, 4, 5];
console.log(head); // 1
console.log(tail); // [2, 3, 4, 5]

// 변수 교환
let p = 10, q = 20;
[p, q] = [q, p];
console.log(p); // 20
console.log(q); // 10

📚 마무리 정리

오늘 배운 내용을 정리하면:

배열의 메서드는 원본을 변경하는 것과 새로운 배열을 반환하는 것으로 나뉩니다

map(), filter(), reduce() 등의 메서드는 함수형 프로그래밍의 핵심이며 매우 자주 사용되고 있습니다

다차원 배열은 복잡한 데이터 구조를 표현할 때 유용하며, 중첩된 반복문으로 접근할 수 있습니다

유사 배열 객체는 배열처럼 보이지만 배열 메서드를 직접 사용할 수 없어서 Array.from()이나 스프레드 연산자로 변환해야 합니다

ES6+의 새 기능들(Array.from(), includes(), 스프레드 연산자, 디스트럭처링 등)은 코드를 더 간결하고 읽기 쉽게 만들어줍니다

💡 오늘 새롭게 알게 된 것

  • reduce() 메서드의 강력함과 다양한 활용 방법
  • copyWithin() 메서드로 배열 내부에서 요소를 복사할 수 있다는 점
  • 디스트럭처링 할당으로 배열의 값을 쉽게 추출하고 변수에 할당할 수 있다는 점
  • Array.from()의 두 번째 매개변수로 매핑 함수를 전달할 수 있다는 점

🤔 어려웠던 점

  • reduce() 메서드의 누적값(accumulator) 개념이 처음엔 헷갈렸어요
  • 다차원 배열에서 인덱스를 관리하는 부분이 복잡하네요
  • 유사 배열 객체와 실제 배열의 차이점을 구분하는 게 어려웠습니다
  • 배열에 관련된 내용은 중요한 부분을 다시 공부해야 할 것같습니다

🎯 다음 학습 계획

다음 포스팅에서는 버그와 오류에 대처하는 방법에 대해 알아보겠습니다.