filter로 반복 조회하면 호출할 때마다 배열 전체를 순회해 비용이 O(n * k)로 늘어납니다.groupBy 유틸리티를 만들 수 있고, 대량 데이터라면 객체를 직접 변경(mutable)하는 방식이 성능상 유리합니다.프론트엔드에서는 서버로 받은 리스트 데이터를 카테고리나 날짜 같은 기준으로 분류해 화면에 보여줘야 할 때가 많습니다. 이때 흔히 쓰는 방식이 Array.prototype.filter()입니다.
하지만 filter는 호출될 때마다 배열 전체를 순회합니다. 여러 카테고리를 처리하려고 filter를 반복해서 쓰면, 배열이 커질수록 비용이 O(n * k)(n: 배열 크기, k: 카테고리 수)로 선형 증가합니다. 특정 카테고리 데이터를 찾으려고 매번 전체 배열을 뒤지는 셈이라 비효율적입니다.
가장 좋은 방법은 데이터를 미리 그룹화해두는 것입니다. 배열을 단 한 번만 순회해 객체(Object)나 맵(Map) 형태로 재구성해두면, 이후에는 키로 데이터에 직접 접근할 수 있어 접근 속도가 O(1)로 향상됩니다.
런타임에 결정되는 동적 패턴을 RegExp 생성자 함수로 안전하게 다루는 방법을 정리합니다.
2022. 4. 29.FrontendV8 같은 현대 JavaScript 엔진이 소스 코드를 토큰화, AST 생성, 바이트코드 변환, JIT 컴파일을 거쳐 기계어로 실행하는 과정을 단계별로 정리합니다.
2024. 11. 25.FrontendReact Native의 기존 브릿지 구조가 가진 성능 한계를, 새 아키텍처의 JSI와 Fabric, Turbo Modules가 어떻게 해결하는지 정리합니다.
2022. 11. 16.filter(category === 'X') 실행 -> 전체 순회.reduce 실행 -> 결과 객체 생성 -> result['X']로 즉시 접근.핵심은 배열을 순회하며 각 아이템의 특정 속성을 키로 사용하는 '해시 맵' 형태의 객체를 만드는 것입니다.
TypeScript 제네릭을 활용해 재사용성이 높고 타입 안정성이 보장되는 groupBy 유틸리티 함수를 구현해 보겠습니다.
typescriptconst DUMMY = [ { category: "food", name: "짜장면" }, { category: "electronic", name: "TV" }, { category: "food", name: "떡볶이" }, { category: "clothes", name: "tshirt" }, ]; /** * 배열을 특정 키를 기준으로 그룹화하는 유틸리티 함수 */ const groupBy = <T extends Record<string, any>>( array: T[], keyForGrouping: keyof T ): Record<string, T[]> => { return array.reduce<Record<string, T[]>>((group, item) => { const valueForGrouping = item[keyForGrouping]; // 그룹이 존재하지 않으면 빈 배열로 초기화 후 아이템 추가 return { ...group, [valueForGrouping]: group[valueForGrouping] ? [...group[valueForGrouping], item] : [item] }; }, {}); }; // 사용 예시 const groupedData = groupBy(DUMMY, 'category'); console.log(groupedData.food); // [{ category: "food", name: "짜장면" }, ...]
위 구현은 reduce 내부에서 ...group(스프레드 연산자)을 사용해 매 순회마다 새 객체를 만듭니다. 대량의 데이터를 처리하면 가비지 컬렉션 부담이 커질 수 있습니다. 실무에서는 다음처럼 객체를 직접 변경(mutable)하는 방식이 성능상 유리합니다.
typescriptconst groupByOptimized = <T extends Record<string, any>>( array: T[], keyForGrouping: keyof T ): Record<string, T[]> => { return array.reduce<Record<string, T[]>>((group, item) => { const key = String(item[keyForGrouping]); if (!group[key]) { group[key] = []; } group[key].push(item); return group; }, {}); };
성과는 다음과 같습니다.
다만 다음 트레이드오프가 있습니다.
TypeScript의 타입 시스템과 결합한 groupBy 함수는 데이터 중심 웹 애플리케이션에서 유용한 도구입니다. 최근 JavaScript 표준(ES2024)에는 Object.groupBy()와 Map.groupBy()가 추가되었으니, 최신 환경이라면 이를 활용하는 것도 좋은 방법입니다.
참고 자료: