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

๋ฉ”ํƒ€ํ”„๋กœ๊ทธ๋ž˜๋ฐ

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

ํ”„๋ก์‹œ

Proxy ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํŠน์ • ๋™์ž‘์„ ๊ฐ€๋กœ์ฑ„๊ณ  ์‚ฌ์šฉ์ž ์ •์˜ ๋™์ž‘์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ๊ฐ์ฒด์—์„œ ์†์„ฑ์„ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒฝ์šฐ,

js
const handler = {
  get(target, name) {
    return name in target ? target[name] : 42;
  },
};

const p = new Proxy({}, handler);
p.a = 1;
console.log(p.a, p.b); // 1, 42

Proxy ๊ฐ์ฒด๋Š” target(์—ฌ๊ธฐ์„œ๋Š” ๋นˆ ๊ฐ์ฒด)๊ณผ get ํ•จ์ •์ด ๊ตฌํ˜„๋œ handler ๊ฐ์ฒด๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ํ”„๋ก์‹œ๋œ ๊ฐ์ฒด๊ฐ€ ์ •์˜๋˜์ง€ ์•Š์€ ์†์„ฑ์„ ๊ฐ€์ ธ์˜ฌ ๋•Œ undefined๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๊ณ  ๋Œ€์‹  ์ˆซ์ž 42๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์ถ”๊ฐ€ ์˜ˆ์ œ๋Š” Proxy ์ฐธ๊ณ  ํŽ˜์ด์ง€์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์šฉ์–ด

ํ”„๋ก์‹œ ๊ธฐ๋Šฅ์„ ์„ค๋ช…ํ•  ๋•Œ ๋‹ค์Œ ์šฉ์–ด๊ฐ€ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

handler

ํŠธ๋žฉ์„ ํฌํ•จํ•˜๋Š” ์ž๋ฆฌ ํ‘œ์‹œ์ž ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.

traps

์†์„ฑ ์ ‘๊ทผ๊ณผ ๊ฐ™์€ ๋™์ž‘์„ ์ œ๊ณตํ•˜๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค. (์šด์˜์ฒด์ œ์˜ 'ํŠธ๋žฉ' ๊ฐœ๋…๊ณผ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค.)

target

ํ”„๋ก์‹œ๊ฐ€ ๊ฐ€์ƒํ™”ํ•˜๋Š” ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค. ํ”„๋ก์‹œ์˜ ์ €์žฅ์†Œ ๋ฐฑ์—”๋“œ๋กœ ์ž์ฃผ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๊ฐ์ฒด์˜ ํ™•์žฅ ๋ถˆ๊ฐ€ ์—ฌ๋ถ€๋‚˜ ์„ค์ • ๋ถˆ๊ฐ€ ์†์„ฑ ๊ด€๋ จ ๋ถˆ๋ณ€์„ฑ(๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š” ์˜๋ฏธ)์€ target์„ ๊ธฐ์ค€์œผ๋กœ ๊ฒ€์ฆ๋ฉ๋‹ˆ๋‹ค.

invariants

์‚ฌ์šฉ์ž ์ •์˜ ๋™์ž‘์„ ๊ตฌํ˜„ํ•  ๋•Œ ์ง€์ผœ์•ผ ํ•˜๋Š” '๋ถˆ๋ณ€์„ฑ'์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ํ•ธ๋“ค๋Ÿฌ์˜ ๋ถˆ๋ณ€์„ฑ์„ ์œ„๋ฐ˜ํ•˜๋ฉด TypeError๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

ํ•ธ๋“ค๋Ÿฌ์™€ ํŠธ๋žฉ

๋‹ค์Œ ํ‘œ๋Š” Proxy ๊ฐ์ฒด์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํŠธ๋žฉ์„ ์š”์•ฝํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ž์„ธํ•œ ์„ค๋ช…๊ณผ ์˜ˆ์ œ๋Š” ์ฐธ์กฐ ํŽ˜์ด์ง€๋ฅผ ํ™•์ธํ•˜์„ธ์š”.

ํ•ธ๋“ค๋Ÿฌ / ํŠธ๋žฉ ๊ฐ€๋กœ์ฑ„๊ธฐ ๋Œ€์ƒ
handler.getPrototypeOf() Object.getPrototypeOf()
Reflect.getPrototypeOf()
__proto__
Object.prototype.isPrototypeOf()
instanceof
handler.setPrototypeOf() Object.setPrototypeOf()
Reflect.setPrototypeOf()
handler.isExtensible() Object.isExtensible()
Reflect.isExtensible()
handler.preventExtensions() Object.preventExtensions()
Reflect.preventExtensions()
handler.getOwnPropertyDescriptor() Object.getOwnPropertyDescriptor()
Reflect.getOwnPropertyDescriptor()
handler.defineProperty() Object.defineProperty()
Reflect.defineProperty()
handler.has()
์†์„ฑ ์กฐํšŒ
foo in proxy
์ƒ์† ์†์„ฑ ์กฐํšŒ
foo in Object.create(proxy)
Reflect.has()
handler.get()
์†์„ฑ ์ ‘๊ทผ
proxy[foo]
proxy.bar
์ƒ์† ์†์„ฑ ์ ‘๊ทผ
Object.create(proxy)โ€‹[foo]
Reflect.get()
handler.set()
์†์„ฑ ํ• ๋‹น
proxy[foo] = bar
proxy.foo = bar
์ƒ์† ์†์„ฑ ํ• ๋‹น
Object.create(proxy)โ€‹[foo] = bar
Reflect.set()
handler.deleteProperty()
์†์„ฑ ์‚ญ์ œ
delete proxy[foo]
delete proxy.foo
Reflect.deleteProperty()
handler.ownKeys() Object.getOwnPropertyNames()
Object.getOwnPropertySymbols()
Object.keys()
Reflect.ownKeys()
handler.apply() proxy(..args)
Function.prototype.apply() ๋ฐ Function.prototype.call()
Reflect.apply()
handler.construct() new proxy(...args)
Reflect.construct()

์ทจ์†Œ ๊ฐ€๋Šฅํ•œ Proxy

Proxy.revocable() ๋ฉ”์„œ๋“œ๋Š” ์ทจ์†Œ ๊ฐ€๋Šฅํ•œ Proxy ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ revoke ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ํ”„๋ก์‹œ๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ดํ›„ ํ”„๋ก์‹œ์— ๋Œ€ํ•œ ๋ชจ๋“  ๋™์ž‘์€ TypeError๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

js
const revocable = Proxy.revocable(
  {},
  {
    get(target, name) {
      return `[[${name}]]`;
    },
  },
);
const proxy = revocable.proxy;
console.log(proxy.foo); // "[[foo]]"

revocable.revoke();

console.log(proxy.foo); // TypeError: ์ทจ์†Œ๋œ ํ”„๋ก์‹œ์—์„œ 'get'์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค
proxy.foo = 1; // TypeError: ์ทจ์†Œ๋œ ํ”„๋ก์‹œ์—์„œ 'set'์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค
delete proxy.foo; // TypeError: ์ทจ์†Œ๋œ ํ”„๋ก์‹œ์—์„œ 'deleteProperty'๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค
console.log(typeof proxy); // "object", typeof๋Š” ํŠธ๋žฉ์„ ์‹คํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค

๋ฆฌํ”Œ๋ ‰์…˜(Reflection)

Reflect๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ๊ฐ€๋กœ์ฑ„๊ธฐ ๊ฐ€๋Šฅํ•œ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋‚ด์žฅ ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋“ค์€ ํ”„๋ก์‹œ ํ•ธ๋“ค๋Ÿฌ์˜ ๋ฉ”์„œ๋“œ์™€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

Reflect๋Š” ํ•จ์ˆ˜ ๊ฐ์ฒด๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.

Reflect๋Š” ๊ธฐ๋ณธ ๋™์ž‘์„ ํ•ธ๋“ค๋Ÿฌ์—์„œ target์œผ๋กœ ์ „๋‹ฌํ•  ๋•Œ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, Reflect.has()๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด in ์—ฐ์‚ฐ์ž๋ฅผ ํ•จ์ˆ˜์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

js
Reflect.has(Object, "assign"); // true

๋” ๋‚˜์€ apply() ํ•จ์ˆ˜

Reflect๊ฐ€ ๋“ฑ์žฅํ•˜๊ธฐ ์ „์—๋Š”, ์ฃผ์–ด์ง„ this ๊ฐ’๊ณผ ๋ฐฐ์—ด(๋˜๋Š” ์œ ์‚ฌ ๋ฐฐ์—ด ๊ฐ์ฒด)๋กœ ์ œ๊ณต๋œ arguments๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ์ฃผ๋กœ Function.prototype.apply() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

js
Function.prototype.apply.call(Math.floor, undefined, [1.75]);

ํ•˜์ง€๋งŒ Reflect.apply๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋” ๊ฐ„๊ฒฐํ•˜๊ณ  ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์›Œ์ง‘๋‹ˆ๋‹ค.

js
Reflect.apply(Math.floor, undefined, [1.75]);
// 1

Reflect.apply(String.fromCharCode, undefined, [104, 101, 108, 108, 111]);
// "hello"

Reflect.apply(RegExp.prototype.exec, /ab/, ["confabulation"]).index;
// 4

Reflect.apply("".charAt, "ponies", [3]);
// "i"

์†์„ฑ ์ •์˜ ์„ฑ๊ณต ์—ฌ๋ถ€ ํ™•์ธ

Object.defineProperty๋Š” ์†์„ฑ ์ •์˜์— ์„ฑ๊ณตํ•˜๋ฉด ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , ์‹คํŒจํ•˜๋ฉด TypeError๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์†์„ฑ์„ ์ •์˜ํ•˜๋ฉด์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ๋Š”์ง€ ํ™•์ธํ•˜๋ ค๋ฉด try...catch ๋ธ”๋ก์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด, Reflect.defineProperty()๋Š” ์„ฑ๊ณต ์—ฌ๋ถ€๋ฅผ ๋ถˆ๋ฆฌ์–ธ ๊ฐ’์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ, ๋‹จ์ˆœํžˆ if...else ๋ธ”๋ก์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

js
if (Reflect.defineProperty(target, property, attributes)) {
  // ์„ฑ๊ณต
} else {
  // ์‹คํŒจ
}