[ES6] 배열(array) 관련 메서드 소개 및 활용

4 minute read

배열은 개발에서 빠질 수 없는 기초적인 자료구조이다. 때문에 프로그래밍 언어는 배열과 관련된 다양한 메서드들을 제공한다. 자바스크립트도 마찬가지로 활용도 높은 메서드들을 제공하고 있다.

본 게시물에서는 자바스크립트에서 제공하는 배열 관련 메서드들을 소개하고 각각의 메서드를 어떤 용도로 사용할 수 있는지 살펴보도록 한다.

forEach

arr.forEach(currentValue[, index[, array]])[, thisArg]);

forEach는 배열의 원소를 순회하면서 callback 함수를 실행한다. callback 함수는 currentValue, index, array 세 개의 인자를 사용 할 수 있다. currentValue에는 각 원소의 값이 들어가므로 for문과 유사한 형태로 사용 할 수 있다.

주로 전체 원소를 대상으로 특정 로직을 수행 할 때 사용된다.

forEach vs for

const arr = [1, 2, 3]

for (let i = 0; i < arr.length; i += 1) {
  console.log(arr[i])
}

arr.forEach(num => console.log(num))

위 예제는 for문과 forEach를 이용해 똑같은 로직을 수행한다. 하지만, forEach를 사용하는 쪽이 훨씬 간결하다. 때문에 간단한 반복문이라면 forEach를 사용하는 것을 추천한다.

forEach 사용 예제

// 1
const arr = [1, 2, 3]
arr.forEach(num => console.log(num))

// 2
const itemIds = [1, 2, 3]
const removeItem = id => someAPI.removeItem(id)
itemIds.forEach(removeItem)

1번 예제는 각 원소의 값을 로그에 출력한다.

2번 예제의 경우 원소를 순회하며 특정 함수를 호출한다. 사실 아래 설명할 map으로 Promise 배열을 받은 뒤 Promise.all로 삭제하는게 더 낫지만, 이 게시물의 취지는 forEach에 대한 설명이므로 더 Promise에 대한 자세한 내용은 이 게시물을 참고하자.

map

arr.map(callback(currentValue[, index[, array]])[, thisArg])

map은 배열의 원소를 순회하며 callback함수를 실행한다. 그리고 callback함수의 반환값으로 구성된 새로운 배열을 반환한다.

주로 배열의 구성 원소를 이용해 새로운 배열을 생성 할 때 사용된다.

map 사용 예제

// 1
const arr = [1, 2, 3]
const plusFiveArr = arr.map(num => num + 5) // [6, 7, 8]

// 2
const itemIds = [1, 2, 3]
const removeItem = (id) => someAPI.removeItem(id)
Promise.all(itemIds.map(removeItem))

1번 예제는 각 배열 원소에 5를 더해 새로운 배열을 생성한다.

2번 예제는 배열 원소를 이용해 다수의 API 호출이 필요한 경우 주로 사용되는 방식이다. map을 이용해 전체 API 호출을 하나의 배열에 담는다. 그 이후 Promise.all을 이용해 API 호출을 병렬 처리 할 수 있다.

reduce

arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])

reduce는 각 배열의 원소를 순회하며 callback 함수를 실행시킨다. callback 함수는 accumulator, currentValue, index, array를 인자로 받는다.

여기서 중요한 포인트는 accumulator이다. accumulator는 현재까지 누적된 결과값을 가진다. callback 함수에서 리턴한 값은 다음 callback 함수의 accumulator 값이 된다. 이를 통해 누적된 값을 계산 할 수 있다. initialValue 값을 입력하면 첫번째 callback함수 실행에서 accumulator 값이 된다.

주로 배열을 하나의 값으로 만들 때 사용된다. 이를 다른식으로 표현하면 벡터(Vector)를 스칼라(Scalar)로 만든다고 할 수 있다.

reduce의 동작 원리

reduce를 처음 접하면 그 동작원리가 정확히 이해되지 않을 수 있다. 다음 예제를 통해 동작 원리를 알아보자.

const arr = [1, 2, 3]
const callback = (accumulator, currentValue, index, array) => accumulator + currentValue
const sum = arr.reduce(callback, 0) // 6

위의 예제에서 callback 함수는 총 3번 호출된다. 각 호출에 따른 인자와 반환값은 다음과 같다.

callback 호출 횟수 accumulator currentValue index array 반환 값
1번째 0 1 0 [1, 2, 3] 1
2번째 1 2 1 [1, 2, 3] 3
3번째 3 3 2 [1, 2, 3] 6

위의 표를 보면 이전 callback 함수의 반환 값이 다음 callback 함수의 accumulator 값으로 사용되는 것을 알 수 있다. 마지막 callback 호출 후 반환되는 6을 sum 변수에 대입하게 된다.

reduce 사용 예제

// 1
const arr = [1, 2, 3]
const sum = arr.reduce((acc, curr) => acc + curr, 0) // 6

// 2
const accounts = [
  { id: 'armadillo1', age: 27, gender: 'male' },
  { id: 'armadillo2', age: 33, gender: 'male' },
  { id: 'armadillo3', age: 21, gender: 'female' },
  { id: 'armadillo4', age: 40, gender: 'female' },
  { id: 'armadillo5', age: 13, gender: 'female' },
]
const groupByGender = accounts.reduce((acc, curr) => {
  const key = curr.gender
  if (!acc.hasOwnProperty(key)) {
    acc[key] = []
  }
  acc[key].push(curr)
  return acc
}, {})

console.log(groupByGender) // { male: [...], female: [...] }

1번 예제는 전체 배열 원소의 합계 값을 구한다.

2번 예제는 계정(account)을 순회하면서 성별(gender)로 그루핑 하는 작업을 수행한다.

find

arr.find(callback[, thisArg])

findcallback 함수가 truthy 값을 반환 할 때까지 배열의 원소를 순회하며 실행시킨다. callback 함수가 truthy를 반환 할 경우 해당 callback에 해당하는 원소 값을 리턴 시킨다. 만약 모든 callbackfalsy 값을 반환하면 undefined를 반환한다.

주로 특정 조건을 만족하는 원소를 찾을 때 사용된다.

find 사용 예제

// 1
const arr = [10, 20, 30]
const result = arr.find(num => num > 10) // 20

// 2
const accounts = [
  { id: 'armadillo1', age: 27, gender: 'male' },
  { id: 'armadillo2', age: 33, gender: 'male' },
  { id: 'armadillo3', age: 21, gender: 'female' },
  { id: 'armadillo4', age: 40, gender: 'female' },
  { id: 'armadillo5', age: 13, gender: 'female' },
]

const armadillo3 = accounts.find(account => account.id === 'armadillo3') // { id: 'armaidllo3' ... }

1번 예제는 10보다 큰 숫자를 찾는다. 2030 모두 10보다 큰 숫자이지만, 20가 먼저 callback 함수로 실핼되기 때문에 최종 결과는 20이 된다.

2번 예제는 여러 개정을 가진 배열에서 특정 계정을 찾는 작업을 수행한다.

some

arr.some(callback[, thisArg])

some 함수는 callback 함수에서 조건을 충족하는 원소가 하나라도 있으면 true를, 모든 원소가 조건을 충족시키지 못한다면 false를 반환한다. 한 개의 원소라도 조건을 충족하면 즉시 true를 반환하고 순회를 종료하기 때문에 every보다 퍼포먼스가 좋다.

주로 배열에서 특정 조건을 만족하는지 여부를 판별 할 때 사용된다.

some 사용 예제

// 1
const arr = [1, 2, 3]
const hasGreaterThanTwo = arr.some(num => num > 2) // true


// 2
const arr2 = [10, 20, 30, 40]
const hasGreaterThanTen = arr2.some((num) => {
  console.log(num)
  return num > 10
}) // 10이 출력되고 true 반환

1번 예제는 2보다 큰 숫자를 가지고 있는지 판별한다. 원소 중 3이 있으므로 true를 반환한다.

2번 예제는 10보다 큰 숫자를 가지고 있는지 판별한다. 1번 예제와 다른 점은 callback 함수가 실행될 때마다 로그를 남기는 것이다. 실행 결과를 보면 10만 로그에 찍히는 것을 알 수 있다. 이처럼 some 메서드는 전체 원소를 순회하지 않고 true값이 반환되면 그 즉시 실행을 종료한다.

결론

javascript에서는 다양한 메서드를 통해 배열을 조작 할 수 있다. 이러한 메서드들을 잘 활용하면 기존의 반복문을 대부분 제거 할 수 있고, 코드 또한 간결해진다.이 게시물에서 다루지 못한 다양한 메서드들은 이 링크에서 확인할 수 있다.

참고자료

Comments