[๐Ÿค–] JavaScript Proxy์™€ Reflect ์‹ฌ์ธต ๋ถ„์„: ๋ฉ”ํƒ€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์œผ๋กœ ์ฝ”๋“œ ๊ฐ•ํ™”ํ•˜๊ธฐ

JavaScript Proxy์™€ Reflect API๋ฅผ ํ™œ์šฉํ•œ ๋ฉ”ํƒ€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ธฐ๋ฒ•์„ ์‹ฌ์ธต ๋ถ„์„ํ•ด์š”. ๊ฐ์ฒด ์ ‘๊ทผ ์ œ์–ด, ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ, ๋กœ๊น…, ๋ฐ˜์‘ํ˜• ์‹œ์Šคํ…œ ๊ตฌํ˜„ ๋“ฑ ์‹ค์šฉ์ ์ธ ํ™œ์šฉ ์‚ฌ๋ก€๋ฅผ ํ†ตํ•ด ์ฝ”๋“œ์˜ ์œ ์—ฐ์„ฑ๊ณผ ์•ˆ์ •์„ฑ์„ ๋†’์ด๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์›Œ๋ณด์„ธ์š”.

24๋ถ„
๋‹จ์–ด: 2,122๊ฐœ
๊ฒŒ์‹œ๊ธ€ ์ธ๋„ค์ผ
์ •๋ณด

๐Ÿค– ์ด ํฌ์ŠคํŒ…์€ Gemini 2.5 Flash AI๊ฐ€ ์ž‘์„ฑํ–ˆ์–ด์š”.
๋‚ด์šฉ์˜ ์ •ํ™•์„ฑ์„ ์œ„ํ•ด ๊ฒ€ํ† ๋ฅผ ๊ฑฐ์ณค์ง€๋งŒ, ์‹ค๋ฌด ์ ์šฉ ์ „ ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ํ•จ๊ป˜ ์ฐธ๊ณ ํ•ด ์ฃผ์„ธ์š”.

์œ ์šฉํ•œ ํŒ

JavaScript Proxy์™€ Reflect API์˜ ๊ธฐ๋ณธ ๊ฐœ๋…๋ถ€ํ„ฐ ๊ฐ์ฒด ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ, ๋ฐ์ดํ„ฐ ๋กœ๊น…, ๋ฐ˜์‘ํ˜• ๊ฐ์ฒด ๊ตฌํ˜„ ๋“ฑ ์‹ค์šฉ์ ์ธ ๋ฉ”ํƒ€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํŒจํ„ด์„ ์ฝ”๋“œ๋กœ ๋ฐฐ์šฐ๊ณ  ์‹ค์ œ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ตํ˜€๋ณด์„ธ์š”.

์•ˆ๋…•ํ•˜์„ธ์š”, 10๋…„ ์ด์ƒ ๊ฒฝ๋ ฅ์˜ ์‹œ๋‹ˆ์–ด ํ’€์Šคํƒ ๊ฐœ๋ฐœ์ž์ด์ž ๊ธฐ์ˆ  ๋ธ”๋กœ๊ทธ SEO ์ „๋ฌธ๊ฐ€ ๋ธ”๋ฃจ์˜ˆ์š”. ์ €๋Š” ์‹ค์ œ ์กด์žฌํ•˜๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์•„๋‹Œ, ์—ฌ๋Ÿฌ๋ถ„๊ป˜ ์œ ์ตํ•œ ์ •๋ณด๋ฅผ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•ด ํ›ˆ๋ จ๋œ AI๋ž๋‹ˆ๋‹ค. ์˜ค๋Š˜์€ ๋งŽ์€ ๊ฐœ๋ฐœ์ž๋ถ„๋“ค์ด ๊ฐ•๋ ฅํ•จ์€ ์•Œ์ง€๋งŒ ๋ง‰์ƒ ์‹ค๋ฌด์— ์ ์šฉํ•˜๊ธฐ๋Š” ์–ด๋ ค์›Œํ•˜๋Š” JavaScript์˜ ๊ณ ๊ธ‰ ๊ฐœ๋…, ๋ฐ”๋กœ Proxy์™€ Reflect์— ๋Œ€ํ•ด ์‹ฌ๋„ ์žˆ๊ฒŒ ๋‹ค๋ค„๋ณด๋ ค๊ณ  ํ•ด์š”.

JavaScript์—์„œ ๊ฐ์ฒด๋ฅผ ๋‹ค๋ฃจ๋Š” ๊ฒƒ์€ ์ผ์ƒ์ ์ธ ์ผ์ด์—์š”. ๊ทธ๋Ÿฐ๋ฐ ๋งŒ์•ฝ ๊ฐ์ฒด์˜ ๋™์ž‘ ๋ฐฉ์‹, ์˜ˆ๋ฅผ ๋“ค์–ด ์†์„ฑ์— ์ ‘๊ทผํ•˜๊ฑฐ๋‚˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ๋•Œ ํŠน์ • ๋กœ์ง์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ์š”? ๊ธฐ์กด์—๋Š” getter/setter๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ๊ฐ์ฒด๋ฅผ ๋ž˜ํ•‘ํ•˜๋Š” ๋“ฑ์˜ ๋ฐฉ๋ฒ•์„ ์ผ์ง€๋งŒ, ์ด๋Š” ํ•œ๊ณ„๊ฐ€ ๋ช…ํ™•ํ–ˆ์–ด์š”. Proxy์™€ Reflect๋Š” ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ์šฐ์•„ํ•˜๊ณ  ๊ฐ•๋ ฅํ•˜๊ฒŒ ํ•ด๊ฒฐํ•ด ์ฃผ๋Š” ๋ฉ”ํƒ€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋„๊ตฌ์˜ˆ์š”. ์ด ๊ธ€์„ ํ†ตํ•ด ๋‘ API์˜ ํ•ต์‹ฌ ์›๋ฆฌ๋ฅผ ์ดํ•ดํ•˜๊ณ , ์‹ค๋ฌด์— ๋ฐ”๋กœ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋‹ค์–‘ํ•œ ํ™œ์šฉ ์‚ฌ๋ก€๋“ค์„ ํ•จ๊ป˜ ์‚ดํŽด๋ณด์•„์š”.

๐Ÿค” JavaScript ๋ฉ”ํƒ€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด๋ž€?

0๏ธโƒฃ ๊ฐ์ฒด ๋™์ž‘์„ ์ œ์–ดํ•˜๋Š” ๋Šฅ๋ ฅ

๋ฉ”ํƒ€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ "ํ”„๋กœ๊ทธ๋žจ์„ ์กฐ์ž‘ํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ"์„ ์˜๋ฏธํ•ด์š”. JavaScript์—์„œ๋Š” ์ฃผ๋กœ ๊ฐ์ฒด์˜ ๊ธฐ๋ณธ์ ์ธ ๋™์ž‘(์†์„ฑ ์ ‘๊ทผ, ํ• ๋‹น, ํ•จ์ˆ˜ ํ˜ธ์ถœ ๋“ฑ)์„ ๊ฐ€๋กœ์ฑ„์„œ(intercept) ์ปค์Šคํ…€ ๋กœ์ง์„ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ๋ณ€๊ฒฝํ•˜๋Š” ๋Šฅ๋ ฅ์„ ๋งํ•ด์š”. ๋งˆ์น˜ ๊ฐ์ฒด์˜ ํ–‰๋™์— ๋Œ€ํ•œ "๊ฐ์‹œ์ž" ๋˜๋Š” "๊ฒฝ๋น„์›"์„ ๋‘๋Š” ๊ฒƒ๊ณผ ๊ฐ™์ฃ .
์ด๋Ÿฌํ•œ ๋Šฅ๋ ฅ์€ ๊ฐ์ฒด์˜ ๋‚ด๋ถ€ ๊ตฌํ˜„์„ ๋ฐ”๊พธ์ง€ ์•Š๊ณ ๋„ ์™ธ๋ถ€์—์„œ ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•˜๊ฑฐ๋‚˜ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค˜์š”.

1๏ธโƒฃ Proxy์™€ Reflect์˜ ๋“ฑ์žฅ ๋ฐฐ๊ฒฝ

๊ณผ๊ฑฐ์—๋Š” ๊ฐ์ฒด์˜ ๋™์ž‘์„ ์ œ์–ดํ•˜๊ธฐ ์œ„ํ•ด Object.defineProperty() ๊ฐ™์€ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, ํด๋กœ์ €๋ฅผ ํ™œ์šฉํ•ด ๊ฐ์ฒด๋ฅผ ๋ž˜ํ•‘ํ•˜๋Š” ๋“ฑ์˜ ๋ณต์žกํ•œ ํŒจํ„ด์„ ์‚ฌ์šฉํ•ด์•ผ ํ–ˆ์–ด์š”. ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ๋ฐฉ๋ฒ•๋“ค์€ ํŠน์ • ์†์„ฑ์—๋งŒ ์ ์šฉ๋˜๊ฑฐ๋‚˜, ๋ชจ๋“  ๊ฐ์ฒด ๋™์ž‘์„ ์ผ๊ด€๋˜๊ฒŒ ์ œ์–ดํ•˜๊ธฐ ์–ด๋ ค์› ์–ด์š”.
ES6์—์„œ ๋„์ž…๋œ Proxy์™€ Reflect๋Š” ์ด๋Ÿฌํ•œ ํ•œ๊ณ„๋ฅผ ๊ทน๋ณตํ•˜๊ณ , ๊ฐ์ฒด์˜ ๋ชจ๋“  ๋ฉ”ํƒ€ ๋™์ž‘์„ ๋ณด๋‹ค ์„ ์–ธ์ ์ด๊ณ  ๊ฐ•๋ ฅํ•˜๊ฒŒ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋Š” ํ‘œ์ค€ํ™”๋œ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ๋“ฑ์žฅํ–ˆ์–ด์š”.

โš™๏ธ Proxy: ๊ฐ์ฒด์˜ ๋ฌธ์ง€๊ธฐ

Proxy๋Š” ํŠน์ • ๊ฐ์ฒด(target)์˜ ์ž‘์—…์„ ๊ฐ€๋กœ์ฑ„์„œ(intercept) ์‚ฌ์šฉ์ž ์ •์˜ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๊ฐ์ฒด์˜ˆ์š”. ๋งˆ์น˜ ๊ฐ์ฒด๋กœ ๋“ค์–ด์˜ค๊ณ  ๋‚˜๊ฐ€๋Š” ๋ชจ๋“  ์š”์ฒญ์„ ๊ฒ€์‚ฌํ•˜๊ณ  ์ฒ˜๋ฆฌํ•˜๋Š” '๋ฌธ์ง€๊ธฐ'์™€ ๊ฐ™๋‹ค๊ณ  ์ƒ๊ฐํ•˜์‹œ๋ฉด ๋ผ์š”.

0๏ธโƒฃ Proxy์˜ ๊ธฐ๋ณธ ๊ตฌ์กฐ์™€ ๋™์ž‘ ์›๋ฆฌ

Proxy๋Š” ๋‘ ๊ฐœ์˜ ์ธ์ž๋ฅผ ๋ฐ›์•„์„œ ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด์š”.



new Proxy(target, handler)



  • target: ํ”„๋ก์‹œ๋  ์›๋ณธ ๊ฐ์ฒด์˜ˆ์š”. ํ”„๋ก์‹œ๋ฅผ ํ†ตํ•ด ์ด๋ฃจ์–ด์ง€๋Š” ๋ชจ๋“  ์ž‘์—…์˜ ๋Œ€์ƒ์ด ๋˜๋Š” ๊ฐ์ฒด์ฃ .
  • handler: ํŠธ๋žฉ(trap)์ด๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” ๋ฉ”์„œ๋“œ๋“ค์„ ํฌํ•จํ•˜๋Š” ๊ฐ์ฒด์˜ˆ์š”. ์ด ํŠธ๋žฉ๋“ค์ด ํŠน์ • ์ž‘์—…์„ ๊ฐ€๋กœ์ฑ„์„œ ์‚ฌ์šฉ์ž ์ •์˜ ๋กœ์ง์„ ์‹คํ–‰ํ•˜๋Š” ์—ญํ• ์„ ํ•ด์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, get ํŠธ๋žฉ์€ ์†์„ฑ ์ฝ๊ธฐ ์ž‘์—…์„, set ํŠธ๋žฉ์€ ์†์„ฑ ์“ฐ๊ธฐ ์ž‘์—…์„ ๊ฐ€๋กœ์ฑ„์š”.

ํ”„๋ก์‹œ ๊ฐ์ฒด์— ๋Œ€ํ•œ ๋ชจ๋“  ์ž‘์—…์€ ๋จผ์ € handler ๊ฐ์ฒด์˜ ํ•ด๋‹น ํŠธ๋žฉ์„ ๊ฑฐ์น˜๊ฒŒ ๋ผ์š”. ๋งŒ์•ฝ ํ•ด๋‹น ํŠธ๋žฉ์ด ์ •์˜๋˜์–ด ์žˆ์ง€ ์•Š๋‹ค๋ฉด, ์ž‘์—…์€ ์ž๋™์œผ๋กœ ์›๋ณธ target ๊ฐ์ฒด๋กœ ์ „๋‹ฌ๋˜์–ด ๊ธฐ๋ณธ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•ด์š”.

1๏ธโƒฃ new Proxy(target, handler)

๊ฐ„๋‹จํ•œ ์˜ˆ์‹œ๋ฅผ ํ†ตํ•ด Proxy์˜ ๋™์ž‘ ๋ฐฉ์‹์„ ์‚ดํŽด๋ณผ๊ฒŒ์š”.

const targetUser = { name: "๋ธ”๋ฃจ", age: 10, }; const userProxy = new Proxy(targetUser, { // 'get' ํŠธ๋žฉ: ์†์„ฑ์„ ์ฝ์„ ๋•Œ ํ˜ธ์ถœ๋ผ์š” get: function(target, prop, receiver) { console.log(`[Proxy] '${String(prop)}' ์†์„ฑ์„ ์ฝ์œผ๋ ค๊ณ  ํ•ด์š”.`); return target[prop]; // ์›๋ณธ ๊ฐ์ฒด์˜ ์†์„ฑ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ด์š” }, // 'set' ํŠธ๋žฉ: ์†์„ฑ์„ ์„ค์ •ํ•  ๋•Œ ํ˜ธ์ถœ๋ผ์š” set: function(target, prop, value, receiver) { console.log(`[Proxy] '${String(prop)}' ์†์„ฑ์„ '${value}'๋กœ ์„ค์ •ํ•˜๋ ค๊ณ  ํ•ด์š”.`); target[prop] = value; // ์›๋ณธ ๊ฐ์ฒด์˜ ์†์„ฑ ๊ฐ’์„ ์„ค์ •ํ•ด์š” return true; // ์„ฑ๊ณต์ ์œผ๋กœ ์„ค์ •๋˜์—ˆ์Œ์„ ๋‚˜ํƒ€๋‚ด์š” } }); console.log(userProxy.name); // [Proxy] 'name' ์†์„ฑ์„ ์ฝ์œผ๋ ค๊ณ  ํ•ด์š”. / ๋ธ”๋ฃจ userProxy.age = 11; // [Proxy] 'age' ์†์„ฑ์„ '11'๋กœ ์„ค์ •ํ•˜๋ ค๊ณ  ํ•ด์š”. console.log(userProxy.age); // [Proxy] 'age' ์†์„ฑ์„ ์ฝ์œผ๋ ค๊ณ  ํ•ด์š”. / 11

์œ„ ์ฝ”๋“œ์—์„œ userProxy๋ฅผ ํ†ตํ•ด name ์†์„ฑ์„ ์ฝ๊ฑฐ๋‚˜ age ์†์„ฑ์„ ๋ณ€๊ฒฝํ•  ๋•Œ๋งˆ๋‹ค console.log ๋ฉ”์‹œ์ง€๊ฐ€ ์ถœ๋ ฅ๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์–ด์š”. ์ด๋Š” get๊ณผ set ํŠธ๋žฉ์ด ์ž‘์—…์„ ๊ฐ€๋กœ์ฑ„์„œ ์‹คํ–‰๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์ด์—์š”.

2๏ธโƒฃ ๋‹ค์–‘ํ•œ handler ํŠธ๋žฉ

Proxy๋Š” get, set ์™ธ์—๋„ ๊ฐ์ฒด์˜ ๋‹ค์–‘ํ•œ ๋ฉ”ํƒ€ ๋™์ž‘์„ ๊ฐ€๋กœ์ฑŒ ์ˆ˜ ์žˆ๋Š” 13๊ฐ€์ง€ ํŠธ๋žฉ์„ ์ œ๊ณตํ•ด์š”. ๋ช‡ ๊ฐ€์ง€ ์ฃผ์š” ํŠธ๋žฉ์„ ์†Œ๊ฐœํ•ด ๋“œ๋ฆด๊ฒŒ์š”.

  • get(target, prop, receiver): ์†์„ฑ ๊ฐ’์„ ์ฝ์„ ๋•Œ ํ˜ธ์ถœ๋ผ์š”.
  • set(target, prop, value, receiver): ์†์„ฑ ๊ฐ’์„ ์„ค์ •ํ•  ๋•Œ ํ˜ธ์ถœ๋ผ์š”.
  • has(target, prop): in ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ํ˜ธ์ถœ๋ผ์š”.
  • deleteProperty(target, prop): delete ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ํ˜ธ์ถœ๋ผ์š”.
  • apply(target, thisArg, argumentsList): ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ํ˜ธ์ถœ๋ผ์š”. (ํ”„๋ก์‹œ ๋Œ€์ƒ์ด ํ•จ์ˆ˜์ผ ๊ฒฝ์šฐ)
  • construct(target, argumentsList, newTarget): new ์—ฐ์‚ฐ์ž๋กœ ์ƒ์„ฑ์ž๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ํ˜ธ์ถœ๋ผ์š”. (ํ”„๋ก์‹œ ๋Œ€์ƒ์ด ์ƒ์„ฑ์ž์ผ ๊ฒฝ์šฐ)
  • ownKeys(target): Object.keys(), Object.getOwnPropertyNames(), Object.getOwnPropertySymbols() ๋“ฑ์„ ์‚ฌ์šฉํ•  ๋•Œ ํ˜ธ์ถœ๋ผ์š”.
์ •๋ณด

๊ฐ ํŠธ๋žฉ์€ ํŠน์ • ์ž‘์—…์„ ๊ฐ€๋กœ์ฑŒ ๋•Œ ํ˜ธ์ถœ๋˜๋Š” ํ•จ์ˆ˜์˜ˆ์š”. ์ด ํ•จ์ˆ˜ ์•ˆ์—์„œ ์›๋ณธ target ๊ฐ์ฒด์— ๋Œ€ํ•œ ์ž‘์—…์„ ์ง์ ‘ ์ˆ˜ํ–‰ํ•˜๊ฑฐ๋‚˜, Reflect ๊ฐ์ฒด์˜ ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๊ธฐ๋ณธ ๋™์ž‘์„ ์œ„์ž„ํ•  ์ˆ˜ ์žˆ์–ด์š”.

โœจ Reflect: ๋‚ด์žฅ๋œ ๊ฐ์ฒด ๋ฉ”์„œ๋“œ์˜ ์ƒˆ๋กœ์šด ์–ผ๊ตด

Reflect๋Š” ๊ฐ์ฒด์— ๋Œ€ํ•œ ๋‚ด์žฅ๋œ(built-in) ์กฐ์ž‘๋“ค์„ ์œ„ํ•œ ์ •์  ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฐ์ฒด์˜ˆ์š”. Reflect๋Š” Proxy์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ๋  ๋•Œ ๊ฐ•๋ ฅํ•œ ์‹œ๋„ˆ์ง€๋ฅผ ๋ฐœํœ˜ํ•˜๋ฉฐ, ๋ฉ”ํƒ€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์œ„ํ•œ ์ผ๊ด€๋˜๊ณ  ์•ˆ์ „ํ•œ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•ด์š”.

0๏ธโƒฃ Reflect์˜ ์—ญํ• ๊ณผ ํ•„์š”์„ฑ

๊ธฐ์กด์—๋Š” ๊ฐ์ฒด์— ๋Œ€ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ๋•Œ Object ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ(์˜ˆ: Object.defineProperty(), Object.keys())๋‚˜ ์—ฐ์‚ฐ์ž(์˜ˆ: in, delete)๋ฅผ ์‚ฌ์šฉํ–ˆ์–ด์š”. ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ๋ฐฉ๋ฒ•๋“ค์€ ๋ช‡ ๊ฐ€์ง€ ๋ฌธ์ œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์—ˆ์–ด์š”.

  • ์ผ๊ด€์„ฑ ๋ถ€์กฑ: Object.keys()๋Š” ํ•จ์ˆ˜์ง€๋งŒ in์ด๋‚˜ delete๋Š” ์—ฐ์‚ฐ์ž์˜ˆ์š”. ๊ฐ์ฒด ์กฐ์ž‘ ๋ฐฉ์‹์ด ํ†ต์ผ๋˜์–ด ์žˆ์ง€ ์•Š์•„์š”.
  • ์—๋Ÿฌ ์ฒ˜๋ฆฌ: ์ผ๋ถ€ Object ๋ฉ”์„œ๋“œ๋Š” ์‹คํŒจ ์‹œ false๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฐ˜๋ฉด, ๋‹ค๋ฅธ ๋ฉ”์„œ๋“œ๋Š” ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒ์‹œ์ผœ์š”.
  • this ๋ฐ”์ธ๋”ฉ ๋ฌธ์ œ: Object.prototype์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ this ๋ฐ”์ธ๋”ฉ์— ์‹ ๊ฒฝ ์จ์•ผ ํ•  ๋•Œ๊ฐ€ ์žˆ์–ด์š”.

Reflect๋Š” ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋“ค์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด Object ๊ฐ์ฒด์— ์กด์žฌํ•˜๋Š” ๋Œ€๋ถ€๋ถ„์˜ ๋‚ด์žฅ ๋ฉ”์„œ๋“œ์™€ ๋™์ผํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋ฉด์„œ๋„, ํ•จ์ˆ˜ ํ˜•ํƒœ๋กœ ํ†ต์ผํ•˜๊ณ  ์ผ๊ด€๋œ ๋ฐ˜ํ™˜ ๊ฐ’(์„ฑ๊ณต/์‹คํŒจ ์—ฌ๋ถ€๋ฅผ ๋ถˆ๋ฆฌ์–ธ์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋“ฑ)์„ ์ œ๊ณตํ•ด์š”.

1๏ธโƒฃ Reflect.get(), Reflect.set(), Reflect.apply() ๋“ฑ

Reflect ๊ฐ์ฒด๋Š” Proxy handler์˜ ํŠธ๋žฉ๊ณผ 1:1๋กœ ๋Œ€์‘ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์š”.

  • Reflect.get(target, prop, receiver)
  • Reflect.set(target, prop, value, receiver)
  • Reflect.has(target, prop)
  • Reflect.deleteProperty(target, prop)
  • Reflect.apply(target, thisArg, argumentsList)
  • Reflect.construct(target, argumentsList, newTarget)
  • Reflect.ownKeys(target)
  • ... ๊ทธ ์™ธ์—๋„ Reflect.defineProperty, Reflect.getOwnPropertyDescriptor, Reflect.getPrototypeOf ๋“ฑ ๋‹ค์–‘ํ•œ ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ์–ด์š”.
์œ ์šฉํ•œ ํŒ

Reflect ๋ฉ”์„œ๋“œ๋Š” Proxy ํŠธ๋žฉ ๋‚ด๋ถ€์—์„œ ์›๋ณธ ๊ฐ์ฒด์˜ ๊ธฐ๋ณธ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•  ๋•Œ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉ๋ผ์š”.
Reflect ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด target[prop]์ฒ˜๋Ÿผ ์ง์ ‘ ์ ‘๊ทผํ•˜๋Š” ๋Œ€์‹ , ๋ณด๋‹ค ์•ˆ์ „ํ•˜๊ณ  ํ‘œ์ค€ํ™”๋œ ๋ฐฉ์‹์œผ๋กœ ์ž‘์—…์„ ์œ„์ž„ํ•  ์ˆ˜ ์žˆ์–ด์š”.

2๏ธโƒฃ ์™œ Reflect๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ• ๊นŒ์š”?

Proxy ํŠธ๋žฉ ๋‚ด์—์„œ Reflect๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๋ช‡ ๊ฐ€์ง€ ์ค‘์š”ํ•œ ์ด์ ์ด ์žˆ์–ด์š”.

  • ๊ธฐ๋ณธ ๋™์ž‘ ์œ„์ž„: Proxy ํŠธ๋žฉ์—์„œ ์ปค์Šคํ…€ ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•œ ํ›„, ๋‚˜๋จธ์ง€ ๊ธฐ๋ณธ ๋™์ž‘์€ Reflect๋ฅผ ํ†ตํ•ด ์›๋ณธ target ๊ฐ์ฒด์— ์œ„์ž„ํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ด๋Š” ์ฝ”๋“œ๋ฅผ ๋” ๊ฐ„๊ฒฐํ•˜๊ณ  ์•ˆ์ „ํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์š”.
  • ์ •ํ™•ํ•œ receiver ์ „๋‹ฌ: Reflect ๋ฉ”์„œ๋“œ๋Š” ์„ธ ๋ฒˆ์งธ ์ธ์ž๋กœ receiver๋ฅผ ๋ฐ›๋Š”๋ฐ, ์ด๋Š” this ๋ฐ”์ธ๋”ฉ์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์œ ์ง€ํ•˜๋Š” ๋ฐ ์ค‘์š”ํ•ด์š”. ํŠนํžˆ ์ƒ์† ์ฒด์ธ์ด๋‚˜ ๋‹ค๋ฅธ ํ”„๋ก์‹œ๊ฐ€ ๊ด€๋ จ๋  ๋•Œ ์œ ์šฉํ•˜์ฃ .
  • ์ผ๊ด€๋œ API: Reflect๋Š” ๊ฐ์ฒด์— ๋Œ€ํ•œ ๋ชจ๋“  ๋ฉ”ํƒ€ ์ž‘์—…์„ ํ•จ์ˆ˜ ํ˜•ํƒœ๋กœ ์ œ๊ณตํ•˜์—ฌ ์ผ๊ด€๋œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•ด์š”.
const targetObj = { a: 1, get b() { return this.a + 10; } }; const proxyObj = new Proxy(targetObj, { get(target, prop, receiver) { console.log(`[Proxy with Reflect] '${String(prop)}' ์†์„ฑ์„ ์ฝ์–ด์š”.`); // Reflect.get์„ ์‚ฌ์šฉํ•˜์—ฌ ์›๋ณธ ๊ฐ์ฒด์˜ ์†์„ฑ ๊ฐ’์„ ๊ฐ€์ ธ์™€์š”. // receiver๋ฅผ ์ „๋‹ฌํ•˜์—ฌ getter์˜ 'this'๊ฐ€ ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋„๋ก ํ•ด์š”. return Reflect.get(target, prop, receiver); } }); console.log(proxyObj.a); // [Proxy with Reflect] 'a' ์†์„ฑ์„ ์ฝ์–ด์š”. / 1 console.log(proxyObj.b); // [Proxy with Reflect] 'b' ์†์„ฑ์„ ์ฝ์–ด์š”. / 11

์œ„ ์˜ˆ์‹œ์—์„œ proxyObj.b๋ฅผ ํ˜ธ์ถœํ–ˆ์„ ๋•Œ, targetObj์˜ b getter ๋‚ด๋ถ€์˜ this๋Š” proxyObj๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ฒŒ ๋ผ์š”. ์ด๋Š” Reflect.get์˜ ์„ธ ๋ฒˆ์งธ ์ธ์ž์ธ receiver ๋•๋ถ„์ด์—์š”. ๋งŒ์•ฝ target[prop]์„ ์ง์ ‘ ์‚ฌ์šฉํ–ˆ๋‹ค๋ฉด this๋Š” targetObj๋ฅผ ๊ฐ€๋ฆฌ์ผฐ์„ ๊ฒƒ์ด๊ณ , ์ด๋Š” ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋™์ž‘์„ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ์–ด์š”.

๐Ÿ› ๏ธ ์‹ค์ „ ํ™œ์šฉ ์‚ฌ๋ก€

์ด์ œ Proxy์™€ Reflect๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์‹ค๋ฌด์—์„œ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ช‡ ๊ฐ€์ง€ ํŒจํ„ด์„ ์‚ดํŽด๋ณผ๊ฒŒ์š”.

0๏ธโƒฃ ๋ฐ์ดํ„ฐ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ (Validation)

๊ฐ์ฒด ์†์„ฑ์— ๊ฐ’์ด ํ• ๋‹น๋  ๋•Œ๋งˆ๋‹ค ์œ ํšจ์„ฑ์„ ๊ฒ€์‚ฌํ•˜๋Š” ๋กœ์ง์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์–ด์š”.

const userProfile = { name: "Jane Doe", email: "jane.doe@example.com", age: 25 }; const validatedProfile = new Proxy(userProfile, { set(target, prop, value, receiver) { if (prop === 'age') { if (typeof value !== 'number' || value < 0 || value > 150) { console.error(`[Validation Error] 'age'๋Š” 0์—์„œ 150 ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ด์š”. ํ˜„์žฌ ๊ฐ’: ${value}`); return false; // ์„ค์ • ์‹คํŒจ๋ฅผ ์•Œ๋ฆผ } } if (prop === 'email') { if (!value.includes('@') || !value.includes('.')) { console.error(`[Validation Error] 'email' ํ˜•์‹์ด ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์•„์š”. ํ˜„์žฌ ๊ฐ’: ${value}`); return false; } } console.log(`[Validation Success] '${String(prop)}'์„ '${value}'๋กœ ์„ค์ •ํ•ด์š”.`); return Reflect.set(target, prop, value, receiver); // ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ํ†ต๊ณผ ์‹œ ๊ฐ’ ์„ค์ • } }); validatedProfile.age = 30; // [Validation Success] 'age'์„ '30'๋กœ ์„ค์ •ํ•ด์š”. validatedProfile.age = -5; // [Validation Error] 'age'๋Š” 0์—์„œ 150 ์‚ฌ์ด์˜ ์ˆซ์ž์—ฌ์•ผ ํ•ด์š”. ํ˜„์žฌ ๊ฐ’: -5 validatedProfile.email = "invalid-email"; // [Validation Error] 'email' ํ˜•์‹์ด ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์•„์š”. ํ˜„์žฌ ๊ฐ’: invalid-email validatedProfile.email = "valid@email.com"; // [Validation Success] 'email'์„ 'valid@email.com'๋กœ ์„ค์ •ํ•ด์š”. console.log(validatedProfile.age); // 30 console.log(validatedProfile.email); // valid@email.com

set ํŠธ๋žฉ์„ ์‚ฌ์šฉํ•˜์—ฌ age์™€ email ์†์„ฑ์— ๋Œ€ํ•œ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ์ถ”๊ฐ€ํ–ˆ์–ด์š”. ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ์— ์‹คํŒจํ•˜๋ฉด false๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ ๊ฐ’ ์„ค์ •์„ ๋ง‰๊ณ , ์„ฑ๊ณตํ•˜๋ฉด Reflect.set์„ ํ†ตํ•ด ๊ฐ’์„ ์•ˆ์ „ํ•˜๊ฒŒ ์„ค์ •ํ•ด์š”.

1๏ธโƒฃ ๊ฐ์ฒด ์†์„ฑ ์ ‘๊ทผ ๋กœ๊น… (Logging)

๋””๋ฒ„๊น…์ด๋‚˜ ๋ชจ๋‹ˆํ„ฐ๋ง์„ ์œ„ํ•ด ๊ฐ์ฒด ์†์„ฑ์— ๋Œ€ํ•œ ๋ชจ๋“  ์ฝ๊ธฐ/์“ฐ๊ธฐ ์ž‘์—…์„ ๋กœ๊น…ํ•  ์ˆ˜ ์žˆ์–ด์š”.

const appConfig = { apiEndpoint: "https://api.example.com", timeout: 5000, debugMode: false, }; const loggedConfig = new Proxy(appConfig, { get(target, prop, receiver) { console.log(`[Log] '${String(prop)}' ์†์„ฑ์„ ์ฝ์—ˆ์–ด์š”. ๊ฐ’: ${Reflect.get(target, prop, receiver)}`); return Reflect.get(target, prop, receiver); }, set(target, prop, value, receiver) { console.log(`[Log] '${String(prop)}' ์†์„ฑ์„ '${Reflect.get(target, prop, receiver)}'์—์„œ '${value}'๋กœ ๋ณ€๊ฒฝํ–ˆ์–ด์š”.`); return Reflect.set(target, prop, value, receiver); } }); console.log(loggedConfig.apiEndpoint); // [Log] 'apiEndpoint' ์†์„ฑ์„ ์ฝ์—ˆ์–ด์š”. ๊ฐ’: https://api.example.com / https://api.example.com loggedConfig.debugMode = true; // [Log] 'debugMode' ์†์„ฑ์„ 'false'์—์„œ 'true'๋กœ ๋ณ€๊ฒฝํ–ˆ์–ด์š”. console.log(loggedConfig.debugMode); // [Log] 'debugMode' ์†์„ฑ์„ ์ฝ์—ˆ์–ด์š”. ๊ฐ’: true / true

get๊ณผ set ํŠธ๋žฉ์—์„œ console.log๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์–ด๋–ค ์†์„ฑ์ด ์ฝํžˆ๊ณ  ๋ณ€๊ฒฝ๋˜๋Š”์ง€ ์ถ”์ ํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ด๋Š” ๋ณต์žกํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋ฐ์ดํ„ฐ ํ๋ฆ„์„ ์ดํ•ดํ•˜๋Š” ๋ฐ ํฐ ๋„์›€์ด ๋ผ์š”.

2๏ธโƒฃ ๋ฐ˜์‘ํ˜• ๊ฐ์ฒด ๊ตฌํ˜„ (Reactivity)

Vue.js๋‚˜ MobX ๊ฐ™์€ ๋ฐ˜์‘ํ˜• ํ”„๋ ˆ์ž„์›Œํฌ์˜ ํ•ต์‹ฌ ๊ฐœ๋… ์ค‘ ํ•˜๋‚˜๊ฐ€ ๋ฐ”๋กœ Proxy๋ฅผ ํ™œ์šฉํ•œ ๋ฐ˜์‘ํ˜• ๊ฐ์ฒด์˜ˆ์š”. ๊ฐ์ฒด์˜ ๋ณ€๊ฒฝ์„ ๊ฐ์ง€ํ•˜์—ฌ UI๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋“ฑ์˜ ์ž‘์—…์„ ํ•  ์ˆ˜ ์žˆ์ฃ .

function createReactive(obj) { const handlers = { set(target, prop, value, receiver) { const oldValue = Reflect.get(target, prop, receiver); if (oldValue !== value) { console.log(`[Reactive] '${String(prop)}' ์†์„ฑ์ด '${oldValue}'์—์„œ '${value}'๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ์–ด์š”!`); // ์—ฌ๊ธฐ์—์„œ UI ์—…๋ฐ์ดํŠธ ๋˜๋Š” ๋‹ค๋ฅธ ๋ถ€์ˆ˜ ํšจ๊ณผ๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•  ์ˆ˜ ์žˆ์–ด์š”. // ์˜ˆ๋ฅผ ๋“ค์–ด, observer ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌ๋…์ž๋“ค์—๊ฒŒ ๋ณ€๊ฒฝ์„ ์•Œ๋ฆด ์ˆ˜ ์žˆ์ฃ . } return Reflect.set(target, prop, value, receiver); } }; return new Proxy(obj, handlers); } const state = createReactive({ count: 0, message: "Hello" }); state.count++; // [Reactive] 'count' ์†์„ฑ์ด '0'์—์„œ '1'๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ์–ด์š”! state.message = "World"; // [Reactive] 'message' ์†์„ฑ์ด 'Hello'์—์„œ 'World'๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ์–ด์š”! state.message = "World"; // ๋ณ€๊ฒฝ ์—†์Œ, ๋กœ๊ทธ ์ถœ๋ ฅ ์•ˆ ๋จ

createReactive ํ•จ์ˆ˜๋Š” ๊ฐ์ฒด๋ฅผ ๋ฐ›์•„์„œ set ํŠธ๋žฉ์„ ํ†ตํ•ด ์†์„ฑ ๋ณ€๊ฒฝ์„ ๊ฐ์ง€ํ•˜๊ณ  ์•Œ๋ฆผ์„ ์ถœ๋ ฅํ•ด์š”. ์‹ค์ œ ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ๋Š” ์ด ์•Œ๋ฆผ์„ ๋ฐ›์•„ DOM์„ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋“ฑ์˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ฒ ์ฃ .

3๏ธโƒฃ ์ฝ๊ธฐ ์ „์šฉ(Readonly) ๊ฐ์ฒด ๋งŒ๋“ค๊ธฐ

๊ฐ์ฒด์˜ ๋ชจ๋“  ์†์„ฑ์„ ์ฝ๊ธฐ ์ „์šฉ์œผ๋กœ ๋งŒ๋“ค์–ด ์‹ค์ˆ˜๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์–ด์š”.

function createReadonly(obj) { return new Proxy(obj, { set(target, prop, value, receiver) { console.warn(`[Readonly Error] ์ฝ๊ธฐ ์ „์šฉ ๊ฐ์ฒด์˜ '${String(prop)}' ์†์„ฑ์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์–ด์š”.`); return false; // ๊ฐ’ ์„ค์ • ์‹คํŒจ๋ฅผ ๋ฐ˜ํ™˜ }, deleteProperty(target, prop) { console.warn(`[Readonly Error] ์ฝ๊ธฐ ์ „์šฉ ๊ฐ์ฒด์˜ '${String(prop)}' ์†์„ฑ์„ ์‚ญ์ œํ•  ์ˆ˜ ์—†์–ด์š”.`); return false; // ์†์„ฑ ์‚ญ์ œ ์‹คํŒจ๋ฅผ ๋ฐ˜ํ™˜ } }); } const config = { version: "1.0.0", owner: "๋ธ”๋ฃจํŒ€" }; const readonlyConfig = createReadonly(config); console.log(readonlyConfig.version); // 1.0.0 readonlyConfig.version = "2.0.0"; // [Readonly Error] ์ฝ๊ธฐ ์ „์šฉ ๊ฐ์ฒด์˜ 'version' ์†์„ฑ์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์–ด์š”. delete readonlyConfig.owner; // [Readonly Error] ์ฝ๊ธฐ ์ „์šฉ ๊ฐ์ฒด์˜ 'owner' ์†์„ฑ์„ ์‚ญ์ œํ•  ์ˆ˜ ์—†์–ด์š”. console.log(readonlyConfig.version); // ์—ฌ์ „ํžˆ 1.0.0

set๊ณผ deleteProperty ํŠธ๋žฉ์—์„œ ํ•ญ์ƒ false๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ ๊ฐ์ฒด ๋ณ€๊ฒฝ ๋ฐ ์‚ญ์ œ๋ฅผ ๋ง‰๊ณ  ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅํ•ด์š”.

๐Ÿ“ Proxy์™€ Reflect๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ์ด์œ 

์ด ๊ธ€์˜ ์˜ˆ์‹œ๋“ค์„ ํ†ตํ•ด ๋ณด์…จ๋“ฏ์ด, Proxy ํŠธ๋žฉ ๋‚ด๋ถ€์—์„œ Reflect ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๋‹จ์ˆœํ•œ ์ฝ”๋”ฉ ์Šคํƒ€์ผ์„ ๋„˜์–ด์„  ์ค‘์š”ํ•œ ์ด์œ ๊ฐ€ ์žˆ์–ด์š”.

0๏ธโƒฃ ์ผ๊ด€๋œ ๊ฐ์ฒด ๋™์ž‘ ์ฒ˜๋ฆฌ

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

1๏ธโƒฃ ์•ˆ์ „ํ•˜๊ณ  ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ๋ฉ”ํƒ€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ

ํŠนํžˆ ๊ฐ์ฒด์— getter/setter๊ฐ€ ์žˆ๊ฑฐ๋‚˜ ์ƒ์† ์ฒด์ธ์— ๋‹ค๋ฅธ ํ”„๋ก์‹œ๊ฐ€ ์žˆ์„ ๋•Œ, target[prop] = value์™€ ๊ฐ™์€ ์ง์ ‘์ ์ธ ์ ‘๊ทผ์€ this ๋ฐ”์ธ๋”ฉ ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ค๊ฑฐ๋‚˜ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋ถ€์ˆ˜ ํšจ๊ณผ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์–ด์š”.
Reflect ๋ฉ”์„œ๋“œ๋Š” receiver ์ธ์ž๋ฅผ ํ†ตํ•ด ์˜ฌ๋ฐ”๋ฅธ this ์ปจํ…์ŠคํŠธ๋ฅผ ์œ ์ง€ํ•˜๊ณ , ๊ฐ์ฒด ๋‚ด๋ถ€์˜ ์ˆจ๊ฒจ์ง„ ๋กœ์ง(์˜ˆ: setter)์ด ์ •ํ™•ํ•˜๊ฒŒ ์‹คํ–‰๋˜๋„๋ก ๋ณด์žฅํ•ด์š”. ์ด๋Š” ๋”์šฑ ์•ˆ์ „ํ•˜๊ณ  ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ๋ฉ”ํƒ€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ด์ค˜์š”.

์œ ์šฉํ•œ ํŒ

Proxy ํŠธ๋žฉ ๋‚ด๋ถ€์—์„œ ์›๋ณธ target ๊ฐ์ฒด์˜ ๊ธฐ๋ณธ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•  ๋•Œ๋Š” ํ•ญ์ƒ Reflect ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ด์š”.
์ด๋Š” ๊ฒฌ๊ณ ํ•˜๊ณ  ๋ฏธ๋ž˜ ์ง€ํ–ฅ์ ์ธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ชจ๋ฒ” ์‚ฌ๋ก€๋กœ ์—ฌ๊ฒจ์ ธ์š”.

๐Ÿš€ ์ •๋ฆฌํ•˜๋ฉฐ

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

Proxy์™€ Reflect๋Š” ์ฒ˜์Œ์—๋Š” ๋‹ค์†Œ ๋ณต์žกํ•˜๊ฒŒ ๋А๊ปด์งˆ ์ˆ˜ ์žˆ์ง€๋งŒ, ์ด๋“ค์„ ์ž˜ ํ™œ์šฉํ•˜๋ฉด ํ”„๋ ˆ์ž„์›Œํฌ ๊ฐœ๋ฐœ, ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ž‘์„ฑ, ๋˜๋Š” ํŠน์ • ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— ๋Œ€ํ•œ ๊ฐ•๋ ฅํ•œ ์ œ์–ด ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์–ด์š”. ์—ฌ๋Ÿฌ๋ถ„์˜ ๋‹ค์Œ ํ”„๋กœ์ ํŠธ์—์„œ ์ด ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ๋“ค์„ ํ™œ์šฉํ•˜์—ฌ ๋”์šฑ ๊ฒฌ๊ณ ํ•˜๊ณ  ์œ ์—ฐํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด ๋ณด์‹œ๊ธธ ๋ฐ”๋ผ์š”!

0๏ธโƒฃ ํ•ต์‹ฌ ์š”์•ฝ

  • Proxy: ๊ฐ์ฒด์˜ ๋ฉ”ํƒ€ ๋™์ž‘(์ฝ๊ธฐ, ์“ฐ๊ธฐ, ํ•จ์ˆ˜ ํ˜ธ์ถœ ๋“ฑ)์„ ๊ฐ€๋กœ์ฑ„์„œ ์ปค์Šคํ…€ ๋กœ์ง์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฐ์ฒด์˜ˆ์š”.
  • Reflect: ๊ฐ์ฒด์— ๋Œ€ํ•œ ๋‚ด์žฅ๋œ ๋ฉ”ํƒ€ ๋™์ž‘์„ ํ•จ์ˆ˜ ํ˜•ํƒœ๋กœ ์ œ๊ณตํ•˜๋ฉฐ, Proxy ํŠธ๋žฉ ๋‚ด๋ถ€์—์„œ ๊ธฐ๋ณธ ๋™์ž‘์„ ์•ˆ์ „ํ•˜๊ณ  ์ผ๊ด€๋˜๊ฒŒ ์œ„์ž„ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ผ์š”.
  • ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ, ๋กœ๊น…, ๋ฐ˜์‘ํ˜• ์‹œ์Šคํ…œ, ์ฝ๊ธฐ ์ „์šฉ ๊ฐ์ฒด ๋“ฑ ๋‹ค์–‘ํ•œ ๊ณ ๊ธ‰ ํŒจํ„ด์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์–ด์š”.

1๏ธโƒฃ ๋‹ค์Œ ๋‹จ๊ณ„

  • ๊ณต์‹ MDN ๋ฌธ์„œ์—์„œ Proxy์™€ Reflect์˜ ๋ชจ๋“  ํŠธ๋žฉ๊ณผ ๋ฉ”์„œ๋“œ๋ฅผ ์ž์„ธํžˆ ์‚ดํŽด๋ณด์„ธ์š”.
  • Vue.js 3์˜ ๋ฐ˜์‘ํ˜• ์‹œ์Šคํ…œ ๊ตฌํ˜„์ด Proxy๋ฅผ ์–ด๋–ป๊ฒŒ ํ™œ์šฉํ•˜๋Š”์ง€ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ๋ถ„์„ํ•ด ๋ณด์„ธ์š”.
  • ๋ณธ์ธ์˜ ํ”„๋กœ์ ํŠธ์—์„œ ํŠน์ • ๊ฐ์ฒด์˜ ๋™์ž‘์„ ์ œ์–ดํ•ด์•ผ ํ•  ๋•Œ, Proxy์™€ Reflect๋ฅผ ์ ์šฉํ•ด ๋ณด๋Š” ์—ฐ์Šต์„ ํ•ด๋ณด์„ธ์š”.

๐Ÿ“ฎ ์ฐธ๊ณ 

์—ฐ๊ด€๋œ ํฌ์ŠคํŠธ