Object.groupBy / Map.groupBy (ES2024)

๐Ÿ“š
JavaScript
2025.11.08

๐Ÿ“š Overview

Object.groupBy, Map.groupBy ๋ฌธ๋ฒ•์„ ํ†ตํ•ด ์ด์ œ reduce, lodash.groupBy ๊ฐ™์€ ๋ฐ˜๋ณต ํŒจํ„ด ์—†์ด๋„ ํ‘œ์ค€ ๋ฌธ๋ฒ•์œผ๋กœ ๊น”๋”ํ•˜๊ฒŒ ๋ฐ์ดํ„ฐ ๊ทธ๋ฃนํ•‘์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

ES2024 ๋ถ€ํ„ฐ ํฌํ•จ๋œ groupBy ๋ฌธ๋ฒ•์˜ ๊ฐœ๋…, ์ฐจ์ด์ , ๊ทธ๋ฆฌ๊ณ  ์‹ค๋ฌด์—์„œ ์œ ์šฉํ•œ ํ™œ์šฉ๋ฒ•์„ ์ •๋ฆฌํ•ด๋ณธ๋‹ค.



1. groupBy ๋ฌธ๋ฒ•์€ ์–ธ์ œ๋ถ€ํ„ฐ ์ƒ๊ฒผ๋‚˜?


ํ•ด๋‹น ๋ฌธ๋ฒ•์€ Array Grouping Proposal์ด 2023๋…„ ๋ง TC39 Stage 4์— ๋„๋‹ฌํ•˜๋ฉด์„œ, ECMAScript 2024 (ES15) ํ‘œ์ค€์— ์ •์‹ ํฌํ•จ๋˜์—ˆ๋‹ค.

๊ตฌ๋ถ„ ๋ช…์„ธ ๋‚ด์šฉ
์ œ์•ˆ ๋‹จ๊ณ„ TC39 Stage 4 Array Grouping Proposal
ํ‘œ์ค€ ๋ฐ˜์˜ ECMAScript 2024 ์ •์‹ ๋ฌธ๋ฒ• ํฌํ•จ
์ง€์› ํ™˜๊ฒฝ Node 21+, ์ตœ์‹  ๋ธŒ๋ผ์šฐ์ € ๊ธฐ๋ณธ ์ง€์›

๐Ÿ’ก ์ฐธ๊ณ : TC39 Proposal: Array Grouping / MDN Object.groupBy



2. Object vs Map, ์–ธ์ œ ์–ด๋–ค ๊ฑธ ์จ์•ผ ํ• ๊นŒ?


groupBy๋Š” ๋™์ผํ•œ ์ธํ„ฐํŽ˜์ด์Šค์ฒ˜๋Ÿผ ๋ณด์ด์ง€๋งŒ ๋ฐ˜ํ™˜ ํƒ€์ž…์ด ๋‹ค๋ฅด๋‹ค. ํ•˜๋‚˜๋Š” Object, ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” Map์„ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ, ์ด ์ฐจ์ด๊ฐ€ ์‚ฌ์šฉ ๋ชฉ์ ์„ ์™„์ „ํžˆ ๊ฐˆ๋ผ๋†“๋Š”๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ๋Š” ์ด๋ ‡๊ฒŒ ๊ธฐ์–ตํ•˜๋ฉด ๋œ๋‹ค.

์ƒํ™ฉ ์ถ”์ฒœ
๋ฌธ์ž์—ด / JSON ์‘๋‹ต ์ค‘์‹ฌ Object.groupBy
์ˆซ์ž / Date / ๊ฐ์ฒด ํ‚ค ์‚ฌ์šฉ Map.groupBy
ํ›„์† ์ •๋ ฌ / Map API ํ™œ์šฉ Map.groupBy
์ง๋ ฌํ™” / ๋‹จ์ˆœ ์‘๋‹ต ๊ฐ€๊ณต Object.groupBy


2-1. Object.groupBy


  • ๋ฌธ์ž์—ด / ์‹ฌ๋ณผ ํ‚ค๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๊ทธ๋ฃนํ•‘

  • ๊ฒฐ๊ณผ๊ฐ€ ์ผ๋ฐ˜ ๊ฐ์ฒด(Record<string, T[]>)๋กœ ๋ฐ˜ํ™˜๋˜์–ด JSON ์ง๋ ฌํ™”๋‚˜ API ์‘๋‹ต ๊ฐ€๊ณต์— ์ ํ•ฉ

    const orders = [
      { id: 'A1', status: 'progress' },
      { id: 'A2', status: 'pending' },
      { id: 'A3', status: 'failed' },
      { id: 'A4', status: 'progress' },
    ];
    
    const groupByStatus = Object.groupBy(orders, order => order.status);
    
    console.log(groupByStatus);
    /*
    {
      progress: [{id:'A1'}, {id:'A4'}],
      pending: [{id:'A2'}],
      failed: [{id:'A3'}]
    }
    */


2-2. Map.groupBy


  • ๋น„๋ฌธ์ž์—ด ํ‚ค(์ˆซ์ž, Date, ๊ฐ์ฒด ๋“ฑ) ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

  • ๊ฒฐ๊ณผ๊ฐ€ Map์œผ๋กœ ๋ฐ˜ํ™˜๋˜์–ด, ์ •๋ ฌ, ๋ณ‘ํ•ฉ, ํ›„์† ์—ฐ์‚ฐ์— ์œ ๋ฆฌ

    const users = [
      { user: 'u1', createdAt: new Date('2025-11-01T10:00Z') },
      { user: 'u2', createdAt: new Date('2025-11-01T11:00Z') },
      { user: 'u3', createdAt: new Date('2025-11-02T09:00Z') },
    ];
    
    const groupByDay = Map.groupBy(users, user => user.createdAt.toDateString());
    
    console.log([...groupByDay.entries()]);
    // [['Sat Nov 01 2025', [u1,u2]], ['Sun Nov 02 2025', [u3]]]


3. reduce ํŒจํ„ด๊ณผ ๋น„๊ต


์ด์ „์—๋Š” ์ด๋Ÿฐ ์‹์œผ๋กœ reduce๋ฅผ ํ™œ์šฉํ–ˆ๋‹ค.

const grouped = orders.reduce((acc, order) => {
  (acc[order.status] ??= []).push(order);
  return acc;
}, {});

์ด์ œ๋Š” ํ›จ์”ฌ ๋‹จ์ˆœํ•˜๊ฒŒ ์“ธ ์ˆ˜ ์žˆ๋‹ค.

const grouped = Object.groupBy(orders, order => order.status);

๐Ÿ’ก ์ฝ”๋“œ ์–‘์ด ์ค„์—ˆ์„ ๋ฟ ์•„๋‹ˆ๋ผ, ์˜๋„๊ฐ€ ๋ช…ํ™•ํ•˜๊ฒŒ ๋“œ๋Ÿฌ๋‚œ๋‹ค. โ€œ๋‚˜๋Š” ์ง€๊ธˆ ๋ฐ์ดํ„ฐ๋ฅผ ๊ทธ๋ฃนํ•‘ํ•œ๋‹ค.โ€



4. ES2024 ์ดํ›„ ๋ณ€ํ™”๊ฐ€ ์˜๋ฏธํ•˜๋Š” ๊ฒƒ


  • Lodash ๊ฐ™์€ ํ—ฌํผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์˜์กด์„ฑ ๊ฐ์†Œ
  • ์ฝ”๋“œ ๋ฆฌ๋ทฐ ์‹œ ์˜๋„ ํŒŒ์•…์ด ์ฆ‰๊ฐ์ 
  • TypeScript์—์„œ๋„ ํƒ€์ž… ์ถ”๋ก ์ด ๋” ์ง๊ด€์ 

ES2024๋Š” โ€œ๊ฐœ๋ฐœ์ž์˜ ๋ฐ˜๋ณต ํŒจํ„ด์„ ์–ธ์–ด ๋ ˆ๋ฒจ๋กœ ์˜ฌ๋ ค์ฃผ๋Š”โ€ ๋ฒ„์ „์ด๋ผ๊ณ  ๋ด๋„ ์ข‹๋‹ค. groupBy ์™ธ์—๋„ ์–ธ๊ธ‰ํ•˜์ง€ ์•Š์•˜์ง€๋งŒ, Array.prototype.with, toSorted ๊ฐ™์€ ๋ฌธ๋ฒ•๋“ค์ด ๊ทธ ๋Œ€ํ‘œ์ ์ธ ์˜ˆ๋‹ค.



๐Ÿค” Understanding

๊ฐœ์ธ์ ์œผ๋กœ๋Š” groupBy๊ฐ€ ๋‹จ์ˆœํ•œ ํ—ฌํผ ๋ฉ”์„œ๋“œ์ž„์„ ๋„˜์–ด โ€œ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ”๋ผ๋ณด๋Š” ๊ด€์ โ€ ์„ ๋ฐ”๊พธ๋Š” ๊ธฐ๋Šฅ์ด๋ผ ์ƒ๊ฐํ•œ๋‹ค.

  • ๋กœ์ง ๋‹จ์ˆœํ™”: ๋ถˆํ•„์š”ํ•œ reduce ํ˜น์€ ์™ธ๋ถ€ ์˜์กด์„ฑ ์ œ๊ฑฐ
  • ๊ฐ€๋…์„ฑ ํ–ฅ์ƒ: ์ฝ”๋“œ ์˜๋„๊ฐ€ ๋ฐ”๋กœ ๋“œ๋Ÿฌ๋‚จ
  • ํ‘œ์ค€ํ™”๋œ ์ ‘๊ทผ: ํŒ€ ์ปจ๋ฒค์…˜ ํ†ต์ผ ๊ฐ€๋Šฅ

์•ž์œผ๋กœ โ€œ๋ฐ์ดํ„ฐ ๊ทธ๋ฃนํ•‘โ€์ด ํ•„์š”ํ•œ ๋Œ€๋ถ€๋ถ„์˜ ์ƒํ™ฉ์—์„œ ๊ณ ๋ฏผ ์—†์ด ์‚ฌ์šฉํ•ด๋ณผ ์ƒ๊ฐ์ด๋‹ค.



Previous
์ฒซ ์˜คํ”ˆ ์†Œ์Šค PR ๊ธฐ์—ฌ ํ›„๊ธฐ (MikroORM Redis Cache Adapter)
๐Ÿค”Retrospect
2025.11.04
Next
structuredClone() โ€“ Web Platform์ด ์ œ๊ณตํ•˜๋Š” ํ‘œ์ค€ ๋”ฅ ํด๋ก 
๐Ÿ“šWeb
2025.11.16