This page was translated from English by the community. Learn more and join the MDN Web Docs community.

View in English Always switch to English

WeakMap

Baseline Widely available *

This feature is well established and works across many devices and browser versions. Itโ€™s been available across browsers since โจ2015๋…„ 7์›”โฉ.

* Some parts of this feature may have varying levels of support.

WeakMap ์€ ํ‚ค/๊ฐ’ ์Œ์˜ ๋ชจ์Œ์œผ๋กœ, ํ‚ค๋Š” ๋ฐ˜๋“œ์‹œ ๊ฐ์ฒด ๋˜๋Š” ๋“ฑ๋ก๋˜์ง€ ์•Š์€ ์‹ฌ๋ณผ์ด๋ฉฐ ๊ฐ’์€ ์ž„์˜์˜ JavaScript ํƒ€์ž…์ž…๋‹ˆ๋‹ค. WeakMap์€ ํ‚ค์— ๋Œ€ํ•œ ๊ฐ•๋ ฅํ•œ ์ฐธ์กฐ๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ, ๊ฐ์ฒด๊ฐ€ WeakMap์˜ ํ‚ค์— ํฌํ•จ๋˜๋”๋ผ๋„ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜์˜ ๋Œ€์ƒ์ด ๋ฉ๋‹ˆ๋‹ค. ํ‚ค ๊ฐ์ฒด๊ฐ€ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ์— ์˜ํ•ด ์ •๋ฆฌ๋œ ํ›„์—๋Š”, ๋‹ค๋ฅธ ๊ณณ์— ๊ฐ•๋ ฅํ•œ ์ฐธ์กฐ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ•œ, ํ‚ค์— ์—ฐ๊ฒฐ๋๋˜ ๊ฐ’ ๋˜ํ•œ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜ ๋Œ€์ƒ์ด ๋ฉ๋‹ˆ๋‹ค. WeakMap์˜ ํ‚ค๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์œ ์ผํ•œ ์›์‹œ ๊ฐ’์€ ์‹ฌ๋ณผ, ์ •ํ™•ํžˆ๋Š” ๋“ฑ๋ก๋˜์ง€ ์•Š์€ ์‹ฌ๋ณผ์ธ๋ฐ, ๋“ฑ๋ก๋˜์ง€ ์•Š์€ ์‹ฌ๋ณผ์€ ๊ณ ์œ ํ•จ์ด ๋ณด์žฅ๋˜๋ฉฐ ๋‹ค์‹œ ์ƒ์„ฑํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

WeakMap์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ’์ด ํ‚ค๋ฅผ ์ฐธ์กฐํ•˜๋”๋ผ๋„ ํ‚ค ๊ฐ์ฒด์˜ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜์„ ๋ฐฉ์ง€ํ•˜์ง€ ์•Š๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ์ฒด์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ WeakMap์€ ํ‚ค์˜ ํ™œ์„ฑ ์ƒํƒœ๋ฅผ ๊ด€์ฐฐํ•˜๋Š” ๊ฒƒ์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š์œผ๋ฉฐ, ์ด๋Š” WeakMap์˜ ํ‚ค๋ฅผ ์—ด๊ฑฐํ•  ์ˆ˜ ์—†๋Š” ์ด์œ ์ž…๋‹ˆ๋‹ค. ๋งŒ์•ฝ WeakMap์ด ํ‚ค ๋ชฉ๋ก์„ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ์–ด๋–ค ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ–ˆ๋‹ค๋ฉด, ๊ทธ ๋ชฉ๋ก์€ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜ ์ƒํƒœ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์งˆ ๊ฒƒ์ด๋ฏ€๋กœ ๋น„๊ฒฐ์ •์„ฑ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ํ‚ค ๋ชฉ๋ก์ด ํ•„์š”ํ•˜๋ฉด WeakMap ๋Œ€์‹  Map์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ‚ค ๊ธฐ๋ฐ˜ ์ปฌ๋ ‰์…˜ ์•ˆ๋‚ด์„œ์˜ WeakMap ๊ฐ์ฒด ๊ตฌํš์—์„œ WeakMap์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์•Œ์•„๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์„ค๋ช…

WeakMap์˜ ํ‚ค๋Š” ๋ฐ˜๋“œ์‹œ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜ ๊ฐ€๋Šฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ์›์‹œ ๊ฐ’์€ ์ž„์˜๋กœ ์ƒ์„ฑ๋  ์ˆ˜ ์žˆ๊ณ  ์ƒ๋ช… ์ฃผ๊ธฐ๊ฐ€ ๋”ฐ๋กœ ์—†์œผ๋ฏ€๋กœ ํ‚ค๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๊ฐ์ฒด์™€ ๋“ฑ๋ก๋˜์ง€ ์•Š์€ ์‹ฌ๋ณผ์€ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜ ๋Œ€์ƒ์ด๋ฏ€๋กœ ํ‚ค๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์™œ WeakMap์ธ๊ฐ€?

JavaScript์˜ ๋งต API๋Š” 4๊ฐœ์˜ API ๋ฉ”์„œ๋“œ์™€ ์ด๋“ค์ด ๊ณต์œ ํ•˜๋Š” ๋‘ ๊ฐœ์˜ ๋ฐฐ์—ด(ํ‚ค์šฉ ํ•˜๋‚˜, ๊ฐ’์šฉ ํ•˜๋‚˜)์œผ๋กœ๋„ ๊ตฌํ˜„ํ•˜๋ ค๋ฉด ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋งต์— ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ํ‚ค์™€ ๊ฐ’์„ ๋™์‹œ์— ๊ฐ ๋ฐฐ์—ด์˜ ๋์œผ๋กœ ๋„ฃ๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ, ํ‚ค์™€ ๊ฐ’์ด ๋‘ ๋ฐฐ์—ด ๊ฐ๊ฐ์—์„œ ๊ฐ™์€ ์ธ๋ฑ์Šค์— ์œ„์น˜ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋งต์—์„œ ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๋ ค๋ฉด ํ‚ค ๋ฐฐ์—ด์„ ์ˆœํšŒํ•˜๋ฉด์„œ ์ผ์น˜ํ•˜๋Š” ํ•ญ๋ชฉ์„ ์ฐพ๊ณ , ์ด ํ•ญ๋ชฉ์˜ ์ธ๋ฑ์Šค๋กœ ๊ฐ’ ๋ฐฐ์—ด์—์„œ ๊ฐ’์„ ๊ฐ€์ ธ์˜ฌ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด ๊ตฌํ˜„์—๋Š” ๋‘ ๊ฐ€์ง€ ํฐ ๋ถˆํŽธํ•จ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ๊ฐ’์˜ ์„ค์ •๊ณผ ๊ฒ€์ƒ‰์ด O(n)(n์€ ๋งต ํ‚ค์˜ ์ˆ˜)์ž…๋‹ˆ๋‹ค. ๋‘ ์ž‘์—… ๋ชจ๋‘ ์ผ์น˜ํ•˜๋Š” ๊ฐ’์„ ์ฐพ๊ธฐ ์œ„ํ•ด ํ‚ค ๋ชฉ๋ก์„ ์ˆœํšŒํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
  2. ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜์ž…๋‹ˆ๋‹ค. ๋ฐฐ์—ด์€ ๊ฐ ํ‚ค์™€ ๊ฐ ๊ฐ’์— ๋Œ€ํ•œ ์ฐธ์กฐ๊ฐ€ ๋ฌด๊ธฐํ•œ ์œ ์ง€๋˜๋„๋ก ๋ณด์žฅํ•˜๊ธฐ ๋•Œ๋ฌธ์ธ๋ฐ, ์ด ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ ๊ณณ์—์„œ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•˜์ง€ ์•Š๋”๋ผ๋„ ํ‚ค๊ฐ€ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜ ๋Œ€์ƒ์ด ๋˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ๊ฐ’๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค.

๋ฐ˜๋ฉด, WeakMap์—์„œ ํ‚ค ๊ฐ์ฒด๋Š” ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜ ๋˜์ง€ ์•Š๋Š” ํ•œ ์ž์‹ ์˜ ๊ฐ’์„ ๊ฐ•๋ ฅํ•˜๊ฒŒ ์ฐธ์กฐํ•˜๊ณ , ๊ทธ ํ›„์—๋Š” ์•ฝํ•˜๊ฒŒ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ WeakMap์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜์„ ๋ฐฉ์ง€ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ํ‚ค ๊ฐ์ฒด์— ๋Œ€ํ•œ ์ฐธ์กฐ๊ฐ€ ๊ฒฐ๊ตญ ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค.
  • ํ‚ค ๊ฐ์ฒด๊ฐ€ WeakMap ๋ฐ–์˜ ๋‹ค๋ฅธ ๊ณณ์—์„œ ์ฐธ์กฐ๋˜์ง€ ์•Š์œผ๋ฉด ๊ทธ ๊ฐ’์˜ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜๋„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.

WeakMap์€ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜ ๋˜์ง€ ์•Š์•„์•ผ๋งŒ ์œ ์šฉํ•œ ํ‚ค์— ์ •๋ณด๋ฅผ ๋งคํ•‘ํ•  ๋•Œ ํŠนํžˆ ์œ ์šฉํ•œ ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ WeakMap์€ ํ‚ค์˜ ํ™œ์„ฑ ์ƒํƒœ๋ฅผ ๊ด€์ฐฐํ•˜๋Š” ๊ฒƒ์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ํ‚ค๋ฅผ ์—ด๊ฑฐํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ํ‚ค ๋ชฉ๋ก์„ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋ฐฉ๋ฒ•์ด ์กด์žฌํ–ˆ๋‹ค๋ฉด, ํ‚ค ๋ชฉ๋ก์€ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜ ์ƒํƒœ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์งˆ ๊ฒƒ์ด๋ฏ€๋กœ ๋น„๊ฒฐ์ •์„ฑ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ํ‚ค ๋ชฉ๋ก์ด ํ•„์š”ํ•˜๋ฉด Map์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ƒ์„ฑ์ž

WeakMap()

์ƒˆ๋กœ์šด WeakMap ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์ธ์Šคํ„ด์Šค ์†์„ฑ

์ด ์†์„ฑ๋“ค์€ WeakMap.prototype์— ์ •์˜๋˜๋ฉฐ ๋ชจ๋“  WeakMap ์ธ์Šคํ„ด์Šค๊ฐ€ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค.

WeakMap.prototype.constructor

์ธ์Šคํ„ด์Šค ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ–ˆ๋˜ ์ƒ์„ฑ์ž ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. WeakMap ์ธ์Šคํ„ด์Šค์—์„œ์˜ ์ดˆ๊ธฐ ๊ฐ’์€ WeakMap ์ƒ์„ฑ์ž์ž…๋‹ˆ๋‹ค.

WeakMap.prototype[@@toStringTag]

@@toStringTag ์†์„ฑ์˜ ์ดˆ๊ธฐ ๊ฐ’์€ ๋ฌธ์ž์—ด "WeakMap"์ž…๋‹ˆ๋‹ค. ์ด ์†์„ฑ์€ Object.prototype.toString()์—์„œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ

WeakMap.prototype.delete()

key์— ์—ฐ๊ฒฐ๋œ ๊ฐ’์„ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. ์ดํ›„ WeakMap.prototype.has(key)๋Š” false๋ฅผ ๋ฐ˜ํ™˜ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

WeakMap.prototype.get()

key์— ์—ฐ๊ฒฐ๋œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ’์ด ์—†์œผ๋ฉด undefined๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

WeakMap.prototype.has()

key์— ์—ฐ๊ฒฐ๋œ ๊ฐ’์ด WeakMap ๊ฐ์ฒด์— ์กด์žฌํ•˜๋Š”์ง€ ๋‚˜ํƒ€๋‚ด๋Š” ๋ถˆ๋ฆฌ์–ธ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

WeakMap.prototype.set()

WeakMap ๊ฐ์ฒด์˜ key์— value๋ฅผ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค. WeakMap ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์ œ

WeakMap ์‚ฌ์šฉํ•˜๊ธฐ

js
const wm1 = new WeakMap();
const wm2 = new WeakMap();
const wm3 = new WeakMap();
const o1 = {};
const o2 = function () {};
const o3 = window;

wm1.set(o1, 37);
wm1.set(o2, "azerty");
wm2.set(o1, o2); // ๊ฐ’์€ ํ•จ์ˆ˜์™€ ๊ฐ์ฒด๋ฅผ ํฌํ•จํ•ด ์•„๋ฌด๊ฑฐ๋‚˜ ๊ฐ€๋Šฅ
wm2.set(o3, undefined);
wm2.set(wm1, wm2); // ํ‚ค๋Š” ์•„๋ฌด ๊ฐ์ฒด๋‚˜ ๊ฐ€๋Šฅ. ๋‹ค๋ฅธ WeakMap๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค!

wm1.get(o2); // "azerty"
wm2.get(o2); // undefined, wm2์—๋Š” o2์— ์—ฐ๊ฒฐ๋œ ๊ฐ’์ด ์—†์Œ
wm2.get(o3); // undefined, o3์— undefined๋ฅผ ์—ฐ๊ฒฐํ•จ

wm1.has(o2); // true
wm2.has(o2); // false
wm2.has(o3); // true (๊ฐ’์ด undefined์ง€๋งŒ)

wm3.set(o1, 37);
wm3.get(o1); // 37

wm1.has(o1); // true
wm1.delete(o1);
wm1.has(o1); // false

WeakMap๊ณผ ์œ ์‚ฌํ•˜์ง€๋งŒ .clear() ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ง„ ํด๋ž˜์Šค ๊ตฌํ˜„

js
class ClearableWeakMap {
  #wm;
  constructor(init) {
    this.#wm = new WeakMap(init);
  }
  clear() {
    this.#wm = new WeakMap();
  }
  delete(k) {
    return this.#wm.delete(k);
  }
  get(k) {
    return this.#wm.get(k);
  }
  has(k) {
    return this.#wm.has(k);
  }
  set(k, v) {
    this.#wm.set(k, v);
    return this;
  }
}

๋น„๊ณต๊ฐœ ๋ฉค๋ฒ„ ํ‰๋‚ด๋‚ด๊ธฐ

WeakMap์„ ์‚ฌ์šฉํ•˜๋ฉด ๋น„๊ณต๊ฐœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ์ฒด์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๊ณ , ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ด์ ์„ ๋ˆ„๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • Map๊ณผ ๋น„๊ตํ–ˆ์„ ๋•Œ, WeakMap์€ ํ‚ค๋กœ ์‚ฌ์šฉ๋˜๋Š” ๊ฐ์ฒด์— ๋Œ€ํ•œ ๊ฐ•๋ ฅํ•œ ์ฐธ์กฐ๋ฅผ ๋ณด์œ ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๊ฐ์ฒด์™€ ๊ทธ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๊ฐ€ ๋™์ผํ•œ ์ˆ˜๋ช…์„ ๊ณต์œ ํ•˜๊ณ , ๋”ฐ๋ผ์„œ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์—ด๊ฑฐํ•  ์ˆ˜ ์—†๋Š” ์†์„ฑ์ด๋‚˜ Symbol ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ๋น„๊ตํ–ˆ์„ ๋•Œ, WeakMap์€ ๊ฐ์ฒด ์™ธ๋ถ€์— ์กด์žฌํ•˜๋ฏ€๋กœ Object.getOwnPropertySymbols ๋“ฑ ๋ฆฌํ”Œ๋ ‰์…˜ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ ์‚ฌ์šฉ์ž ์ฝ”๋“œ์—์„œ๋Š” ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
  • ํด๋กœ์ €์™€ ๋น„๊ตํ–ˆ์„ ๋•Œ, ํ•˜๋‚˜์˜ WeakMap์„ ์ƒ์„ฑ์ž์—์„œ ์ƒ์„ฑํ•œ ๋ชจ๋“  ์ธ์Šคํ„ด์Šค์— ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์„ฑ์ด ๋” ๋†’๊ณ , ๊ฐ™์€ ํด๋ž˜์Šค์˜ ๋‹ค๋ฅธ ์ธ์Šคํ„ด์Šค๊ฐ€ ์„œ๋กœ์˜ ๋น„๊ณต๊ฐœ ๋ฉค๋ฒ„๋ฅผ ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
js
let Thing;

{
  const privateScope = new WeakMap();
  let counter = 0;

  Thing = function () {
    this.someProperty = "foo";

    privateScope.set(this, {
      hidden: ++counter,
    });
  };

  Thing.prototype.showPublic = function () {
    return this.someProperty;
  };

  Thing.prototype.showPrivate = function () {
    return privateScope.get(this).hidden;
  };
}

console.log(typeof privateScope);
// "undefined"

const thing = new Thing();

console.log(thing);
// Thing {someProperty: "foo"}

thing.showPublic();
// "foo"

thing.showPrivate();
// 1

์œ„ ์ฝ”๋“œ๋Š” ๋น„๊ณต๊ฐœ ํ•„๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์•„๋ž˜ ์˜ˆ์ œ์™€ ๋™์ผํ•˜๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

js
class Thing {
  static #counter = 0;
  #hidden;
  constructor() {
    this.someProperty = "foo";
    this.#hidden = ++Thing.#counter;
  }
  showPublic() {
    return this.someProperty;
  }
  showPrivate() {
    return this.#hidden;
  }
}

console.log(thing);
// Thing {someProperty: "foo"}

thing.showPublic();
// "foo"

thing.showPrivate();
// 1

๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์—ฐ๊ฒฐํ•˜๊ธฐ

WeakMap์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ์ฒด์˜ ์ƒ๋ช… ์ฃผ๊ธฐ์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๊ณ ๋„ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋น„๊ณต๊ฐœ ๋ฉค๋ฒ„ ์˜ˆ์ œํ•˜๊ณ ๋„ ๊ต‰์žฅํžˆ ๋น„์Šทํ•œ๋ฐ, ๋น„๊ณต๊ฐœ ๋ฉค๋ฒ„ ๋˜ํ•œ ํ”„๋กœํ† ํƒ€์ž… ์ƒ์†์— ์ฐธ์—ฌํ•˜์ง€ ์•Š๋Š” ์™ธ๋ถ€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋กœ ์„ค๊ณ„๋๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

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

js
const buttons = document.querySelectorAll(".button");
buttons.forEach((button) => {
  button.clicked = false;
  button.addEventListener("click", () => {
    button.clicked = true;
    const currentButtons = [...document.querySelectorAll(".button")];
    if (currentButtons.every((button) => button.clicked)) {
      console.log("๋ชจ๋“  ๋ฒ„ํŠผ์„ ํด๋ฆญํ–ˆ์Šต๋‹ˆ๋‹ค!");
    }
  });
});

์œ„ ๋ฐฉ๋ฒ•๋„ ๋™์ž‘ํ•˜์ง€๋งŒ, ๋ช‡ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  • clicked ์†์„ฑ์ด ์—ด๊ฑฐ ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ Object.keys(button), for...in ๋ฐ˜๋ณต๋ฌธ ๋“ฑ์— ๋…ธ์ถœ๋ฉ๋‹ˆ๋‹ค. Object.defineProperty()๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋Œ€์‘ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋Œ€์‹  ์ฝ”๋“œ๊ฐ€ ๋” ์‹œ๋„๋Ÿฌ์›Œ์ง‘๋‹ˆ๋‹ค.
  • clicked ์†์„ฑ์€ ์ผ๋ฐ˜ ๋ฌธ์ž์—ด ์†์„ฑ์ด๋ฏ€๋กœ ๋‹ค๋ฅธ ์ฝ”๋“œ์—์„œ ์ ‘๊ทผํ•˜๊ฑฐ๋‚˜ ๋ฎ์–ด์“ธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Symbol ํ‚ค๋ฅผ ์‚ฌ์šฉํ•ด ๋Œ€์‘ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๊ทธ๋ž˜๋„ Object.getOwnPropertySymbols()๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

WeakMap์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ชจ๋‘ ๊ณ ์น  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

js
const buttons = document.querySelectorAll(".button");
const clicked = new WeakMap();
buttons.forEach((button) => {
  clicked.set(button, false);
  button.addEventListener("click", () => {
    clicked.set(button, true);
    const currentButtons = [...document.querySelectorAll(".button")];
    if (currentButtons.every((button) => clicked.get(button))) {
      console.log("๋ชจ๋“  ๋ฒ„ํŠผ์„ ํด๋ฆญํ–ˆ์Šต๋‹ˆ๋‹ค!");
    }
  });
});

์—ฌ๊ธฐ์„œ๋Š” clicked์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ๋งŒ ๊ฐ ๋ฒ„ํŠผ์˜ ํด๋ฆญ ์ƒํƒœ๋ฅผ ์•Œ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์™ธ๋ถ€ ์ฝ”๋“œ๋Š” ์ด ์ƒํƒœ๋ฅผ ๋ฐ”๊ฟ€ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ๋ฒ„ํŠผ์ด DOM์—์„œ ์ œ๊ฑฐ๋˜๋ฉด ์—ฐ๊ด€๋๋˜ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋„ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ๊ฐ€ ์ž๋™์œผ๋กœ ์ •๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

์บ์‹ฑ

ํ•จ์ˆ˜์— ์ „๋‹ฌํ–ˆ๋˜ ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ๊ทธ ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ๋ฅผ ์—ฐ๊ด€์ง€์œผ๋ฉด, ๊ฐ™์€ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋‹ค์‹œ ๋ฐ›์•˜์„ ๋•Œ ํ•จ์ˆ˜๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•˜์ง€ ์•Š๊ณ  ์บ์‹œ๋œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์€ ํ•จ์ˆ˜๊ฐ€ ์ˆœ์ˆ˜(์™ธ๋ถ€ ๊ฐ์ฒด๋ฅผ ์กฐ์ž‘ํ•˜๊ฑฐ๋‚˜, ๊ธฐํƒ€ ๊ด€์ธก ๊ฐ€๋Šฅํ•œ ๋ถ€์ž‘์šฉ์„ ์œ ๋ฐœํ•˜์ง€ ์•Š์Œ)ํ•  ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

js
const cache = new WeakMap();
function handleObjectValues(obj) {
  if (cache.has(obj)) {
    return cache.get(obj);
  }
  const result = Object.values(obj).map(heavyComputation);
  cache.set(obj, result);
  return result;
}

ํ•˜์ง€๋งŒ ํ•จ์ˆ˜๊ฐ€ ํ•œ ๊ฐ์ฒด๋ฅผ ๋ฐ›์„ ๋•Œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ์ฃผ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์ž…๋ ฅํ–ˆ๋˜ ๊ฐ์ฒด๋ฅผ ํ•จ์ˆ˜์— ๋‹ค์‹œ ์ „๋‹ฌํ•  ์ผ์ด ์˜์›ํžˆ ์—†๋‹ค๊ณ  ํ•ด๋„, ๊ฒฐ๊ณผ๋Š” ์บ์‹œ์— ๊ณ„์† ๋‚จ์•„์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋” ํšจ์œจ์ ์ธ ๋ฐฉ๋ฒ•์€ Map๊ณผ WeakRef ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•ด์„œ, ์ž„์˜ ํƒ€์ž…์˜ ์ž…๋ ฅ ๊ฐ’์„ ๊ทธ์— ๋Œ€์‘ํ•˜๋Š” (์•„๋งˆ๋„ ๋งค์šฐ ํฐ) ๊ณ„์‚ฐ ๊ฒฐ๊ณผ์™€ ์—ฐ๊ด€์ง“๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ WeakRef์™€ FinalizationRegistry ์˜ˆ์ œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.

๋ช…์„ธ์„œ

Specification
ECMAScriptยฎ 2026 Language Specification
# sec-weakmap-objects

๋ธŒ๋ผ์šฐ์ € ํ˜ธํ™˜์„ฑ

๊ฐ™์ด ๋ณด๊ธฐ