[JS] Map, Set

jinyยท2025๋…„ 10์›” 19์ผ

๊ธฐ์ˆ  ๋ฉด์ ‘

๋ชฉ๋ก ๋ณด๊ธฐ
66/78

๐Ÿ—ฃ๏ธ Map, Set์˜ ๊ฐœ๋…๊ณผ ํ™œ์šฉ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”.

  • ์˜๋„: ์ง€์›์ž๊ฐ€ ES6์—์„œ ๋„์ž…๋œ Map๊ณผ Set์˜ ๊ฐœ๋…๊ณผ ๊ทธ ํ™œ์šฉ๋ฒ•์„ ์ดํ•ดํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ‰๊ฐ€
  • ํŒ
    • Map๊ณผ Set์˜ ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•๊ณผ ๊ทธ ์žฅ์ ์— ๋Œ€ํ•ด ์„ค๋ช…ํ•œ๋‹ค.
    • ์ฃผ์š” ๋ฉ”์„œ๋“œ(add, delete, has, clear ๋“ฑ)์— ๋Œ€ํ•œ ์˜ˆ์ œ๋ฅผ ๋– ์˜ฌ๋ ค๋ณธ๋‹ค.
  • ๋ชจ๋ฒ” ๋‹ต์•ˆ

    ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ Map๊ณผ Set์€ ES6์—์„œ ๋„์ž…๋œ ์ƒˆ๋กœ์šด ์ปฌ๋ ‰์…˜ ์ž๋ฃŒ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค.

    Map์€ ํ‚ค์™€ ๊ฐ’์„ ํ•œ ์Œ์œผ๋กœ ์ €์žฅํ•œ๋‹ค๋Š” ์ ์—์„œ ๊ฐ์ฒด์™€ ๋น„์Šทํ•˜์ง€๋งŒ,
    ๋ชจ๋“  ํƒ€์ž…์˜ ๊ฐ’์„ ํ‚ค๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ , ํ‚ค์˜ ์‚ฝ์ž… ์ˆœ์„œ๋ฅผ ์œ ์ง€ํ•œ๋‹ค๋Š” ์ฐจ์ด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
    ๊ทธ๋ž˜์„œ ์ฃผ๋กœ ์ˆœ์„œ๊ฐ€ ์ค‘์š”ํ•˜๊ฑฐ๋‚˜, ๊ฐ์ฒด ํ‚ค ์™ธ์˜ ๊ฐ’์„ ํ‚ค๋กœ ์‚ฌ์šฉํ•ด์•ผ ํ•  ๋•Œ ํ™œ์šฉ๋ฉ๋‹ˆ๋‹ค.
    ์˜ˆ๋ฅผ ๋“ค์–ด API ์‘๋‹ต ์บ์‹ฑ, DOM ์š”์†Œ๋ณ„ ๋ฐ์ดํ„ฐ ๋งคํ•‘ ๊ฐ™์€ ๊ฒฝ์šฐ์— ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

    ๋ฐ˜๋ฉด Set์€ ์ค‘๋ณต๋˜์ง€ ์•Š๋Š” ์œ ์ผํ•œ ๊ฐ’์˜ ์ง‘ํ•ฉ์„ ์ €์žฅํ•˜๋Š” ์ž๋ฃŒ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค.
    ๊ฐ’์ด ํ•œ ๋ฒˆ๋งŒ ์กด์žฌํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ, ์˜ˆ๋ฅผ ๋“ค์–ด ์ค‘๋ณต ์ œ๊ฑฐ, ๋ฐฐ์—ด์—์„œ ๊ณ ์œ ํ•œ ๊ฐ’ ์ถ”์ถœ ๋“ฑ์— ์ž์ฃผ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
    ์‚ฝ์ž… ์ˆœ์„œ๋„ ์œ ์ง€๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ˆœํšŒ ์‹œ์—๋„ ์•ˆ์ •์ ์ž…๋‹ˆ๋‹ค.

    ๋‘ ๊ตฌ์กฐ ๋ชจ๋‘ size, has, delete, clear ๊ฐ™์€ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•ด ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ๊ฐ€ ๊ฐ์ฒด๋ณด๋‹ค ํ›จ์”ฌ ์ง๊ด€์ ์ด๊ณ  ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค.


๐Ÿ“ ๊ฐœ๋… ์ •๋ฆฌ

๐ŸŒŸ Map

  • ๊ฐœ๋…
    • ํ‚ค-๊ฐ’(key-value) ์Œ์„ ์ €์žฅํ•˜๋Š” ES6 ์ปฌ๋ ‰์…˜
    • ํ‚ค๋กœ ๋ชจ๋“  ์ž๋ฃŒํ˜• ์‚ฌ์šฉ ๊ฐ€๋Šฅ (๋ฌธ์ž์—ด/์ˆซ์ž/๊ฐ์ฒด/ํ•จ์ˆ˜/NaN ๋“ฑ)
    • ์‚ฝ์ž… ์ˆœ์„œ๋ฅผ ์œ ์ง€ํ•˜๋ฉฐ, ์ˆœํšŒ ์‹œ ๊ทธ ์ˆœ์„œ๋Œ€๋กœ ๋‚˜์˜ด
  • ์–ธ์ œ ์“ฐ๋‚˜?

    • ๋ฌธ์ž์—ด ์ด์™ธ์˜ ๊ฐ’(์˜ˆ: ๊ฐ์ฒด, ํ•จ์ˆ˜)์„ ํ‚ค๋กœ ์จ์•ผ ํ•  ๋•Œ

      const map = new Map();
      
      const user = { id : 1 };
      function handler() {}
      const notANumber = NaN;
      
      map.set(user, { role: "admin" });
      map.set(handler, { once: true });
      map.set(notANumber, "special");
      
      // ๋™์ผ ์ฐธ์กฐ๋กœ ์กฐํšŒ ๊ฐ€๋Šฅ
      console.log(map.get(user)); // { role: "admin" }
      console.log(map.get(handler)); // { once: true }
      console.log(map.get(NaN)); // "special"
      • ๊ฐ์ฒด(Object)์˜ ํ‚ค๋Š” ๋ฌธ์ž์—ด/์‹ฌ๋ณผ๋กœ ๊ฐ•์ œ๋จ (๊ฐ์ฒด๋ฅผ ํ‚ค๋กœ ๋„ฃ์œผ๋ฉด ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜๋˜์–ด ์ถฉ๋Œ/์˜๋„์น˜ ์•Š์€ ๋™์ž‘ ๋ฐœ์ƒ)
      • Map์€ ๋ชจ๋“  ํƒ€์ž…์„ ํ‚ค๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅ, ์‚ฝ์ž… ์ˆœ์„œ ์œ ์ง€
      • Map์€ ํ‚ค๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•˜์ง€ ์•Š๊ณ , "๊ทธ ๊ฐ์ฒด ์ฐธ์กฐ ์ž์ฒด"๋ฅผ ํ‚ค๋กœ ์”€
      • ์ฆ‰, { id: 1 } ๊ทธ ๊ฐ์ฒด(๋ฉ”๋ชจ๋ฆฌ ์ƒ์˜ ์ฐธ์กฐ)๊ฐ€ ๊ทธ๋Œ€๋กœ ํ‚ค๋กœ ์ €์žฅ๋จ
      • ๊ทธ๋ž˜์„œ ๋™์ผํ•œ ๋ชจ์–‘์˜ ๋‹ค๋ฅธ ๊ฐ์ฒด๋Š” ํ‚ค๊ฐ€ ๋‹ค๋ฆ„
        const user1 = { id: 1 };
        const user2 = { id: 2 }; // ๋‚ด์šฉ ๊ฐ™์•„๋„ ๋‹ค๋ฅธ ๊ฐ์ฒด(์ฐธ์กฐ ๋‹ค๋ฆ„)
        const map = new Map();
        map.set(user1, "A");
        map.get(user1); // "A"
        map.get(user2); // undefined (๋ฌธ์ž์—ด ํ‚ค์˜€๋‹ค๋ฉด ์ถฉ๋Œ/ํ˜ผ๋™์ด ์ƒ๊ฒผ์„ ๋ถ€๋ถ„)
    • ํ‚ค ๊ฐœ์ˆ˜๋ฅผ ์ž์ฃผ ํ™•์ธํ•  ๋•Œ(size) (์˜ˆ: ๊ฐ„๋‹จ LRU ์บ์‹œ ํŠธ๋ฆฌ๋ฐ)

      // ์ตœ๋Œ€ N๊ฐœ๊นŒ์ง€๋งŒ ๋ณด๊ด€ํ•˜๋Š” ์บ์‹œ: size๋กœ ์ฆ‰์‹œ ํŒ๋‹จ ํ›„ ๊ฐ€์žฅ ์˜ค๋ž˜๋œ ํ•ญ๋ชฉ ์ œ๊ฑฐ
      const MAX = 3;
      const cache = new Map();
      
      function setCache(key, value) {
        if (cache.size >= MAX) {
          // ๊ฐ€์žฅ ๋จผ์ € ๋“ค์–ด์˜จ(๊ฐ€์žฅ ์˜ค๋ž˜๋œ) ํ‚ค๋ฅผ ํ•˜๋‚˜ ์ œ๊ฑฐ
          const oldestKey = cache.keys().next().value;
          cache.delete(oldestKey);
        }
        cache.set(key, value);
      }
      
      setCache("a", 1); // size: 1
      setCache("b", 2); // size: 2
      setCache("c", 3); // size: 3
      setCache("d", 4); // size๊ฐ€ 3์„ ๋„˜๊ธฐ ์ง์ „์ด๋ฏ€๋กœ 'a' ์ œ๊ฑฐ
      
      console.log([...cache.entries()]); // [ ['b', 2], ['c', 3], ['d', 4] ]
      console.log(cache.size); // 3

      ๐Ÿ’ป cache.keys()

      • Map์˜ ํ‚ค ์ดํ„ฐ๋ ˆ์ดํ„ฐ(Iterator)๋ฅผ ๋Œ๋ ค์คŒ
      • ์ด ์ดํ„ฐ๋ ˆ์ดํ„ฐ๋Š” for...of๋กœ ๋Œ๋ฆด ์ˆ˜ ์žˆ๊ณ , ๋‚ด๋ถ€ ์ˆœ์„œ๋Š” ์‚ฝ์ž… ์ˆœ์„œ์ž„

      ๐Ÿ’ป .next()

      • ์ดํ„ฐ๋ ˆ์ดํ„ฐ์—์„œ ๋‹ค์Œ ํ•ญ๋ชฉ ํ•˜๋‚˜๋ฅผ ๊บผ๋‚ด๋ผ๋Š” ๋œป
      • ๋ฐ˜ํ™˜๊ฐ’์€ { value: <ํ‚ค๊ฐ’>, done: <๋ถˆ๋ฆฌ์–ธ> } ํ˜•ํƒœ์˜ IteratorResult ๊ฐ์ฒด
        • value: ์ด๋ฒˆ์— ๊บผ๋‚ธ ์š”์†Œ
        • done: ๋” ๊บผ๋‚ผ ๊ฒŒ ์—†์œผ๋ฉด true, ์žˆ์œผ๋ฉด false

      ๐Ÿ’ป .value

      • ์œ„์—์„œ ๋ฐ›์€ ๊ฐ์ฒด์—์„œ ํ‚ค ๊ฐ’๋งŒ ์ถ”์ถœํ•จ
      • ์ฆ‰, ์ฒซ ๋ฒˆ์งธ(๊ฐ€์žฅ ์˜ค๋ž˜๋œ) ํ‚ค๊ฐ€ ๋“ค์–ด์˜ด
      • Map.size๋Š” O(1)๋กœ ์ฆ‰์‹œ ํ™•์ธ ๊ฐ€๋Šฅ
      • ๊ฐ์ฒด๋Š” ํ‚ค ๊ฐœ์ˆ˜ ๊ณ„์‚ฐ ์‹œ Object.keys(obj).length์ฒ˜๋Ÿผ ๋งค๋ฒˆ ์ˆœํšŒ ๋น„์šฉ์ด ๋“ฆ
      • ์บ์‹œ/๋ฒ„ํผ์ฒ˜๋Ÿผ ์šฉ๋Ÿ‰ ๊ด€๋ฆฌ๊ฐ€ ํ•„์š”ํ•œ ๊ณณ์— ์œ ๋ฆฌํ•จ
    • ์ˆœ์„œ๊ฐ€ ์ค‘์š”ํ•œ ๋งคํ•‘, ์บ์‹œ, ๋นˆ๋„/์นด์šดํŠธ ํ…Œ์ด๋ธ” ๋“ฑ

      • ์ˆœ์„œ ๋ณด์กด ๋งคํ•‘: ํผ ํ•„๋“œ - ๋ผ๋ฒจ/๊ฒ€์ฆ ์ˆœ์„œ๋Œ€๋กœ ๋ Œ๋”๋ง

        const fieldMap = new Map([
          ["email", { label: "์ด๋ฉ”์ผ", required: true }],
          ["password", { label: "๋น„๋ฐ€๋ฒˆํ˜ธ", required: true }],
          ["nickname", { label: "๋‹‰๋„ค์ž„", required: false }],
        ]);
        
        // ์‚ฝ์ž… ์ˆœ์„œ๋Œ€๋กœ UI ๋ Œ๋”
        for (const [name, meta] or fieldMap) {
          console.log(`{meta.label} (${meta.required ? "ํ•„์ˆ˜" : "์„ ํƒ"})`);
        }
        // ์ถœ๋ ฅ ์ˆœ์„œ: ์ด๋ฉ”์ผ โ†’ ๋น„๋ฐ€๋ฒˆํ˜ธ โ†’ ๋‹‰๋„ค์ž„
      • ์บ์‹œ(์ตœ๊ทผ ์ฐธ์กฐ๋ฅผ ๋’ค๋กœ ๋ฐ€๊ธฐ) - ๊ฐ„๋‹จํ•œ LRU ์ ‘๊ทผ

        const cache = new Map();
        
        function get(key) {
          if (!cache.has(key)) return undefined;
          const val = cache.get(key);
          // ์‚ฌ์šฉ๋œ ํ•ญ๋ชฉ์„ '์ตœ์‹ '์œผ๋กœ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์‚ญ์ œ ํ›„ ์žฌ์‚ฝ์ž… โ†’ ์ˆœ์„œ ๋’ค๋กœ ์ด๋™
          cache.delete(key);
          cache.set(key, val);
          return val;
        }
        
        function put(key, val, max = 3) {
          if (cache.has(key)) cache.delete(key);
          cache.set(key, val);
          if (cache.size > max) {
            const oldestKey = cache.keys().next().value;
            cache.delete(oldestKey);
          }
        }
        
        put("A", 1); put("B", 2); put("C", 3); // A, B, C
        get("A"); // A๋ฅผ ์ตœ๊ทผ์œผ๋กœ: B, C, A
        put("D", 4); // ์ดˆ๊ณผ: ๊ฐ€์žฅ ์˜ค๋ž˜๋œ B ์ œ๊ฑฐ
        console.log([...cache.keys()]); // ['C', 'A', 'D']
      • ๋นˆ๋„/์นด์šดํŠธ ํ…Œ์ด๋ธ” (๋‹จ์–ด ๋“ฑ์žฅ ์ˆœ์„œ ์œ ์ง€ํ•ด ํ†ต๊ณ„ ์ถœ๋ ฅ)

        function frequency(list) {
          const freq = new Map();
          for (const item of list) {
            freq.set(item, (freq.get(item) ?? 0) + 1);
          }
          return freq; // ์‚ฝ์ž… ์ˆœ์„œ(์ฒซ ๋“ฑ์žฅ ์ˆœ์„œ)๋„ ํ•จ๊ป˜ ๋ณด์กด
        }
        
        const words = ["a", "b", "a", "c", "b", "a"];
        const table = frequency(words);
        
        for (const [word, count] of table) {
          console.log(`${word}: ${count}`);
        }
        // a: 3 โ†’ b: 2 โ†’ c: 1 (์ฒซ ๋“ฑ์žฅ ์ˆœ์„œ๋Œ€๋กœ)
  • ์ฃผ์š” ํŠน์ง•
    • ํฌ๊ธฐ: map.size
    • ์กด์žฌ ํ™•์ธ: map.has(key)
    • ์ถ”๊ฐ€/๊ฐฑ์‹ : map.set(key, value) (๋™์ผ ํ‚ค๋ฉด ๊ฐฑ์‹ )
    • ์กฐํšŒ: map.get(key) (์—†์œผ๋ฉด undefined)
    • ์‚ญ์ œ/์ดˆ๊ธฐํ™”: map.delete(key), map.clear()
    • ์ˆœํšŒ: for (const [k, v] of map), map.forEach((v, k) => ...)
    • ํ‚ค ๋™๋“ฑ์„ฑ: SameValueZero

      ๐Ÿ”Ž SameValueZero๋ž€?

      ๊ฐœ๋…

      • ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ๊ฐ’์˜ "๊ฐ™์Œ"์„ ํŒ๋‹จํ•˜๋Š” ๊ทœ์น™(๋™๋“ฑ ๋น„๊ต ์•Œ๊ณ ๋ฆฌ์ฆ˜) ์ค‘ ํ•˜๋‚˜
      • ๋Œ€๋ถ€๋ถ„ ===์ฒ˜๋Ÿผ ๋น„๊ตํ•˜์ง€๋งŒ NaN์„ ์„œ๋กœ ๊ฐ™๋‹ค๊ณ  ๋ณด๊ณ , +0๊ณผ -0๋„ ๊ฐ™๋‹ค๊ณ  ๋ด„

      ๋น„๊ต ๊ทœ์น™ ์ฐจ์ดํ‘œ

      ๋น„๊ต ๊ทœ์น™NaN vs. NaN+0 vs. -0๊ฐ์ฒด ๋น„๊ต
      === (์—„๊ฒฉ ๋™๋“ฑ)falsetrue์ฐธ์กฐ ๋™์ผ์„ฑ
      SameValueZerotruetrue์ฐธ์กฐ ๋™์ผ์„ฑ
      Object.istruefalse์ฐธ์กฐ ๋™์ผ์„ฑ

      โ“ ์ฐธ์กฐ ๋™์ผ์„ฑ(reference equality)

      • "๋‘ ๊ฐ’์ด ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋А๋ƒ?"๋ฅผ ๋ฌป๋Š” ๊ฐœ๋…
      • ๋‘ ํ”ผ์—ฐ์‚ฐ์ž๊ฐ€ ๋™์ผํ•œ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค(๊ฐ™์€ ์ฐธ์กฐ)๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋ฉด true, ์•„๋‹ˆ๋ฉด false

      ์™œ ์ค‘์š”ํ•œ๊ฐ€?

      Map/Set์€ ํ‚ค(๋˜๋Š” ๊ฐ’) ๋™๋“ฑ์„ฑ์„ SameValueZero๋กœ ํŒ๋‹จํ•จ
      ๊ทธ๋ž˜์„œ NaN์„ ํ‚ค๋กœ ์จ๋„ ์ •์ƒ ๋™์ž‘ํ•จ

      const m = new Map();
      m.set(NaN, 'ok');
      console.log(m.get(NaN)); // 'ok' (NaN๋„ ๊ฐ™์€ ํ‚ค๋กœ ์ธ์‹)
      const s = new Set([NaN, NaN]);
      console.log(s.size); // 1 (์ค‘๋ณต์œผ๋กœ ํŒ๋‹จํ•จ)

      ๋ฐ˜๋ฉด ๋ฐฐ์—ด ๊ฒ€์ƒ‰์€ ๊ทœ์น™์ด ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Œ

      const array = [NaN];
      array.indexOf(NaN); // -1 (indexOf๋Š” === ๊ทœ์น™ ์ ์šฉ)
      array.includes(NaN); // true (includes๋Š” SameValueZero ๊ทœ์น™ ์ ์šฉ)
  • ์ดํ„ฐ๋ ˆ์ด์…˜ & ๋ฐ˜ํ™˜
    • entries / keys / values
      for (const [k, v] of m.entries()) {}
      for (const k of m.keys()) {}
      for (const v of m.values()) {}
    • ๊ฐ์ฒด โ†” Map
      const m2 = new Map(Object.entries({ a: 1, b: 2 }));
      const obj = Object.fromEntries(m2); // { a: 1, b: 2 }

      ๐Ÿ’ป Object.entries({ a: 1, b: 2 })

      • ๋ฐ˜ํ™˜: [['a', 1], ['b', 2]] ํ˜•ํƒœ์˜ [ํ‚ค, ๊ฐ’] ํŠœํ”Œ ๋ฐฐ์—ด
      • ํฌํ•จ ๋ฒ”์œ„: ์—ด๊ฑฐ ๊ฐ€๋Šฅํ•œ(enumerable) ๋ฌธ์ž์—ด ํ‚ค๋งŒ ํฌํ•จ
        • ๋น„์—ด๊ฑฐ ํ”„๋กœํผํ‹ฐ๋Š” ์ œ์™ธ
        • Symbol ํ‚ค๋Š” ์ œ์™ธ
      • ํ‚ค ํƒ€์ž…: ๋ฌธ์ž์—ด๋กœ ๋„˜์–ด์˜ด

      ๐Ÿ’ป new Map(<iterable>)

      • Map ์ƒ์„ฑ์ž๋Š” [key, value] ์Œ๋“ค์˜ ์ดํ„ฐ๋Ÿฌ๋ธ”์„ ๋ฐ›์Œ
      • ์œ„์—์„œ ๋ฐ›์€ [['a', 1], ['b', 2]]๋ฅผ ๋„ฃ์œผ๋ฉด
        • m2.get('a') === 1, m2.get('b') === 2
        • ์‚ฝ์ž… ์ˆœ์„œ ์œ ์ง€
      • ํฌ์ธํŠธ: ์ด ๊ฒฝ์šฐ ํ‚ค๊ฐ€ ๋ฌธ์ž์—ด์ด์ง€๋งŒ, Map์€ ์›๋ž˜ ๋ชจ๋“  ํƒ€์ž…์„ ํ‚ค๋กœ ์“ธ ์ˆ˜ ์žˆ์Œ(๊ฐ์ฒด, ํ•จ์ˆ˜, NaN ๋“ฑ)

      ๐Ÿ’ป Object.fromEntries(m2)

      • ์—ญํ• : [key, value] ์Œ์˜ ์ดํ„ฐ๋Ÿฌ๋ธ”์„ ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด๋กœ ๋ณ€ํ™˜
      • m2๋Š” ์ดํ„ฐ๋Ÿฌ๋ธ”(Map์€ ๊ธฐ๋ณธ ์ˆœํšŒ๊ฐ€ [key, value])์ด๋ฏ€๋กœ ๊ทธ๋Œ€๋กœ ์ „๋‹ฌ ๊ฐ€๋Šฅ
      • ๊ฒฐ๊ณผ: { a: 1, b: 2 }
    • ๋ฐฐ์—ด โ†” Map
      const m3 = new Map([["x", 10], ["y", 20]]);
      const arr = [...m3]; // [ ["x", 10], ["y", 20] ]

๐ŸŒŸ Map ์‹ค์ „ ํ™œ์šฉ ์˜ˆ์ œ

  • API ์‘๋‹ต ์บ์‹œ
    const cache = new Map();
    async function fetchWithCache(url) {
      // ์บ์‹œ์— ์žˆ์œผ๋ฉด ์ฆ‰์‹œ ๋ฐ˜ํ™˜(O(1)))
      if (cache.has(url)) return cache.get(url);
      // ์บ์‹œ์— ์—†์œผ๋ฉด fetch โ†’ JSON ํŒŒ์‹ฑ
      const res = await fetch(url).then(r => r.json());
      // ๊ฒฐ๊ณผ๋ฅผ ์บ์‹œ์— ์ €์žฅ
      cache.set(url, res);
      // ํ˜ธ์ถœ์ž์— ๋ฐ˜ํ™˜
      return res;
    }

    ๐Ÿ’ซ ๋™์ž‘ ํฌ์ธํŠธ

    • cache๋Š” Map<string, any> ์—ญํ• : ํ‚ค๋Š” URL ๋ฌธ์ž์—ด, ๊ฐ’์€ ํŒŒ์‹ฑ๋œ ์‘๋‹ต ๊ฐ์ฒด
    • cache.has(url) โ†’ cache.get(url)์˜ ์กฐํ•ฉ์œผ๋กœ ์บ์‹œ ํžˆํŠธ๋ฅผ O(1)๋กœ ์ฒ˜๋ฆฌ
    • ์ตœ์ดˆ ์š”์ฒญ(๋ฏธ์Šค)์ผ ๋•Œ๋งŒ fetch๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ์‘๋‹ต์„ setํ•˜์—ฌ ๋‹ค์Œ ํ˜ธ์ถœ ์ตœ์ ํ™”
    • Map์„ ์“ฐ๋Š” ์ด์œ : size/has/get/set์ด ๋น ๋ฅด๊ณ , ํ‚ค ์ถฉ๋Œ ์—†์ด ๋ฌธ์ž์—ด ํ‚ค๋ฅผ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉ

    ๐Ÿ’ซ ์‹ค๋ฌด์—์„œ ๋ฐ”๋กœ ์ƒ๊ฐํ•ด์•ผ ํ•  ๊ฒƒ๋“ค

    1. ์š”์ฒญ ์ค‘๋ณต(๋™์‹œ์„ฑ) ์ด์Šˆ
      ๋™์‹œ์— ๊ฐ™์€ URL์ด ์—ฌ๋Ÿฌ ๋ฒˆ ํ˜ธ์ถœ๋˜๋ฉด, ์œ„ ์ฝ”๋“œ์—์„  ์ค‘๋ณต fetch๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Œ
      โ†’ "์ง„ํ–‰ ์ค‘์ธ ํ”„๋ผ๋ฏธ์Šค"๋ฅผ ์บ์‹œ์— ์ €์žฅํ•˜๋ฉด ํ•ด๊ฒฐ๋จ
      const cache = new Map();
      async function fetchWithCache(url) {
        if (cache.has(url)) return cache.get(url); // ๊ฐ’ ๋˜๋Š” ํ”„๋ผ๋ฏธ์Šค ๋ชจ๋‘ ๋ฐ˜ํ™˜ ๊ฐ€๋Šฅ 
        const p = fetch(url)
        	.then(r => {
             if (!r.ok) throw new Error(`HTTP ${r.status}`);
             return r.json();
           })
        	.then(data => {
             cache.set(url, data); // ์™„๋ฃŒ ํ›„ ์‹ค์ œ ๋ฐ์ดํ„ฐ๋กœ ์น˜ํ™˜
             return data;
           })
        	.catch(err => {
             cache.delete(url); // ์‹คํŒจ ์‹œ ์บ์‹œ์—์„œ ์ œ๊ฑฐ (๋ถˆ๋Ÿ‰ ํ”„๋ผ๋ฏธ์Šค ๋‚จ์ง€ ์•Š๊ฒŒ)
             throw err;
           });
        cache.set(url, p); // "์ง„ํ–‰ ์ค‘์ธ ํ”„๋ผ๋ฏธ์Šค" ์บ์‹ฑ โ†’ ์ค‘๋ณต ์š”์ฒญ ๋ฐฉ์ง€
        return p;
      }
    2. ๋งŒ๋ฃŒ(TTL)/๋ฌดํšจํ™”
      ๋ฐ์ดํ„ฐ๊ฐ€ ์˜ค๋ž˜๋˜๋ฉด ๊ฐฑ์‹ ํ•ด์•ผ ํ•จ
      โ†’ ๊ฐ„๋‹จํžˆ ํƒ€์ž„์Šคํƒฌํ”„๋ฅผ ํ•จ๊ป˜ ์ €์žฅํ•˜๊ฑฐ๋‚˜ LRU + TTL์„ ๋„์ž…ํ•จ
      const cache = new Map(); // url -> { data, ts }
      const TTL = 60_000; // 60s
      async function fetchWithTTL(url) {
        const hit = cache.get(url);
        const now = Date.now();
        if (hit && now - hit.ts < TTL) return hit.data;
        const data = await fetch(url).then(r => r.json());
        cache.set(url, { data, ts: now });
        return data;
      }
    3. ํ‚ค ์„ค๊ณ„
      • ์ฟผ๋ฆฌ์ŠคํŠธ๋ง์ด ๋‹ค๋ฅด๋ฉด ๋‹ค๋ฅธ ๋ฆฌ์†Œ์Šค๋กœ ๊ฐ„์ฃผ: ?page=1 vs. ?page=2
      • POST/ํ—ค๋”/๋ฐ”๋””์— ๋”ฐ๋ผ ๊ฒฐ๊ณผ๊ฐ€ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Œ โ†’ ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ง๋ ฌํ™”ํ•ด ํ‚ค๋กœ ํฌํ•จํ•ด์•ผ ํ•จ
      • ์ธ์ฆ ํ† ํฐ, ๋กœ์ผ€์ผ ๋“ฑ๋„ ์บ์‹œ ํ‚ค์— ๋ฐ˜์˜ ํ•„์š”
    4. ์—๋Ÿฌ ์ฒ˜๋ฆฌ
      • response.ok ์ฒดํฌ, ๋„คํŠธ์ฟผ์œผ ์—๋Ÿฌ ํ•ธ๋“ค๋ง, ์‹คํŒจ ์‹œ ์žฌ์‹œ๋„/๋ฐฑ์˜คํ”„ ์ „๋žต ๊ณ ๋ ค
      • ์‹คํŒจ ์‘๋‹ต์„ ์บ์‹œํ•˜๋ฉด ์•ˆ ๋˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Œ โ†’ ์‹คํŒจ ์‹œ ์บ์‹œ ์ œ๊ฑฐ
    5. ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ
      • ๋ฌดํ•œํžˆ ์Œ“์ด์ง€ ์•Š๊ฒŒ ์ตœ๋Œ€ ์šฉ๋Ÿ‰์„ ๋‘๊ณ  LRU๋กœ ์ œ๊ฑฐ
      • ํƒญ ์ด๋™/์•ฑ ์ข…๋ฃŒ ์‹œ ์‚ฌ๋ผ์ง€๋Š” ํ”„๋กœ์„ธ์Šค ๋ฉ”๋ชจ๋ฆฌ ์บ์‹œ์ž„์„ ์ดํ•ดํ•ด์•ผ ํ•จ (์˜์†์„ฑ ํ•„์š”ํ•˜๋ฉด IndexedDB/Cache Storage ๊ณ ๋ ค)
    6. ๋ณด์•ˆ/๋ฏผ๊ฐ ๋ฐ์ดํ„ฐ
      • ์‚ฌ์šฉ์ž๋ณ„๋กœ ๋‹ค๋ฅธ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ค๋Š” ๊ฐœ์ธํ™” ๋ฐ์ดํ„ฐ๋Š” ์‚ฌ์šฉ์ž ์ปจํ…์ŠคํŠธ ๋‹จ์œ„๋กœ ๋ถ„๋ฆฌํ•˜๊ฑฐ๋‚˜ ์บ์‹œ ๊ธˆ์ง€

    ๐Ÿ’ซ ์–ธ์ œ ์œ ์šฉํ•œ๊ฐ€?

    • ๋™์ผ URL์„ ์งง์€ ์‹œ๊ฐ„ ์•ˆ์— ๋ฐ˜๋ณต ํ˜ธ์ถœํ•˜๋Š” ํ™”๋ฉด (๋ฆฌ์ŠคํŠธ ์žฌ๋ฐฉ๋ฌธ, ํƒญ ์ „ํ™˜, ๋ฌดํ•œ ์Šคํฌ๋กค์˜ ์žฌ์š”์ฒญ ๋“ฑ)
    • ์„œ๋ฒ„์— ์บ์‹œ ํ—ค๋”๊ฐ€ ์—†๊ฑฐ๋‚˜, ํด๋ผ์ด์–ธํŠธ ๋ ˆ๋ฒจ์—์„œ ๋” ๊ณต๊ฒฉ์ ์œผ๋กœ ์ตœ์ ํ™”ํ•˜๊ณ  ์‹ถ์„ ๋•Œ
  • ๋“ฑ์žฅ ๋นˆ๋„/์นด์šดํŒ…
    function countBy(arr) {
      const map = new Map();
      for (const v of arr) map.set(v, (map.get(v) ?? 0) + 1);
      return map;
    }

    ๐Ÿ’ซ ์ฝ”๋“œ์˜ ์—ญํ• 

    • ์ž…๋ ฅ ๋ฐฐ์—ด arr์˜ ๊ฐ’์„ ๊ฐ ํ‚ค๋กœ, ๊ทธ ๋“ฑ์žฅ ํšŸ์ˆ˜๋ฅผ ๊ฐ’์œผ๋กœ ๊ฐ–๋Š” Map์„ ๋งŒ๋“ค์–ด ๋ฐ˜ํ™˜ํ•จ
    • ๊ฒฐ๊ณผ Map์˜ ์ˆœ์„œ๋Š” ํ•ด๋‹น ๊ฐ’์ด ์ฒ˜์Œ ๋“ฑ์žฅํ•œ ์ˆœ์„œ๋ฅผ ๋”ฐ๋ฆ„ (์‚ฝ์ž… ์ˆœ์„œ ์œ ์ง€)

    ๐Ÿ’ซ ๋‹จ๊ณ„๋ณ„ ๋™์ž‘

    1. const map = new Map();
      • ๋นˆ ์นด์šดํŠธ ํ…Œ์ด๋ธ” ์ƒ์„ฑ
    2. for (const v of arr)
      • ๋ฐฐ์—ด์„ ์ˆœ์ฐจ ์ˆœํšŒ
    3. map.set(v, (map.get(v) ?? 0) + 1);
      • ํ˜„์žฌ ๊ฐ’ v์˜ ๊ธฐ์กด ์นด์šดํŠธ๋ฅผ ์ฝ๊ณ (map.get(v))
      • ์—†์œผ๋ฉด undefined์ด๋ฏ€๋กœ ๋„ ๋ณ‘ํ•ฉ ์—ฐ์‚ฐ์ž(Nullish Coalescing Operator) ??๋กœ 0์„ ๋Œ€์‹  ์‚ฌ์šฉ
      • + 1ํ•ด์„œ ๋‹ค์‹œ ์ €์žฅํ•จ
    4. return map;
      • Map<๊ฐ’, ์นด์šดํŠธ> ๋ฐ˜ํ™˜

    ๐Ÿ’ซ ์ž์ฃผ ํ•˜๋Š” ์‹ค์ˆ˜

    • map.set(v, (map.get(v) || 0) + 1)
      • ||๋Š” 0์ด๋‚˜ ""(๋นˆ ๋ฌธ์ž์—ด)๋„ "์—†์Œ"์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋ฏ€๋กœ ๋น„์ถ”์ฒœ
      • ์ด ์ฝ”๋“œ๋Š” ํ˜„์žฌ ๋งฅ๋ฝ์—์„œ๋Š” ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•˜์ง€๋งŒ ์Šต๊ด€ํ™”ํ•˜๋ฉด ๋‹ค๋ฅธ ์ƒํ™ฉ์—์„œ ๋ฒ„๊ทธ๋ฅผ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ์Œ
      • ๋”ฐ๋ผ์„œ ํ•ญ์ƒ ??์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์•ˆ์ „ํ•จ
  • DOM/๊ฐ์ฒด โ†” ๋ฐ์ดํ„ฐ ๋งคํ•‘
    const dataByEl = new Map();
    function bind(el, data) { dataByEl.set(el, data); }
    function getData(el) { return dataByEl.get(el); }

    ๐Ÿ’ซ ์—ญํ• 

    • dataByEl
      • Map<Node, any> ์—ญํ• ์„ ํ•จ
      • ํ‚ค: DOM ์š”์†Œ(๋˜๋Š” ์ž„์˜์˜ ๊ฐ์ฒด) ์ฐธ์กฐ
      • ๊ฐ’: ๊ทธ ์š”์†Œ์— ์—ฐ๊ฒฐํ•ด ๋‘๊ณ  ์‹ถ์€ ์ž„์˜์˜ ๋ฐ์ดํ„ฐ(์ƒํƒœ, ์˜ต์…˜, ๋ฉ”ํƒ€์ •๋ณด ๋“ฑ)
    • bind(el, data): ์š”์†Œ el์— data๋ฅผ ๋ถ™์ž„(Map์— ์ €์žฅ)
    • getData(el): ๋‚˜์ค‘์— ๊ฐ™์€ ์š”์†Œ ์ฐธ์กฐ๋กœ ์ฆ‰์‹œ ๊บผ๋ƒ„(O(1))

    ๐Ÿ’ซ ์™œ Map์œผ๋กœ ํ• ๊นŒ?

    • ๊ฐ์ฒด/ํ•จ์ˆ˜/DOM ๋“ฑ ๋น„๋ฌธ์ž์—ด์„ ํ‚ค๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ(๋ฌธ์ž์—ด ํ‚ค ๊ฐ•์ œ ๋ณ€ํ™˜ ์—†์Œ)
    • ์š”์†Œ์— ์ง์ ‘ ์ปค์Šคํ…€ ํ”„๋กœํผํ‹ฐ๋ฅผ ๋‹ฌ์ง€ ์•Š์•„๋„ ๋จ โ†’ ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ/DOM์„ ์˜ค์—ผ์‹œํ‚ค์ง€ ์•Š์Œ
    • ์‚ฝ์ž…ยท์กฐํšŒ๊ฐ€ ํ‰๊ท  O(1), ์ˆœํšŒ ํ•„์š” ์—†์ด ๋น ๋ฆ„

    ๐Ÿ’ซ ์‚ฌ์šฉ ์˜ˆ์‹œ

    // 1) ์ƒํƒœ ์—ฐ๊ฒฐ
    const el = document.querySelector('#btn');
    bind(el, { clicked: 0, color: 'teal' });
    // 2) ์ด๋ฒคํŠธ์—์„œ ์ƒํƒœ ์—…๋ฐ์ดํŠธ
    el.addEventListener('click', () => {
      const st = getData(el);
      st.clicked += 1;
      console.log(st.clicked);
    });

    ๐Ÿ’ซ ์‹ค์ „ ํŒ

    1. GC(๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜)๊นŒ์ง€ ์‹ ๊ฒฝ ์“ด๋‹ค๋ฉด WeakMap์ด ๋” ์ ํ•ฉ
      • DOM/๊ฐ์ฒด๊ฐ€ ์–ด๋””์—์„œ๋„ ๋” ์ด์ƒ ์ฐธ์กฐ๋˜์ง€ ์•Š์œผ๋ฉด WeakMap์€ ์—”ํŠธ๋ฆฌ๋ฅผ ์ž๋™์œผ๋กœ ์ •๋ฆฌํ•จ(์•ฝํ•œ ์ฐธ์กฐ)
      • WeakMap: ํ‚ค๊ฐ€ ๋ฐ˜๋“œ์‹œ ๊ฐ์ฒด ๋˜๋Š” DOM์ด์–ด์•ผ ํ•˜๊ณ , ๊ทธ ํ‚ค ๊ฐ์ฒด๊ฐ€ ์–ด๋””์—์„œ๋„ ๋” ์ด์ƒ ์ฐธ์กฐ๋˜์ง€ ์•Š์œผ๋ฉด ํ•ด๋‹น ์—”ํŠธ๋ฆฌ๊ฐ€ ์ž๋™์œผ๋กœ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜ ๋˜๋Š” Map
        // ํ‚ค๊ฐ€ ๋ฐ˜๋“œ์‹œ ๊ฐ์ฒด/DOM์ด์–ด์•ผ ํ•จ. size/์ˆœํšŒ ๋ถˆ๊ฐ€(์˜๋„์ )
        const dataByEl new WeakMap();
        function bind(el, data) { dataByEl.set(el, data); }
        function getData(el) { return dataByEl.get(el); }
        function hasData(el) { return dataByEl.has(el); }
        โžก๏ธ ์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ/ํŒŒ๊ดด๊ฐ€ ์žฆ๊ณ , DOM์ด ์ œ๊ฑฐ๋˜๋ฉด ์ž๋™ ์ •๋ฆฌ๋˜๊ธธ ์›ํ•  ๋•Œ(๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐฉ์ง€) ์‚ฌ์šฉํ•จ
    2. ํ‚ค๋Š” "์ฐธ์กฐ ๋™์ผ์„ฑ"
      ๋ชจ์–‘์ด ๊ฐ™์€ ๋‹ค๋ฅธ ์š”์†Œ/๊ฐ์ฒด๋ฅผ ์ƒˆ๋กœ ๋งŒ๋“ค์–ด๋„ ๋‹ค๋ฅธ ํ‚ค์ž„
    3. ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ ์˜ˆ์‹œ
      • ๋‹จ์ˆœ ๊ฐ’: { opened: true }, { role: 'dialog' }
      • ๋ณตํ•ฉ ์ƒํƒœ: { timer, cleanup, options }
      • ์บ์‹œ: { measuredRect, lastComputedAt }
    4. ์ง์ ‘ ํ”„๋กœํผํ‹ฐ๋กœ ๋ถ™์ด๋Š” ๋ฐฉ์‹๊ณผ ๋น„๊ต
      // ์•ˆํ‹ฐํŒจํ„ด(๊ถŒ์žฅ X): DOM์„ ์˜ค์—ผ์‹œํ‚ค๊ณ  ํ‚ค ์ถฉ๋Œ ์œ„ํ—˜
      el.__myData = { ... };
      โžก๏ธ ์Šคํƒ€์ผ/๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ถฉ๋Œ ์œ„ํ—˜, ํƒ€์ž… ์•ˆ์ „์„ฑ/์บก์Аํ™” ๋–จ์–ด์ง โ†’ Map/WeakMap ๊ถŒ์žฅ
  • ์–‘๋ฐฉํ–ฅ ๋งต (๊ฐ’โ†”ํ‚ค ์—ญ์กฐํšŒ)
    class BiMap {
      #kv = new Map(); // key -> value
      #vk = new Map(); // value -> key
      
      // ์Œ ์ถ”๊ฐ€/๊ฐฑ์‹ 
      set(k, v) { this.#kv.set(k, v); this.#vk.set(v, k); }
      
      // key -> value
      getByKey(k) { return this.#kv.get(k); }
      
      // value -> key
      getByValue(v) { return this.#vk.get(v); }
      
      // key์™€ ๊ทธ์— ๋Œ€์‘ํ•˜๋Š” value ๋ชจ๋‘ ์ œ๊ฑฐ
      deleteByKey(k) {
        const v = this.#kv.get(k);
        this.#kv.delete(k);
        this.#vk.delete(v);
      }
    }

    ๐Ÿ’ซ ์—ญํ• 

    • ๋‚ด๋ถ€์— Map ๋‘ ๊ฐœ๋ฅผ ๋‘ 
      • #kv: key โ†’ value
      • #vk: value โ†’ key
    • set(k, v) ๋•Œ ๋‘ ๋งต์„ ๋™์‹œ์— ๊ฐฑ์‹ ํ•ด ๋‘ ๋ฐฉํ–ฅ์˜ ์กฐํšŒ๋ฅผ ๋ชจ๋‘ ๋น ๋ฅด๊ฒŒ ํ•จ
    • getByKey, getByValue๋กœ ์–‘์ชฝ ๋ฐฉํ–ฅ์„ O(1)๋กœ ์กฐํšŒํ•จ
    • deleteByKey๋Š” ํ•œ์ชฝ์—์„œ ์ง€์šฐ๋ฉด ๋ฐ˜๋Œ€ํŽธ๋„ ํ•จ๊ป˜ ์ง€์›Œ ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•จ

    ๐Ÿ’ซ ๋ฌธ๋ฒ•/๋””์ž์ธ ํฌ์ธํŠธ

    • #kv, #vk๋Š” ํ”„๋ผ์ด๋น— ํ•„๋“œ(ํด๋ž˜์Šค ์™ธ๋ถ€์—์„œ ์ ‘๊ทผ ๋ถˆ๊ฐ€)
    • Map์˜ ์‚ฝ์ž… ์ˆœ์„œ ์œ ์ง€๋‚˜ size, has ๋“ฑ ์ด์  ๊ทธ๋Œ€๋กœ ํ™œ์šฉ ๊ฐ€๋Šฅ
    • ์ฐธ์กฐ ๋™์ผ์„ฑ์ด ์ ์šฉ๋จ: ๊ฐ์ฒด/ํ•จ์ˆ˜๋ฅผ ํ‚ค, ๊ฐ’์œผ๋กœ ์“ฐ๋ฉด ๊ฐ™์€ ๋ชจ์–‘์ด์–ด๋„ ๊ฐ™์€ ์ฐธ์กฐ์—ฌ์•ผ ๊ฐ™์€ ๊ฒƒ์œผ๋กœ ์ธ์‹ํ•จ

    ๐Ÿ’ซ ๋™์ž‘ ์˜ˆ์‹œ

    const bm = new BiMap();
    bm.set('KR', 82);
    bm.set('US', 1);
    bm.getByKey('KR'); // 82
    bm.getByValue(1); // 'US'
    bm.deleteByValue(1); // value ๊ธฐ์ค€ ์‚ญ์ œ๋„ ๊ฐ€๋Šฅ
    bm.hasKey('US'); // false

    ๐Ÿ’ซ ์–ธ์ œ ์œ ์šฉํ• ๊นŒ?

    • ์ฝ”๋“œ/๋ผ๋ฒจ ์ƒํ˜ธ ๋ณ€ํ™˜: ๊ตญ๊ฐ€ ์ฝ”๋“œ โ†” ์ „ํ™” ์ฝ”๋“œ, MIME โ†” ํ™•์žฅ์ž
      ๐Ÿ” MIME: ํŒŒ์ผ/๋ฐ์ดํ„ฐ์˜ ํ˜•์‹(๋ฏธ๋””์–ด ํƒ€์ž…)์„ ํ‘œ์ค€ ๋ฌธ์ž์—ด๋กœ ๋‚˜ํƒ€๋‚ด๋Š” ๊ทœ์น™
    • ID โ†” ์ธ์Šคํ„ด์Šค ์—ญ์ฐธ์กฐ: ๋ฆฌ์†Œ์Šค ํ’€, ์†Œ์ผ“/์„ธ์…˜ ๋งคํ•‘
    • ํ† ํฐ โ†” ์‚ฌ์šฉ์ž ๋งคํ•‘ ๋“ฑ ์—ญ์กฐํšŒ๊ฐ€ ๋นˆ๋ฒˆํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค

๐ŸŒŸ Set

  • ๊ฐœ๋…
    • ์ค‘๋ณต ์—†๋Š” ๊ฐ’์˜ ๋ชจ์Œ(์ง‘ํ•ฉ) ์ปฌ๋ ‰์…˜
    • ์‚ฝ์ž… ์ˆœ์„œ๋ฅผ ์œ ์ง€ํ•˜๋ฉฐ, ๊ฐ’ ์กด์žฌ ํ™•์ธ/์ถ”๊ฐ€/์‚ญ์ œ๊ฐ€ ๋น ๋ฆ„
  • ์–ธ์ œ ์“ฐ๋‚˜?

    • ๋ฐฐ์—ด ์ค‘๋ณต ์ œ๊ฑฐ

      // ์ˆซ์ž/๋ฌธ์ž์—ด ์ค‘๋ณต ์ œ๊ฑฐ
      const arr = [1, 2, 2, 3, 3, 3];
      const unique = [...new Set(arr)];
      console.log(unique); // [1, 2, 3]
      
      // NaN๋„ ํ•œ ๋ฒˆ๋งŒ ๋‚จ์Œ (Set์€ SameValueZero ๊ทœ์น™ ์ ์šฉ)
      console.log([...new Set([NaN, NaN])]); // [NaN]
      
      // ๊ฐ์ฒด๋Š” '์ฐธ์กฐ ๋™์ผ์„ฑ' ๊ธฐ์ค€
      const a = { id: 1 }, b = { id: 1 };
      console.log([...new Set([a, a, b])].length); // 2
      // -> a๋Š” ๊ฐ™์€ ์ฐธ์กฐ 1๊ฐœ๋กœ ํ•ฉ์ณ์ง€๊ณ , b๋Š” ๋ณ„๊ฐœ
      1. ์ˆซ์ž/๋ฌธ์ž์—ด ์ค‘๋ณต ์ œ๊ฑฐ
        • new Set(arr)๋กœ ๋ฐฐ์—ด์„ Set์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋ฉด์„œ ์ค‘๋ณต์„ ์ž๋™ ์ œ๊ฑฐํ•จ
        • [...] ์Šคํ”„๋ ˆ๋“œ๋กœ ๋‹ค์‹œ ๋ฐฐ์—ด๋กœ ํŽผ์นจ โ†’ Set์€ ์ดํ„ฐ๋Ÿฌ๋ธ”์ด์ง€๋งŒ ๋ฐฐ์—ด ๋ฉ”์„œ๋“œ๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ
        • ์‹œ๊ฐ„ ๋ณต์žก๋„(ํ‰๊ท ): Set ๋นŒ๋“œ O(n), ๋ฉ”๋ชจ๋ฆฌ O(n)
      2. NaN๋„ ํ•œ ๋ฒˆ๋งŒ ๋‚จ์Œ
        • Set์€ ๊ฐ’ ๋น„๊ต์— SameValueZero๋ฅผ ์‚ฌ์šฉํ•จ โ†’ NaN์„ ์„œ๋กœ ๊ฐ™์€ ๊ฐ’์œผ๋กœ ๋ด„
        • ๊ทธ๋ž˜์„œ NaN์„ ์—ฌ๋Ÿฌ ๋ฒˆ ๋„ฃ์–ด๋„ ์ค‘๋ณต์œผ๋กœ ํŒ๋‹จ๋˜์–ด 1๊ฐœ๋งŒ ์œ ์ง€๋จ
      3. ๊ฐ์ฒด๋Š” '์ฐธ์กฐ ๋™์ผ์„ฑ' ๊ธฐ์ค€
        • ๊ฐ์ฒด๋Š” ๋ชจ์–‘์ด ๊ฐ™์•„๋„ ๋‹ค๋ฅธ ์ฐธ์กฐ๋ฉด ๋‹ค๋ฅธ ๊ฐ’์ž„
        • a๋Š” ๊ฐ™์€ ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ๋‘ ๋ฒˆ ๋„ฃ์—ˆ์œผ๋ฏ€๋กœ 1๊ฐœ๋กœ ํ•ฉ์ณ์ง
        • b๋Š” a์™€ ๋‹ค๋ฅธ ๊ฐ์ฒด๋ผ ๋ณ„๋„ ์›์†Œ๋กœ ๋‚จ์•„ ์ด 2๊ฐœ๊ฐ€ ๋จ
    • ๋ฐฉ๋ฌธ ์ฒดํฌ/ํ† ๊ธ€

      // ์„ ํƒ/์ฆ๊ฒจ์ฐพ๊ธฐ/๋ฐฉ๋ฌธ ์—ฌ๋ถ€ ํ† ๊ธ€
      const selected = new Set();
      
      function toggle(id) {
        if (selected.has(id)) selected.delete(id);
        else selected.add(id);
      }
      
      toggle('p1'); // ์„ ํƒ
      toggle('p2'); // ์„ ํƒ
      toggle('p1'); // ํ•ด์ œ
      console.log([...selected]); // ['p2']
      
      // "์ฒ˜์Œ ๋ฐฉ๋ฌธ์ธ๊ฐ€?" ๋ฐฉ๋ฌธ ์ฒดํฌ
      const seen = new Set();
      function isFirstVisit(key) {
        if (seen.has(key)) return false; // ์ด๋ฏธ ๋ณธ ์  ์žˆ์Œ
        seen.add(key); // ์ฒ˜์Œ ๋ณด๋ฉด ๋“ฑ๋ก
        return true; // ์ฒ˜์Œ ๋ฐฉ๋ฌธ
      }
      console.log(isFirstVisit('A')); // true
      console.log(isFirstVisit('A')); // false
      1. ์„ ํƒ/์ฆ๊ฒจ์ฐพ๊ธฐ ํ† ๊ธ€ ์˜ˆ์ œ
        • selected๋Š” ์„ ํƒ๋œ ํ•ญ๋ชฉ๋“ค์˜ ์ง‘ํ•ฉ์ž„
        • toggle(id)๋Š” ๊ฐ™์€ ID๋ฅผ ์—†์œผ๋ฉด ์ถ”๊ฐ€, ์žˆ์œผ๋ฉด ์ œ๊ฑฐํ•˜์—ฌ ํ† ๊ธ€ํ•จ
        • selected.has(id)๋กœ ํฌํ•จ ์—ฌ๋ถ€๋ฅผ O(1)๋กœ ๊ฒ€์‚ฌํ•จ
      2. "์ฒ˜์Œ ๋ฐฉ๋ฌธ์ธ๊ฐ€?" ๋ฐฉ๋ฌธ ์ฒดํฌ
        • ์–ด๋–ค key(์˜ˆ: ์‚ฌ์šฉ์ž ID, ํŽ˜์ด์ง€ ID)๋ฅผ ํ•œ ๋ฒˆ์ด๋ผ๋„ ๋ดค๋Š”์ง€ ๊ธฐ๋กํ•จ
        • ์ฒ˜์Œ์ด๋ฉด true, ์ดํ›„์—๋Š” ํ•ญ์ƒ false
    • ์ˆ˜ํ•™์  ์ง‘ํ•ฉ ์—ฐ์‚ฐ(ํ•ฉ/๊ต/์ฐจ/๋Œ€์นญ์ฐจ) ๊ตฌํ˜„

      const A = new Set([1, 2, 3]);
      const B = new Set([3, 4, 5]);
      
      // ํ•ฉ์ง‘ํ•ฉ: A โˆช B
      const union = new Set([...A, ...B]);
      console.log([...union]); // [1, 2, 3, 4, 5]
      
      // ๊ต์ง‘ํ•ฉ: A โˆฉ B
      const intersection = new Set([...A].filter(x => B.has(x)));
      console.log([...intersection]); // [3]
      
      // ์ฐจ์ง‘ํ•ฉ:  A \ B  (A์—๋Š” ์žˆ๊ณ  B์—๋Š” ์—†๋Š” ์›์†Œ)
      const difference = new Set([...A].filter(x => !B.has(x)));
      console.log([...difference]); // [1, 2]
      
      // ๋Œ€์นญ์ฐจ: (A \ B) โˆช (B \ A)
      const symmetricDiff = new Set([
        ...[...A].filter(x => !B.has(x)),
        ...[...B].filter(x => !A.has(x)),
      ]);
      console.log([...symmetricDiff]); // [1, 2, 4, 5]
      1. ํ•ฉ์ง‘ํ•ฉ (A โˆช B)
        • ...A, ...B๋กœ ๋‘ ์ง‘ํ•ฉ์„ ํŽผ์ณ์„œ ํ•˜๋‚˜์˜ ๋ฐฐ์—ด๋กœ ๋งŒ๋“  ๋’ค new Set(...)์— ๋„ฃ์–ด ์ค‘๋ณต์„ ์ œ๊ฑฐํ•จ
        • ์‹œ๊ฐ„๋ณต์žก๋„(ํ‰๊ท ): O(|A| + |B|)
      2. ๊ต์ง‘ํ•ฉ (A โˆฉ B)
        • A์˜ ์›์†Œ ์ค‘ B์— ์กด์žฌํ•˜๋Š” ๊ฒƒ๋งŒ ๊ฑธ๋Ÿฌ์„œ Set์œผ๋กœ ์ƒ์„ฑํ•จ
        • ํ•ต์‹ฌ์€ B.has(x)๊ฐ€ ํ‰๊ท  O(1)์ด๋ผ ์ „์ฒด ์‹œ๊ฐ„๋ณต์žก๋„๋Š” O(|A|)
      3. ์ฐจ์ง‘ํ•ฉ (A \ B)
        • A์—์„œ B์— ์—†๋Š” ๊ฒƒ๋งŒ ๋‚จ๊น€
        • ์‹œ๊ฐ„๋ณต์žก๋„(ํ‰๊ท ): O(|A|)
      4. ๋Œ€์นญ์ฐจ (A โ–ณ B)
        • ์–‘์ชฝ ์ฐจ์ง‘ํ•ฉ์„ ํ•ฉ์ณ์„œ Set์— ๋„ฃ์–ด ์ค‘๋ณต ์ œ๊ฑฐ
        • ์‹œ๊ฐ„๋ณต์žก๋„(ํ‰๊ท ): O(|A| + |B|)
  • ์ฃผ์š” ํŠน์ง•
    • ํฌ๊ธฐ: set.size
    • ์กด์žฌ ํ™•์ธ: set.has(value)
    • ์ถ”๊ฐ€: set.add(value) (์ด๋ฏธ ์žˆ์œผ๋ฉด ๋ณ€ํ™” ์—†์Œ)
    • ์‚ญ์ œ/์ดˆ๊ธฐํ™”: set.delete(value), set.clear()
    • ์ˆœํšŒ: for (const v of set), set.forEach(v => ...)
    • ๊ฐ’ ๋™๋“ฑ์„ฑ: SameValueZero (NaN๋„ ๋™์ผ ์ทจ๊ธ‰)
  • ๋ฐฐ์—ด๊ณผ์˜ ์ƒํ˜ธ ๋ณ€ํ™˜

    const arr = [1, 1, 2, 3];
    const unique = [...new Set(arr)]; // [1, 2, 3]
    
    const s2 = new Set(arr);
    const backToArray = Array.from(s2);

    ๐Ÿ” Array.from

    1. ์ •์˜

    • ์ดํ„ฐ๋Ÿฌ๋ธ”(iterable) ๋˜๋Š” ์œ ์‚ฌ ๋ฐฐ์—ด(array-like)์„ ์ง„์งœ ๋ฐฐ์—ด๋กœ ๋ฐ˜ํ™˜ํ•จ
      • ์ดํ„ฐ๋Ÿฌ๋ธ”: Set, Map, ๋ฌธ์ž์—ด, ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ๋“ฑ Symbol.iterator์ด ์žˆ๋Š” ๊ฒƒ
      • ์œ ์‚ฌ ๋ฐฐ์—ด: length์™€ ์ธ๋ฑ์Šค ํ”„๋กœํผํ‹ฐ๊ฐ€ ์žˆ๋Š” ๊ฐ์ฒด(์˜ˆ: arguments, DOM NodeList ๋“ฑ)

    2. ์‹œ๊ทธ๋‹ˆ์ฒ˜

    Array.from(source, mapFn?, thisArg?)
    • source: ์ดํ„ฐ๋Ÿฌ๋ธ”/์œ ์‚ฌ ๋ฐฐ์—ด
    • mapFn(value, index): ์ƒ์„ฑํ•˜๋ฉด์„œ ๋งคํ•‘(์„ฑ๋Šฅยท๋ฉ”๋ชจ๋ฆฌ ์œ ๋ฆฌ)
    • thisArg: mapFn ๋‚ด๋ถ€์˜ this

    3. ์˜ˆ์ œ ๋ชจ์Œ

    1) Set/Map โ†’ Array

    const s = new Set([1, 2, 3]);
    Array.from(s); // [1, 2, 3]
    const m = new Map([['a', 1], ['b', 2]]);
    Array.from(m); // [['a', 1], ['b', 2]]
    Array.from(m, ([k, v]) => k); // ['a', 'b'] (ํ‚ค๋งŒ)

    2) ์œ ์‚ฌ ๋ฐฐ์—ด โ†’ Array

    function f() {
      const args = Array.from(arguments); // ์ง„์งœ ๋ฐฐ์—ด
      // [...arguments]๋Š” ์ผ๋ถ€ ํ™˜๊ฒฝ์—์„œ ์‹คํŒจ(์ดํ„ฐ๋Ÿฌ๋ธ”์ด ์•„๋‹ ์ˆ˜ ์žˆ์Œ)
    }
    const nodeList = document.querySelectorAll('div'); // ์œ ์‚ฌ ๋ฐฐ์—ด + iterable
    Array.from(nodeList, el => el.textContent.trim());

    3) ๋ฌธ์ž์—ด โ†’ ๋ฌธ์ž ๋ฐฐ์—ด

    Array.from('hello'); // ['h', 'e', 'l', 'l', 'o']

    4) ์ƒ์„ฑ + ๋งคํ•‘ ํ•œ ๋ฒˆ์— (์„ฑ๋Šฅ ์ด์ )

    Array.from({ length: 5 }, (_, i) => i * i); // [0, 1, 4, 9, 16]

    4. ์Šคํ”„๋ ˆ๋“œ(...)์™€ ์ฐจ์ด

    ์ƒํ™ฉArray.from์Šคํ”„๋ ˆ๋“œ([...src])
    Set/Map/๋ฌธ์ž์—ด๊ฐ€๋Šฅ๊ฐ€๋Šฅ
    ์œ ์‚ฌ ๋ฐฐ์—ด(iterator ์—†์Œ)๊ฐ€๋Šฅ๋ถˆ๊ฐ€๋Šฅ(TypeError)
    ์ƒ์„ฑ ์‹œ ๋งคํ•‘mapFn ์ œ๊ณต๋งŒ๋“ค๊ณ  ๋‚˜์„œ map ํ•œ ๋ฒˆ ๋”
    ์œ ๋‹ˆ์ฝ”๋“œ(๋ฌธ์ž ๋‹จ์œ„)๋ฌธ์ž์—ด ์ดํ„ฐ๋ ˆ์ดํ„ฐ๋กœ OK๋ฌธ์ž์—ด ์ดํ„ฐ๋ ˆ์ดํ„ฐ๋กœ OK
    • ์œ ์‚ฌ ๋ฐฐ์—ด์ธ๋ฐ iterator๊ฐ€ ์—†๋Š” ๊ฐ์ฒด ์˜ˆ์‹œ
      const arrayLike = { 0: 'a', 1: 'b', length: 2 }; // iterator ์—†์Œ
      Array.from(arrayLike); // ['a', 'b'] โœ… ๊ฐ€๋Šฅ (length/์ธ๋ฑ์Šค๋ฅผ ์ฝ์–ด ๋ฐฐ์—ด ์ƒ์„ฑ)
      [...arrayLike]; // โŒ TypeError: arrayLike is not iterable

    5. ํฌ์†Œ ๋ฐฐ์—ด(sparse) ์ฒ˜๋ฆฌ

    Array.from({ length: 3 }); // [undefined, undefined, undefined]
    • Array.from์€ ์ธ๋ฑ์Šค๋ฅผ 0 ~ length-1๋กœ ์ˆœํšŒํ•˜๋ฉฐ ๋นˆ ์นธ๋„ ์ฑ„์›Œ undefined๊ฐ€ ๋จ
    • ๋ฐ˜๋ฉด ๋ฆฌํ„ฐ๋Ÿด๋กœ ๋งŒ๋“  ํฌ์†Œ ๋ฐฐ์—ด([ , , ])์€ ๊ตฌ๋ฉ์ด ๋‚จ์„ ์ˆ˜ ์žˆ์Œ
    • ์ผ๊ด€์„ฑ์ด ํ•„์š”ํ•˜๋ฉด Array.from์ด ์•ˆ์ „ํ•จ

    6. ์–•์€ ๋ณต์‚ฌ (Shallow)

    ๊ฐ์ฒด ์š”์†Œ๋Š” ์ฐธ์กฐ๋งŒ ๋ณต์‚ฌ๋จ

    const a = [{ x: 1 }];
    const b = Array.from(a);
    b[0].x = 2;
    console.log(a[0].x); // 2 (๊ฐ™์€ ๊ฐ์ฒด ์ฐธ์กฐ)
  • ์ง‘ํ•ฉ ์—ฐ์‚ฐ ์œ ํ‹ธ (์‹ค์ „์—์„œ ์ž์ฃผ ์“ฐ๋Š” ํ˜•ํƒœ)
    const union = (A, B) => new Set([...A, ...B]);
    const intersection = (A, B) => new Set([...A].filter(x => B.has(x)));
    const difference = (A, B) => new Set([...A].filter(x => !B.has(x)));
    const symmetricDiff = (A, B) => new Set([...difference(A, B), ...difference(B, A)]);

๐ŸŒŸ Set ์‹ค์ „ ํ™œ์šฉ ์˜ˆ์ œ

  • ์ค‘๋ณต ์ œ๊ฑฐ & ์œ ๋‹ˆํฌ ๋ณด์žฅ

    const users = ["kim", "lee", "kim"];
    const uniqueUsers = [...new Set(users)]; // ["kim", "lee"]

    ๐Ÿ’ซ ๋‹จ๊ณ„๋ณ„ ๋™์ž‘

    1. new Set(users)
      • ๋ฐฐ์—ด์„ Set์œผ๋กœ ๋ฐ”๊พธ๋Š” ์ˆœ๊ฐ„ ์ค‘๋ณต ์š”์†Œ๊ฐ€ ์ž๋™ ์ œ๊ฑฐ๋จ
      • Set์€ ๊ฐ’ ๋น„๊ต์— SameValueZero ๊ทœ์น™์„ ์จ์„œ NaN๋„ ํ•˜๋‚˜๋กœ ์ทจ๊ธ‰ํ•˜๊ณ , ์‚ฝ์ž… ์ˆœ์„œ๋ฅผ ์œ ์ง€ํ•จ
    2. [...set]
      • Set(์ดํ„ฐ๋Ÿฌ๋ธ”)์„ ๋ฐฐ์—ด๋กœ ๋‹ค์‹œ ํŽผ์นจ
      • ๊ฒฐ๊ณผ: ["kim", "lee"] (์ฒซ ๋“ฑ์žฅ ์ˆœ์„œ ์œ ์ง€)

    ๐Ÿ’ซ ์™œ Set์„ ์“ธ๊นŒ?

    • ๊ฐ„๊ฒฐ + ๋น ๋ฆ„: ํ‰๊ท  O(n)์œผ๋กœ ํ•œ ๋ฒˆ์— ์ฒ˜๋ฆฌํ•จ
    • ์ค‘๋ณต ์ž๋™ ๋ฐฉ์ง€: ๊ฐ™์€ ๊ฐ’์ด ์—ฌ๋Ÿฌ ๋ฒˆ ์™€๋„ ํ•˜๋‚˜๋งŒ ์œ ์ง€ํ•จ
    • ์ˆœ์„œ ๋ณด์กด: ์›๋ž˜ ๋ฐฐ์—ด์—์„œ ์ตœ์ดˆ ๋“ฑ์žฅ ์ˆœ์„œ๊ฐ€ ๊ฒฐ๊ณผ์—๋„ ๋ฐ˜์˜๋จ
  • ๋ฐฉ๋ฌธ/์„ ํƒ ์ƒํƒœ ๊ด€๋ฆฌ (ํ† ๊ธ€)

    const selected = new Set();
    function toggle(id) {
      if (selected.has(id)) selected.delete(id);
      else selected.add(id);
    }

    ๐Ÿ’ซ ์ฝ”๋“œ ์„ค๋ช…

    • selected: ํ˜„์žฌ ์„ ํƒ๋˜์–ด ์žˆ๋Š” ํ•ญ๋ชฉ๋“ค์˜ ์ง‘ํ•ฉ
    • toggle(id)
      • ์ด๋ฏธ ์žˆ์œผ๋ฉด(has) โ†’ ์ œ๊ฑฐ(delete) = ํ•ด์ œ
      • ์—†์œผ๋ฉด โ†’ ์ถ”๊ฐ€(add) = ์„ ํƒ

    ๐Ÿ’ซ ์‚ฌ์šฉ ์˜ˆ (๋™์ž‘ ํ™•์ธ)

    toggle('p1'); // ์„ ํƒ: {'p1'}
    toggle('p2'); // ์„ ํƒ: {'p1', 'p2'}
    toggle('p1'); // ํ•ด์ œ: {'p2'}
    console.log([...selected]); // ['p2']
  • ํ•„ํ„ฐ๋ง ๋ณด์กฐ (ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ/๋ธ”๋ž™๋ฆฌ์ŠคํŠธ)

    const allow = new Set(["/home", "/about"]);
    const filtered = routes.filter(r => allow.has(r.path));

    ๐Ÿ’ซ ์ฝ”๋“œ ์„ค๋ช…

    • allow: ์ ‘๊ทผ/๋…ธ์ถœ์„ ํ—ˆ์šฉํ•  ๊ฒฝ๋กœ๋“ค์˜ ์ง‘ํ•ฉ
    • routes: { path: string, ...} ํ˜•ํƒœ์˜ ๋ผ์šฐํŠธ ๋ฐฐ์—ด์ด๋ผ๊ณ  ๊ฐ€์ •
    • filter: ๊ฐ ๋ผ์šฐํŠธ r์˜ r.path๊ฐ€ allow์— ์žˆ์œผ๋ฉด(has) ๋‚จ๊ธฐ๊ณ , ์—†์œผ๋ฉด ๋ฒ„๋ฆผ
    • ๊ฒฐ๊ณผ filtered: "/home", /"about"๋งŒ ํฌํ•จ๋œ ๋ผ์šฐํŠธ ๋ฐฐ์—ด

    ๐Ÿ’ซ ์‹œ๊ฐ„ ๋ณต์žก๋„

    • ํ•„ํ„ฐ๋ง ์ „์ฒด: O(|routes|) (๊ฐ ์š”์†Œ๋‹น has ํ•œ ๋ฒˆ)
    • ๋ฐฐ์—ด์— includes๋ฅผ ์“ฐ๋ฉด O(|routes|ร—|allow|)๋กœ ์ปค์งˆ ์ˆ˜ ์žˆ์Œ
  • ๊ต์ง‘ํ•ฉ ๊ธฐ๋ฐ˜์˜ ๋น ๋ฅธ ๊ต์ฐจ ์ฒดํฌ

    function hasAnyOverlap(aArr, bArr) {
      const B = new Set(bArr);
      return aArr.some(x => B.has(x));
    }

    ๐Ÿ’ซ ์ฝ”๋“œ ์„ค๋ช…

    • bArr๋ฅผ Set์œผ๋กœ ๋งŒ๋“ค์–ด ํฌํ•จ ๊ฒ€์‚ฌ๋ฅผ O(1)๋กœ ๋น ๋ฅด๊ฒŒ ํ•˜๊ณ ,
    • aArr๋ฅผ ์ˆœํšŒํ•˜๋ฉด์„œ ํ•˜๋‚˜๋ผ๋„ B์— ์žˆ์œผ๋ฉด true๋ฅผ ์ฆ‰์‹œ ๋ฐ˜ํ™˜(์กฐ๊ธฐ ์ข…๋ฃŒ)ํ•จ
    • ๋๊นŒ์ง€ ์—†์œผ๋ฉด false

    ๐Ÿ’ซ ์‹œ๊ฐ„ ๋ณต์žก๋„

    • B.has(x)๋Š” ํ‰๊ท  O(1)
    • ์ „์ฒด ๋ณต์žก๋„๋Š” O(|aArr|+|bArr|)
    • ๋ฐฐ์—ด์— includes๋ฅผ ์“ฐ๋ฉด O(|aArr|ร—|bArr|)๊ฐ€ ๋˜์–ด ์ปค์งˆ์ˆ˜๋ก ๋А๋ ค์ง

    ๐Ÿ’ซ ๋™์ž‘ ์˜ˆ์‹œ

    hasAnyOverlap([1, 2, 3], [4, 5]); // false
    hasAnyOverlap([1, 2, 3], [3, 4, 5]); // true
    hasAnyOverlap(['a', 'b'], ['B']); // false (๋Œ€์†Œ๋ฌธ์ž ๊ตฌ๋ถ„)

๐ŸŒŸ Map vs. Object / Set vs. Array ์„ ํƒ ๊ฐ€์ด๋“œ

์ƒํ™ฉ์ถ”์ฒœ
ํ‚ค๋กœ ๊ฐ์ฒด/ํ•จ์ˆ˜/NaN ๋“ฑ ๋น„๋ฌธ์ž์—ด์„ ์จ์•ผ ํ•จMap
ํ‚ค์˜ ์‚ฝ์ž… ์ˆœ์„œ ์œ ์ง€ + ๋นˆ๋ฒˆํ•œ ์ˆœํšŒMap
ํ‚ค ๊ฐœ์ˆ˜ ์ž์ฃผ ํ™•์ธMap (size)
JSON ์ง๋ ฌํ™” ๊ฐ„๋‹จ/์ •์  ํ‚ค ๊ตฌ์กฐObject
์ค‘๋ณต ์ œ๊ฑฐ/์ง‘ํ•ฉ ์—ฐ์‚ฐ์ด ํ•ต์‹ฌSet
์ธ๋ฑ์Šค ์ ‘๊ทผ/์ •๋ ฌ/์Šฌ๋ผ์ด์‹ฑ ๋“ฑ ๋ฐฐ์—ด ๊ธฐ๋ŠฅArray

0๊ฐœ์˜ ๋Œ“๊ธ€