brunch

You can make anything
by writing

C.S.Lewis

by swimjiy Sep 20. 2020

JS flat(), flatMap() 함수 톺아보기

중첩된 배열을 깔끔하게 펼쳐보자

flat()과 flatMap()은 둘 다 중첩된 배열 구조를 평탄화하기 위해 사용하는 함수입니다.

두 함수 모두 ECMAScript 2019(ES10)에 새롭게 추가된 함수라 아직은 일상적으로 쓰이진 않지만, 그래도 알고 있으면 아무리 깊고 복잡한 배열 구조여도 간단하게 정리할 수 있다는 장점이 있습니다.


flat()

먼저 flat() 함수부터 알아보도록 하겠습니다. 가령 이런 구조의 배열이 있다고 생각해봅시다.

const fruits = ['apple', ['banana', 'orange', ['melon']]];


우리는 이 배열을 아래와 같이 평탄하게 만들고 싶어 합니다.

['apple', 'banana', 'orange', 'melon']


그렇다면 어떤 방식을 사용하는 게 좋을까요? 만약 ES6 스펙으로 작업한다면 아래와 같이 코드를 작성할 수 있습니다.

const flatten = (arr) => {
  return arr.reduce((flat, toFlatten) => {
    return flat.concat(
      Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten
    );
  }, []);
};
console.log(flatten(fruits));
// [ 'apple', 'banana', 'orange', 'melon' ]

reduce로 각 배열의 요소를 순회하며 빈 배열에 요소를 concat()을 이용하여 덧붙이는 flatten이라는 함수를 만들고, 만약 배열의 요소의 타입이 배열이라면 재귀적으로 돌면서 같은 작업을 반복하게끔 했습니다.


지금 코드 또한 나쁘진 않지만 flat() 함수를 사용한다면 아래와 같이 한 줄로 마무리할 수 있습니다.

console.log(fruits.flat(2));


정말 간결해지지 않았나요? 그렇다면 조금 더 자세히 flat 함수에 대해 알아보도록 하겠습니다.


기본 구문

flat() 함수는 중첩된 배열 구조를 정해진 깊이만큼 평탄하게 만들 수 있는 함수이며 기본 구문은 아래와 같습니다.

const newArr = arr.flat([depth])

   

매개변수로 어느 깊이까지 평탄화할지를 정할 수 있는 depth 변수가 있으며 생략이 가능합니다.

depth를 생략했을 때는 아래와 같이 기본값인 1이 적용됩니다.


console.log(fruits.flat());
// [ 'apple', 'banana', 'orange', [ 'melon' ] ]


Infinity를 사용하면 하위 배열이 없을 때까지 평탄하게 바꿉니다.

console.log(fruits.flat(Infinity));
// [ 'apple', 'banana', 'orange', 'melon' ]


flatMap()

flatMap은 이름에서 알 수 있듯이 배열을 평탄화하는 flat()의 기능에 배열의 각 요소에 접근하여 사용자 정의 로직을 수행할 수 있는 map()의 기능을 합친 함수입니다.

다만 flat()과 달리 깊이를 최대 1만큼만 평탄하게 만들 수 있다는 특징이 있습니다.

그럼 간단하게 예시를 볼까요?


아래와 같이 각 요소들을 2로 곱하고 하위 1 레벨만큼의 배열 중첩을 제거해야 한다고 합시다.

const children = [[1], [2], [3], [4]];
// [2, 4, 6, 8];


아까 얘기했던 flat() 함수에 map() 함수를 사용하면 아래와 같이 작성할 수 있습니다.

console.log(children.map((x) => x * 2).flat());


이걸 flatMap()을 이용하면 조금 더 간결하게 작성할 수 있습니다.

console.log(children.flatMap((x) => [x * 2]));


기본 구문

이번에는 flatMap()의 구문을 간단히 알아보겠습니다. 명세는 아래와 같이 나와있습니다.

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

복잡하게 표현되어 있지만 map()의 명세를 보면 구문이 동일함을 알 수 있습니다. 즉 마지막에 반환하는 값의 양 옆에 대괄호([])를 붙이는 것 이외에는 map 함수와 사용법이 같다는 거죠.

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


다만 flat()과 달리 깊이 1만큼만 평탄화가 가능하고 이외에는 map()과 기능이 유사하기 때문에 정확히 어떤 상황에서 flatMap()을 사용하는 게 좋을지는 좀 더 알아봐야 할 것 같습니다.

마지막으로 두 메서드 모두 ES2019에 추가된 메서드이기 때문에 Internet Explorer에서는 호환되지 않는다는 이슈가 있으므로 이점 유의하시기 바랍니다.



참고자료

Array.prototype.flat() - JavaScript | MDN

Array.prototype.flatMap() - JavaScript | MDN

브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari