JavaScript의 Array
메서드 중 하나인 flatMap
을 자주 접하지만, 정확히 어떤 역할을 하는지 이해하기 어려울 때가 있습니다.
예제를 봐도 flatMap
이 어떤 데이터 타입으로 결과를 반환하는지 명확하지 않을 때가 있었습니다.
그래서 이 글을 통해 flatMap
의 개념을 정리하고 이해를 심화해보겠습니다.
공식 문서 살펴보기
flatMap
flatMap()
는 Array
인스턴스의 메서드로, 각 요소에 맵핑 함수를 적용한 후 결과를 새로운 배열로 평탄화하는 기능을 제공합니다.
이는 map()
을 사용한 후 깊이 1의 flat()
을 호출하는 것과 동일하지만 (arr.map(...args).flat()
), 두 메서드를 각각 호출하는 것보다 약간 더 효율적입니다.
공식 문서는 위와 같이 설명하고 있지만, "평탄화"라는 개념이 낯설고, "약간 효율적"이라는 부분이 어떤 의미인지 의문이 들었습니다.
flat
의 문서도 살펴보면 다음과 같습니다.
flat
flat()
는 Array
인스턴스의 메서드로, 모든 하위 배열 요소를 지정된 깊이까지 재귀적으로 결합한 새로운 배열을 생성합니다.
이 설명 역시도 낯설고 이해하기 어려웠습니다. 이를 좀 더 명확히 이해해 보겠습니다.
flat 이해하기
flat의 예시
flat
의 개념을 이해하기 위해 문서에 나와 있는 예시를 지역, 도시, 구역, 거리라는 계층으로 바꾸어 생각해 보겠습니다.
// 문서의 예시
const arr2 = [1, 2, [3, 4, [5, 6]]];
console.log(arr2.flat());
// [1, 2, 3, 4, [5, 6]]
// 계층 구조로 변환
const arr2 = ['대한민국', '일본', ['서울', '부산', ['인천', '대구']]];
console.log(arr2.flat());
// ['대한민국', '일본', '서울', '부산', ['인천', '대구']]
최상위 계층이 "국가"인 배열에 flat()
을 사용하면, 2계층에 있었던 "도시" 요소가 1계층의 "국가"와 같은 수준으로 올라옵니다.
단순히 한 계층을 분해하는 이미지입니다. 이렇게 계층을 단순화하는 것이 flat()
의 역할입니다.
flatMap 이해하기
flatMap의 필요성
flatMap
을 사용하고자 할 때는 중첩된 계층의 요소에 대해 특정 처리를 수행하고 싶을 때입니다.
예를 들어, 다음과 같은 복잡한 처리가 필요하다고 가정해 봅시다.
문제: 인구 50만 명 이상인 도시를 출력하라.
조건: 아래 regions
라는 객체가 주어짐.
const regions = [
{
prefecture: '서울',
cities: [
{ city: '강남구', population: 339000 },
{ city: '서초구', population: 227000 },
{ city: '송파구', population: 939000 }
]
},
{
prefecture: '부산',
cities: [
{ city: '해운대구', population: 2750000 },
{ city: '남구', population: 830000 },
{ city: '동구', population: 500000 }
]
},
{
prefecture: '대구',
cities: [
{ city: '달서구', population: 400000 },
{ city: '북구', population: 160000 },
{ city: '남구', population: 90000 }
]
}
];
map()만 사용한 경우
const largeCities = regions.map(region =>
region.cities.filter(city => city.population >= 500000)
);
console.log(largeCities);
위 코드에서 map()
만 사용했을 때는 다음과 같이 중첩된 배열이 반환됩니다.
[
[
{ city: '송파구', population: 939000 }
],
[
{ city: '해운대구', population: 2750000 },
{ city: '남구', population: 830000 },
{ city: '동구', population: 500000 }
],
[] // 대구의 처리 결과
]
이렇게 중첩된 배열은 타입스크립트 같은 정적 타입 언어에서는 타입 오류를 발생시킬 수 있습니다.
이를 해결하기 위해 flatMap
의 사용이 필요합니다.
map() 후 flat() 실행
const largeCities = regions.map(region =>
region.cities.filter(city => city.population >= 500000)
).flat();
console.log(largeCities);
map()
후 flat()
을 실행하면 중첩된 배열이 평탄화되어 다음과 같은 결과를 얻을 수 있습니다.
[
{ city: '송파구', population: 939000 },
{ city: '해운대구', population: 2750000 },
{ city: '남구', population: 830000 },
{ city: '동구', population: 500000 }
]
이처럼 원하는 결과를 얻을 수 있지만, 매번 flat()
을 호출하는 것은 번거로울 수 있습니다. 이때 flatMap()
이 유용합니다.
flatMap() 사용
const largeCities = regions.flatMap(region =>
region.cities.filter(city => city.population >= 500000)
);
console.log(largeCities);
flatMap()
을 사용하면 map()
후 flat()
을 호출한 것과 동일한 결과를 얻을 수 있습니다.
[
{ city: '송파구', population: 939000 },
{ city: '해운대구', population: 2750000 },
{ city: '남구', population: 830000 },
{ city: '동구', population: 500000 }
]
이제 flatMap()
의 기능을 이해하고 나니 공식 문서를 다시 보면 그 의미가 명확해집니다.
flatMap()
은 배열의 각 요소를 매핑한 후 결과를 새로운 배열에 평탄화합니다.
이는 map()
후 깊이 1의 flat()
을 수행하는 것과 동일하지만, 두 메서드를 별도로 호출하는 것보다 약간 더 효율적입니다.
추가 정보
flatMap()
은 평탄화 깊이를 지정할 수 없지만, 더 깊은 계층까지 평탄화하고 싶다면 flat()
을 사용하여 다음과 같이 지정할 수 있습니다.
const arr3 = [1, 2, [3, 4, [5, 6]]];
console.log(arr3.flat(2));
// [1, 2, 3, 4, 5, 6]
const arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
console.log(arr4.flat(Infinity));
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
이러한 기능은 언젠가 유용하게 사용할 수 있을 것입니다. 기억해 두면 좋습니다.
이렇게 새롭게 작성된 글을 통해 flatMap
의 개념과 사용법을 이해할 수 있기를 바랍니다.
그럼.
'Javascript' 카테고리의 다른 글
2024년 웹 개발의 최신 트렌드와 기법 (0) | 2024.08.24 |
---|---|
자바스크립트 표준 빌트인 객체 정리: 코딩 테스트 필수 지식 (0) | 2024.08.24 |
lodash-es보다 가볍고 빠른 es-toolkit으로 전환하기 (0) | 2024.08.24 |
TypeScript의 고급 타입 시스템과 React Hooks 활용법 (0) | 2024.08.24 |
TypeScript로 불필요한 변수 선언 없애기: `satisfies` 활용법 (0) | 2024.08.24 |