한눈에 보는 JavaScript 배열 메서드 활용법 실무 코딩 가이드 썸네일

한눈에 보는 JavaScript 배열 메서드 활용법 | 실무 코딩 가이드

JavaScript 배열 메서드는 실무에서 정말 많이 사용하지만 기억력이 좋지 않은 저는 늘 AI의 도움을 받아서 사용하고 있습니다. AI가 활성화되기 전에도 능숙하게 사용하지 못하고, 구글링을 꼭 하고 나서 사용하곤 했었죠.

그래서 자주 사용하던 배열 메서드 문법도 조금 더 익숙해지고, 잘 몰랐던 배열 메서드도 알아보고, 실무에서 어떻게 더 효과적으로 사용할 수 있을지에 대해서 글을 작성해 보기로 했습니다.

배열 메서드 종류는 이 글에 언급된 것 보다 더 많이 있습니다. 이 글에서는 기본적이고, 많이 사용되는 메서드만 다루고 있습니다.

예제의 실습이 필요하면 jsfiddle로 하면 편할 것 같습니다. 각 메서드 별 자세한 정보는 Array – JavaScript | MDN (mozilla.org) 이 사이트에 잘 나와 있습니다. 이 글은 좀 더 쉽고 편하게 모아서 보는데 목적을 두고 있습니다.

한눈에 보는 JavaScript 배열 메서드 활용법 실무 코딩 가이드 썸네일

JavaScript 배열 메서드(데이터 추가/삭제)

배열의 끝이나 시작 부분에 요소를 추가하거나 삭제할 때 사용되는 메서드입니다.

push()

배열의 마지막에 하나 이상의 요소를 추가하고, 변경된 배열의 길이를 반환합니다.

// 배열에 1개 요소 추가
const arr = [1, 2, 3];
arr.push(4);
console.log(arr); // 출력: [1, 2, 3, 4]

// 배열에 여러 개 요소 한꺼번에 추가
const arr2 = [1, 2, 3, 4];
arr2.push(5, 6, 7);
console.log(arr2); // 출력: [1, 2, 3, 4, 5, 6, 7]

pop()

배열의 마지막 요소를 제거하고, 제거된 요소를 반환합니다.

const arr = [1, 2, 3];
const lastElement = arr.pop();
console.log('arr', arr); // 출력: [1, 2]
console.log('lastElement', lastElement); // 출력: 3

unshift()

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

// 배열의 맨 앞에 1개 요소 추가
const arr = [2, 3];
arr.unshift(1);
console.log(arr); // 출력: [1, 2, 3]

// 배열의 맨 앞에 여러 개 요소 추가
const arr2 = [2, 3];
arr2.unshift(-1, 0, 1);
console.log(arr2); // 출력: [-1, 0, 1, 2, 3]

shift()

배열의 맨 앞 요소를 제거하고, 제거된 요소를 반환합니다.

const arr = [1, 2, 3];
const firstElement = arr.shift();
console.log('arr', arr); // 출력: [2, 3]
console.log('firstElement', firstElement); // 출력: 1

제가 했었던 프로젝트만 그런지는 모르겠지만 배열의 순서에 어떤 의미를 부여하는 경우는 거의 없었던 것 같습니다.
그래서 그런지 pop(), unshift(), shift() 같이 마지막 요소를 제거하거나 맨 앞 요소를 추가/제거하는 메서드를 쓸 일은 별로 없었습니다.

JavaScript 배열 메서드(배열 순회 및 탐색)

배열의 모든 요소를 반복하거나 특정 조건에 맞는 요소를 찾을 때 유용합니다.

forEach()

배열의 각 요소에 대해 주어진 함수를 실행합니다. 반환값은 없습니다.

const numbers = [1, 2, 3];
numbers.forEach(num => console.log(num * 2)); // 출력: 2, 4, 6

map()

배열의 각 요소에 주어진 함수를 적용하여 새로운 배열을 만들어 반환합니다.

const numbers = [1, 2, 3];
const doubled = numbers.map(num => num * 2);
console.log('numbers', numbers); // numbers는 그대로 유지됨 [1, 2, 3]
console.log('doubled', doubled); // 출력: [2, 4, 6]

filter()

주어진 테스트 함수를 통과하는 모든 요소를 모아 새로운 배열을 반환합니다.

const numbers = [1, 2, 3, 4, 5];
const evens = numbers.filter(num => num % 2 === 0);
console.log('numbers', numbers); // numbers는 그대로 유지됨 [1, 2, 3, 4, 5]
console.log('evens', evens); // 출력: [2, 4]

find()

주어진 테스트 함수를 통과하는 배열의 첫 번째 요소를 반환합니다. 없으면 undefined를 반환합니다.

const users = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }, { id: 2, name: 'Bob' }];
const foundUser = users.find(user => user.id === 2);
console.log('users ', users ); // users는 그대로 유지됨
console.log('foundUser', foundUser); // 출력: { id: 2, name: 'Bob' }

includes()

배열에 특정 요소가 포함되어 있는지 확인하여 true 또는 false를 반환합니다.

const fruits = ['apple', 'banana', 'orange', 'grape'];
console.log('사과가 있나요?', fruits.includes('apple')); // true
console.log('망고가 있나요?', fruits.includes('mango')); // false

some()

배열의 요소 중 하나라도 주어진 함수를 통과하면 true를 반환합니다.

// 주어진 함수를 만족하는 게 하나도 없는 경우
const numbers = [1, 3, 5, 7];
const hasEvenNumber = numbers.some(num => num % 2 === 0);
console.log(hasEvenNumber); // 출력: false

// 주어진 함수를 만족하는 게 하나라도 있는 경우
const numbers2 = [1, 2, 3, 5, 7];
const hasEvenNumber2 = numbers2.some(num => num % 2 === 0);
console.log(hasEvenNumber2); // 출력: true

every()

배열의 모든 요소가 주어진 함수를 통과해야 true를 반환합니다.

// 모든 요소가 주어진 함수를 만족하는 경우
const numbers = [2, 4, 6, 8];
const allEvenNumbers = numbers.every(num => num % 2 === 0);
console.log(allEvenNumbers); // 출력: true

// 한 개라도 주어진 함수를 만족하지 않는 경우
const numbers2 = [2, 4, 6, 8, 9];
const allEvenNumbers2 = numbers2.every(num => num % 2 === 0);
console.log(allEvenNumbers2); // 출력: false

reduce()

배열의 각 요소를 순회하며 단일 값으로 축소하는 데 사용됩니다. 주로 배열의 합계, 평균 계산, 객체 변환 등에 활용됩니다.

기본 구조

array.reduce(callback(accumulator, currentValue, index, array), initialValue)

  • accumulator: 누적값 (이전 콜백의 반환값)
  • currentValue: 현재 처리 중인 요소
  • index: 현재 처리 중인 요소의 인덱스 (0부터 시작)
  • array: reduce()를 호출한 원본 배열
  • initialValue: 초기값 (선택사항)

활용 예제

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

// 1. 숫자 배열 합계 구하기(sum)
const sum = numbers.reduce((acc, curr) => acc + curr, 0);
console.log('합계:', sum); // 출력: 15

// 2. min, max 값 찾기(min, max)
const max = numbers.reduce((acc, curr) => Math.max(acc, curr));
const min = numbers.reduce((acc, curr) => Math.min(acc, curr));
console.log('max:', max); // 출력: 5
console.log('min:', min); // 출력: 1

// 3. 배열 평탄화
const nestedArray = [[1, 2], [3, 4], [5, 6, 7]];
const flattened = nestedArray.reduce((acc, curr) => acc.concat(curr), []);
console.log('평탄화된 배열:', flattened); // 출력: [1, 2, 3, 4, 5, 6, 7]

// 4. 그룹화(group by)
const people = [
  { name: '김철수', department: '개발팀' },
  { name: '이영희', department: '디자인팀' },
  { name: '박민수', department: '개발팀' },
  { name: '정수진', department: '마케팅팀' }
];
const groupedByDept = people.reduce((acc, person) => {
  const dept = person.department;
  if (!acc[dept]) {
    acc[dept] = [];
  }
  acc[dept].push(person.name);
  return acc;
}, {});
console.log('부서별 그룹:', groupedByDept); // 출력: { 개발팀: ['김철수', '박민수'], 디자인팀: ['이영희'], 마케팅팀: ['정수진'] }

forEach(), map(), filter(), find(), includes() 같은 경우는 실무에서 쓸 일이 굉장히 많습니다.
some(), every() 같은 경우도 쓰임새가 분명 있을 것 같지만 실무에서의 사용 빈도는 약간 떨어지는 것 같습니다.
reduce() 같은 경우는 다른 메서드에 비해 복잡하지만 쓰임새가 워낙 다양하고, 강력하기 때문에 특히 신경 써서 봐야 하는 메서드입니다.

JavaScript 배열 메서드(배열 변형 및 결합)

배열의 순서를 바꾸거나, 요소를 자르거나, 다른 배열과 합칠 때 사용합니다.

slice()

배열의 특정 부분을 새로운 배열로 복사하여 반환합니다. 원본 배열을 변경하지 않습니다.

// 지정한 시작 인덱스부터 끝까지 복사
const numbers = [0, 1, 2, 3, 4, 5];
const slicedNumbers = numbers.slice(3); // 인덱스 3부터 끝까지
console.log(slicedNumbers); // 출력: [3, 4, 5]

// 지정한 시작 인덱스부터 종료 인덱스 직전까지 복사
const numbers2 = [0, 1, 2, 3, 4, 5];
const slicedNumbers2 = numbers2.slice(1, 3); // 인덱스 1부터 3의 직전까지
console.log(slicedNumbers2); // 출력: [1, 2]

※ slice()의 두 번째 파라미터에 넣은 종료 인덱스까지가 아니라 종료 인덱스 -1까지 복사된다는 점을 주의해야 합니다. 저도 매번 쓸 때마다 헷갈리고 있습니다.

splice()

배열의 기존 요소를 제거하거나 교체하고, 새로운 요소를 추가합니다. 원본 배열이 변경됩니다.

// 1. 요소 제거
let arr = ['사과', '바나나', '오렌지', '포도'];
let removed = arr.splice(1, 2); // 인덱스 1부터 2개의 요소 제거
console.log(arr); // ['사과', '포도']
console.log(removed); // ['바나나', '오렌지'] (제거된 요소들)

// 2. 요소 추가
let arr2 = ['사과', '바나나', '포도'];
arr2.splice(1, 0, '망고'); // 인덱스 1부터 0개 제거, '망고' 추가
console.log(arr2); // 출력: ['사과', '망고', '바나나', '포도']

// 3. 요소 교체
let arr3 = ['사과', '바나나', '포도'];
arr3.splice(1, 1, '망고', '키위'); // 인덱스 1에서 1개 제거, '망고'와 '키위' 추가
console.log(arr3); // 출력: ['사과', '망고', '키위', '포도']

// 4. 음수 인덱스 사용
let arr4 = ['사과', '바나나', '포도'];
arr4.splice(-1, 1); // 끝에서 첫 번째 요소 제거
console.log(arr4); // 출력: ['사과', '바나나']

concat()

여러 배열을 합쳐 새로운 배열을 만듭니다.

const arr1 = [1, 2];
const arr2 = [3, 4];
const newArr = arr1.concat(arr2);
console.log('arr1', arr1); // arr1은 그대로 유지됨 [1, 2]
console.log('arr2', arr2); // arr2는 그대로 유지됨 [3, 4]
console.log('newArr', newArr); // 출력: [1, 2, 3, 4]

join()

배열의 모든 요소를 연결하여 하나의 문자열로 만듭니다.

const fruits = ['apple', 'banana', 'orange'];
const fruitString = fruits.join(', '); 
console.log(fruitString); // 출력: "apple, banana, orange"

sort()

배열의 요소를 정렬합니다. 기본적으로 문자열 순서로 정렬되므로, 숫자나 객체 정렬 시에는 비교 함수를 제공해야 합니다.

문자열 정렬

let fruits = ["banana", "apple", "cherry"];

// 기본 정렬 (오름차순)
fruits.sort();
console.log(fruits); // 출력: ["apple", "banana", "cherry"]

// 내림차순 정렬
fruits.sort((a, b) => b.localeCompare(a));
console.log(fruits); // 출력: ["cherry", "banana", "apple"]

숫자 정렬

let numbers = [100, 5, 20, 10];

// 잘못된 정렬 (문자열로 간주)
numbers.sort();
console.log(numbers); // 출력: [10, 100, 20, 5]

// 올바른 오름차순 정렬
numbers.sort((a, b) => a - b);
console.log(numbers); // 출력: [5, 10, 20, 100]

// 내림차순 정렬
numbers.sort((a, b) => b - a);
console.log(numbers); // 출력: [100, 20, 10, 5]

객체 정렬

let items = [
  { name: "Apple", price: 30 },
  { name: "Banana", price: 10 },
  { name: "Cherry", price: 20 }
];

// 1. 이름 기준 오름차순 정렬
items.sort((a, b) => a.name.localeCompare(b.name));
console.log("이름 오름차순:", items);
// 출력: [
//   { name: "Apple", price: 30 },
//   { name: "Banana", price: 10 },
//   { name: "Cherry", price: 20 }
// ]

// 2. 이름 기준 내림차순 정렬
items.sort((a, b) => b.name.localeCompare(a.name));
console.log("이름 내림차순:", items);
// 출력: [
//   { name: "Cherry", price: 20 },
//   { name: "Banana", price: 10 },
//   { name: "Apple", price: 30 }
// ]

// 3. 가격 기준 오름차순 정렬
items.sort((a, b) => a.price - b.price);
console.log("가격 오름차순:", items);
// 출력: [
//   { name: "Banana", price: 10 },
//   { name: "Cherry", price: 20 },
//   { name: "Apple", price: 30 }
// ]

// 4. 가격 기준 내림차순 정렬
items.sort((a, b) => b.price - a.price);
console.log("가격 내림차순:", items);
// 출력: [
//   { name: "Apple", price: 30 },
//   { name: "Cherry", price: 20 },
//   { name: "Banana", price: 10 }
// ]

JavaScript 배열 메서드 장단점

장점

  • 가독성: 코드 길이가 배열 메서드를 사용하지 않았을 때에 비해 짧고, 어떤 배열 메서드를 사용하냐에 따라 의도가 명확히 드러나서 이해하기 쉽다.
  • 체이닝: 메서드를 연결하여 간결하고 직관적인 코드 작성이 가능하다.
  • 유지보수성: 함수형 프로그래밍 패턴을 따르므로 로직이 단순화되고 버그 가능성이 줄어든다.

단점

  • 성능: 일부 메서드는 배열 전체를 순회하며, 체이닝 시 여러 번 순회해 성능 저하가 발생할 수 있다. for 루프가 더 빠를 수 있다.
  • 메모리 사용: map, filter 등은 새 배열을 생성하므로 메모리 소비가 증가한다.
  • 제어 흐름 제약: break나 continue 같은 루프 제어 구문을 사용할 수 없다.

파괴적 메서드와 비파괴적 메서드

JavaScript 배열 메서드를 사용할 때 중요하게 생각해야 하는 부분 중 하나는 원본 배열이 유지되느냐 변경되느냐입니다.

원본 배열의 유지가 필요한지, 필요 없는지를 꼭 먼저 생각하고, 배열 메서드를 사용해야 합니다.

  • 파괴적 메서드: push(), pop(), shift(), unshift(), splice(), sort()
  • 비파괴적 메서드: map(), filter(), slice(), concat(), join()

JavaScript 배열 메서드 체이닝 활용 예제

메서드 체이닝은 코드를 더 간결하고 읽기 쉽게 만들어 줍니다. 각 메서드가 어떤 값을 반환하는지 명확히 이해하면, 복잡한 데이터 처리도 여러 단계로 나눠서 효과적으로 처리할 수 있습니다.

// 1. 짝수만 찾아서 2배로 만들기
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

const doubledEvens = numbers
  .filter(num => num % 2 === 0)  // 짝수만 걸러내기: [2, 4, 6, 8, 10]
  .map(num => num * 2);          // 각 요소를 2배로 만들기: [4, 8, 12, 16, 20]

console.log(doubledEvens); // 출력: [4, 8, 12, 16, 20]

// 2. 장바구니 총액 계산하기
const cart = [
  { name: '책', price: 15000, quantity: 2 },
  { name: '펜', price: 2000, quantity: 5 },
  { name: '노트', price: 5000, quantity: 3 },
];

const totalAmount = cart
  .map(item => item.price * item.quantity) // 각 아이템의 총 가격 계산: [30000, 10000, 15000]
  .reduce((total, current) => total + current, 0); // 모든 가격 합산하기: 55000

console.log(totalAmount); // 출력: 55000

JavaScript 배열 메서드는 상황에 따라 적절하게 사용하자.

요즘은 배열 메서드를 적극적으로 활용하는 추세이지만 상황에 따라서는 for 루프와 if 문을 활용한 전통적인 방법이 더 맞을 때도 있습니다.

간결한 작업은 배열 메서드를 적극 활용하고, 복잡하거나 성능이 중요한 작업에서는 전통적인 방법이 더 알맞지 않은지 고려해 봐야 합니다.

결론은 너무 배열 메서드 사용만 고집하지 말고, 또 너무 배열 메서드가 익숙하지 않아서 전통적인 for 루프와 if 문 사용만을 고집하지도 말아야 한다는 것입니다.

예제를 메서드 별로 실행해 보면서 전체적으로 JavaScript 배열 메서드를 실행해 보니 전보다는 많이 익숙해진 것 같습니다. 실무에서 전보다 적극적으로 활용할 수 있을 것 같습니다. 혹시 잘못된 부분 있으면 댓글로 남겨주세요.

Similar Posts

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다