Please enable JavaScript to view the comments powered by Disqus.

[๋ฒˆ์—ญ] ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ฐ˜์‘์„ฑ(Reactivity)์— ๋Œ€ํ•œ ๊ฐ€์žฅ ์ข‹์€ ์„ค๋ช…

Gregg Pollack์˜ The Best Explanation of JavaScript Reactivity ๐ŸŽ†๋ฅผ ๋ฒˆ์—ญํ•œ ๊ธ€์ด๋‹ค.

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


main

๋งŽ์€ ํ”„๋ก ํŠธ์—”๋“œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํ”„๋ ˆ์ž„์›Œํฌ(Angular, React, Vue, etc)๋Š” ์ž์‹ ๋งŒ์˜ ๋ฐ˜์‘์„ฑ(Reactivity) ์—”์ง„์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ๋ฐ˜์‘์„ฑ์ด ๋ฌด์—‡์ธ์ง€, ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€๋ฅผ ์ดํ•ดํ•จ์œผ๋กœ์จ ๋‹น์‹ ์˜ ๊ฐœ๋ฐœ ๊ธฐ์ˆ ์„ ํ–ฅ์ƒํ•  ์ˆ˜ ์žˆ๊ณ  ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๋ณด๋‹ค ํšจ์œจ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์•„๋ž˜์˜ ์˜์ƒ๊ณผ ๋น„๋””์˜ค๋ฅผ ํ†ตํ•ด ์šฐ๋ฆฌ๋Š” Vue ์†Œ์Šค ์ฝ”๋“œ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ์ข…๋ฅ˜์˜ Reactivity๋ฅผ ๊ตฌํ˜„ํ•  ๊ฒƒ์ด๋‹ค.

๊ธ€์„ ์ฝ๋Š” ๋Œ€์‹  ๋น„๋””์˜ค๋ฅผ ์‹œ์ฒญํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์ด ์‹œ๋ฆฌ์ฆˆ์˜ ๋‹ค์Œ ์˜์ƒ์„ ๋ณด๋ฉด์„œ Vue๋ฅผ ๋งŒ๋“  Evan You์™€ ํ•จ๊ป˜ ๋ฐ˜์‘์„ฑ๊ณผ ํ”„๋ก์‹œ์— ๋Œ€ํ•ด ํ† ๋ก ํ•˜๋Š” ๋‚ด์šฉ์„ ํ™•์ธํ•˜๊ธธ ๋ฐ”๋ž€๋‹ค.

๋ฐ˜์‘์„ฑ ์‹œ์Šคํ…œ

Vue์˜ ๋ฐ˜์‘์„ฑ ์‹œ์Šคํ…œ์„ ์ฒ˜์Œ ๋ณด๋ฉด ๋งˆ์น˜ ๋งˆ๋ฒ•์ฒ˜๋Ÿผ ๋Š๊ปด์งˆ ์ˆ˜ ์žˆ๋‹ค. ๊ฐ„๋‹จํ•œ Vue ์•ฑ์„ ํ™•์ธํ•ด๋ณด์ž.

code 1

code 2

Vue๊ฐ€ ๋งŒ์•ฝ price ๊ฐ’์ด ๋ณ€ํ–ˆ๋‹ค๋Š” ์‚ฌ์‹ค์„ ์•Œ๊ฒŒ ๋œ๋‹ค๋ฉด ์•„๋ž˜ 3๊ฐ€์ง€ ์ผ์„ ํ•  ๊ฒƒ์ด๋‹ค.

  • ์›นํŽ˜์ด์ง€์˜ price ๊ฐ’์„ ์—…๋ฐ์ดํŠธํ•œ๋‹ค.
  • price * quantity ๋ฅผ ๋‹ค์‹œ ๊ณ„์‚ฐํ•˜๊ณ  ํŽ˜์ด์ง€๋ฅผ ์—…๋ฐ์ดํŠธํ•œ๋‹ค.
  • totalPriceWithTax ํ•จ์ˆ˜๋ฅผ ๋‹ค์‹œ ํ˜ธ์ถœํ•˜๊ณ  ํŽ˜์ด์ง€๋ฅผ ์—…๋ฐ์ดํŠธํ•œ๋‹ค.

ํ•˜์ง€๋งŒ ์ž ๊น, ๋‹น์‹ ์€ ์ด๋Ÿฐ ์˜๋ฌธ์„ ๊ฐ€์ง€๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค. Vue๋Š” price๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ๋ฌด์—‡์„ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•˜๋Š”์ง€ ์–ด๋–ป๊ฒŒ ์•Œ๋ฉฐ, ์–ด๋–ป๊ฒŒ ๋ชจ๋“  ๊ฒƒ์„ ์ถ”์ ํ•˜๊ณ  ์žˆ๋Š”๊ฐ€?

code 3

Vue๊ฐ€ ํ•˜๋Š” ์ผ์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์ผ๋ฐ˜์ ์œผ๋กœ ๋™์ž‘ํ•˜๋Š” ๋ฐฉ์‹์ด ์•„๋‹ˆ๋‹ค.

๋‹ค์‹œ ๋งํ•ด, ์šฐ๋ฆฌ๊ฐ€ ์˜๋ฌธ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ฌธ์ œ๋Š” ์ผ๋ฐ˜์ ์ธ ํ”„๋กœ๊ทธ๋žจ ๋™์ž‘ ๋ฐฉ์‹์ด ์•„๋‹ˆ๋ผ๋Š” ๋ง์ด๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋งŒ์•ฝ ์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค๋ฉด:

code 4

๋ฌด์—‡์ด ์ถœ๋ ฅ๋  ๊ฒƒ์œผ๋กœ ์ƒ๊ฐํ•˜๋Š”๊ฐ€? ๋ณดํ†ต์˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ฝ”๋“œ๋ผ์„œ 10์„ ์ถœ๋ ฅํ•  ๊ฒƒ์ด๋‹ค.

code 5

Vue์—์„œ๋Š” ์šฐ๋ฆฌ๋Š” price๋‚˜ quantity๊ฐ€ ์—…๋ฐ์ดํŠธ๋˜๋ฉด total๋„ ์—…๋ฐ์ดํŠธ๋˜๊ธธ ๋ฐ”๋ž€๋‹ค. ๋ฐ”๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ถœ๋ ฅ๋˜๊ธธ ์›ํ•œ๋‹ค:

code 6

ํ•˜์ง€๋งŒ ๋ถˆํ–‰ํžˆ๋„ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ๋ฐ˜์‘ํ˜•์ด ์•„๋‹ˆ๋ผ ์ ˆ์ฐจ์ (procedural) ์–ธ์–ด๋ผ์„œ ์šฐ๋ฆฌ๊ฐ€ ๊ธฐ๋Œ€ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๋ฐ”๋กœ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š”๋‹ค. total ๋ณ€์ˆ˜๊ฐ€ ๋ฐ˜์‘์ ์ด ๋˜๋„๋ก ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋‹ค๋ฅธ ์ ‘๊ทผ ๋ฐฉ์‹์ด ํ•„์š”ํ•˜๋‹ค.

โš ๏ธ ๋ฌธ์ œ

total ๊ฐ’์„ ๊ณ„์‚ฐํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ €์žฅํ•ด ๋‘˜ ํ•„์š”๊ฐ€ ์žˆ๊ณ , price๋‚˜ quantity ๊ฐ’์ด ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค ๊ทธ ์ฝ”๋“œ๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•ด์•ผ ํ•œ๋‹ค.

โœ… ํ•ด๊ฒฐ์ฑ…

์šฐ์„  ์šฐ๋ฆฌ์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—๊ฒŒ ๋‹ค์Œ์˜ ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌํ•  ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•˜๋‹ค, โ€œ๋‚ด๊ฐ€ ์‹คํ–‰ํ•˜๋ ค๋Š” ์ฝ”๋“œ๊ฐ€ ํ•˜๋‚˜ ์žˆ๋Š”๋ฐ, ์ด๊ฑธ ์ €์žฅํ•ด ๋‘ฌ. ๋‚˜์ค‘์— ๋„ค๊ฐ€ ๋‹ค์‹œ ์‹คํ–‰ํ•  ํ•„์š”๊ฐ€ ์ƒ๊ธธ๊ฑฐ์•ผโ€. ๊ทธ๋Ÿฐ ์ผ์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด ์šฐ๋ฆฌ๋Š” ์ฝ”๋“œ๋ฅผ ํ•œ๋ฒˆ ์‹คํ–‰ํ•œ ํ›„์—, price๋‚˜ quantity ๊ฐ’์ด ๋ฐ”๋€” ๋•Œ ์•ž์„œ ์ €์žฅ๋œ ์ฝ”๋“œ๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•˜๋ฉด ๋œ๋‹ค.

code 7

์ด๋Š” ํ•จ์ˆ˜๋ฅผ ๊ธฐ๋กํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ํ†ตํ•ด ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

code 8

target ๋ณ€์ˆ˜์— ์ต๋ช… ํ•จ์ˆ˜๋ฅผ ํ• ๋‹นํ•ด์„œ ์žฌ์‹คํ–‰ํ•  ์ฝ”๋“œ๋ฅผ ์ €์žฅํ•˜๊ณ , record ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ–ˆ๋‹ค. ES6 ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์•„๋ž˜์ฒ˜๋Ÿผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

code 9

ํ•จ์ˆ˜ record๋Š” ๊ฐ„๋‹จํžˆ ์•„๋ž˜์ฒ˜๋Ÿผ ์ •์˜ํ•œ๋‹ค.

code 10 storage ๋ฐฐ์—ด์— target ํ•จ์ˆ˜๋ฅผ ์ €์žฅํ•œ๋‹ค.

target (์ฝ”๋“œ์—์„œ๋Š” { total = price * quantity })์„ ์ €์žฅํ–ˆ์œผ๋‹ˆ ๋‚˜์ค‘์— ๋‹ค์‹œ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ €์žฅํ•œ ๋ชจ๋“  ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•  replay ํ•จ์ˆ˜๊ฐ€ ํ•„์š”ํ•  ๊ฒƒ์ด๋‹ค.

code 11

replay ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜๋ฉด storage ๋ฐฐ์—ด์— ์ €์žฅํ•œ ๋ชจ๋“  ์ต๋ช… ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

์ด์ œ ๊ฐ„๋‹จํžˆ ๋‹ค์Œ์ฒ˜๋Ÿผ ํ•˜๋ฉด ๋œ๋‹ค.

code 12

๊ฐ„๋‹จํ•˜์ง€ ์•Š์€๊ฐ€? ์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ์ „์ฒด ํ๋ฆ„์„ ๋‹ค์‹œ ํ•œ ๋ฒˆ ์‚ดํŽด๋ณด๊ธฐ ๋ฐ”๋ž€๋‹ค.

code 13

โš ๏ธ ๋ฌธ์ œ

ํ•„์š”ํ•œ ๋งŒํผ target์„ ๊ธฐ๋กํ•ด ๋‘˜ ์ˆ˜ ์žˆ์ง€๋งŒ, ์•ฑ์˜ ํ™•์žฅ์„ฑ์„ ์œ„ํ•ด ๋ณด๋‹ค ๊ฐ•๋ ฅํ•œ ์†”๋ฃจ์…˜์„ ๋งŒ๋“œ๋Š” ํŽธ์ด ์ข‹์„ ๊ฒƒ์ด๋‹ค. target ๋ชฉ๋ก์„ ์œ ์ง€ํ•˜๋ฉด์„œ ์šฐ๋ฆฌ๊ฐ€ ํ•„์š”ํ•  ๋•Œ ์žฌ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ์•Œ๋ ค์ฃผ๋Š” ํด๋ž˜์Šค ๊ฐ™์€ ๊ฒƒ ๋ง์ด๋‹ค.

โœ… ํ•ด๊ฒฐ์ฑ…: ์˜์กด ํด๋ž˜์Šค

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ• ํ•˜๋‚˜๋Š” ์œ„์˜ ๋™์ž‘์„ ํ‘œ์ค€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์˜ต์ €๋ฒ„(observer) ํŒจํ„ด์„ ๊ตฌํ˜„ํ•˜๋Š” ์˜์กด ํด๋ž˜์Šค๋กœ ์บก์Šํ™”(encapsulation)ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

๊ทธ๋ž˜์„œ, target ๊ฐ™์€ ์ข…์†๋ฌผ(dependencies)์„ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ํ˜•ํƒœ๊ฐ€ ๋  ๊ฒƒ์ด๋‹ค.

class Dep { // dependency์˜ ์•ฝ์ž
  constructor() {
    this.subscribers = []
    // subscribers๋Š” ํด๋ž˜์Šค์— ์ข…์†๋˜์–ด ์žˆ๋Š” target ํ•จ์ˆ˜๋“ค์„ ์ €์žฅํ•˜๋Š” ๋ฐฐ์—ด.
    // notify() ๋ฉ”์†Œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด ๋ฐฐ์—ด์— ์ €์žฅ๋œ ํ•จ์ˆ˜๋“ค์ด ์‹คํ–‰๋˜์–ด์•ผ ํ•œ๋‹ค.
  }

  depend() { // ์•ž์„œ ์ž‘์„ฑํ•œ record ํ•จ์ˆ˜๋ฅผ ๋Œ€์ฒดํ•œ๋‹ค.
    if (target && !this.subscribers.includes(target)) {
    // target์ด subscribers์— ์ €์žฅ๋˜์–ด ์žˆ์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค.
      this.subscribers.push(target)
    }
  }

  notify() { // ์•ž์„œ ์ž‘์„ฑํ•œ replay ํ•จ์ˆ˜๋ฅผ ๋Œ€์ฒดํ•œ๋‹ค.
    this.subscribers.forEach(sub => sub()) // target ๋˜๋Š” observer๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.
  }
}

์ด์ œ storage ๋Œ€์‹  subscribers์— ์ต๋ช… ํ•จ์ˆ˜๋ฅผ ์ €์žฅํ•˜๋ฉฐ, record ํ•จ์ˆ˜ ๋Œ€์‹  depend ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  replay ํ•จ์ˆ˜ ๋Œ€์‹  notify ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์ด ํด๋ž˜์Šค๋ฅผ ์ž‘๋™์‹œ์ผœ ๋ณด์ž.

const dep = new Dep() // ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ

let price = 5
let quantity = 2
let total = 0
let target = () => { target = price * quantity }

dep.depend() // subscribers์— target ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.
target()     // target ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

console.log(total) // => 10 .. ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๊ฐ€ ๋งž๋‹ค.
price = 20
console.log(total) // => 10 .. total์ด ์ž๋™์œผ๋กœ ์—…๋ฐ์ดํŠธ ๋˜์ง€ ์•Š์•˜๋‹ค.
dep.notify()       // subscribers์— ๋“ฑ๋ก๋œ ํ•จ์ˆ˜๋“ค์„ ์‹คํ–‰ํ•œ๋‹ค.
console.log(total) // => 40 .. ์ œ๋Œ€๋กœ ๋œ ๊ฒฐ๊ณผ๋ฅผ ์–ป์—ˆ๋‹ค.

์ž˜ ์ž‘๋™ํ•œ๋‹ค. ์ด์ œ ์šฐ๋ฆฌ์˜ ์ฝ”๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค. ์—ฌ์ „ํžˆ ์ด์ƒํ•˜๊ฒŒ ๋Š๊ปด์ง€๋Š” ๊ฑด target์„ ๋“ฑ๋กํ•˜๊ณ  ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.

โš ๏ธ ๋ฌธ์ œ

๊ฐœ๋ฐœ์ด ์ง„ํ–‰๋˜๋ฉด ๋ณ€์ˆ˜๋งˆ๋‹ค Dep ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์—…๋ฐ์ดํŠธ๋ฅผ ๊ฐ์ง€ํ•˜๋Š” ์—ญํ• ์„ ํ•˜๋Š” ์ต๋ช… ํ•จ์ˆ˜(target)๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ณผ์ •์„ ์บก์Šํ™”ํ•˜๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค. watcher ํ•จ์ˆ˜๊ฐ€ ์ด๋Ÿฐ ์—ญํ• ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋Ÿฌ๋ฉด ์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋Œ€์‹ :

code 14

์•„๋ž˜์ฒ˜๋Ÿผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค:

code 15

โœ… ํ•ด๊ฒฐ์ฑ…: Watcher ํ•จ์ˆ˜

Watcher ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ๋ช‡๊ฐ€์ง€ ๊ฐ„๋‹จํ•œ ์ž‘์—…์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.

function watcher(myFunc) {
  target = myFunc  // ํ˜„์žฌ ์ฒ˜๋ฆฌํ•˜๊ณ  ์žˆ๋Š” target์œผ๋กœ myFunc์„ ์„ค์ •ํ•œ๋‹ค.
  dep.depend()     // target์„ ์ข…์†๋ฌผ(=์ข…์†๋œ ์ฝ”๋“œ)๋กœ ์ถ”๊ฐ€ํ•œ๋‹ค.
  target()         // target์„ ์‹คํ–‰ํ•œ๋‹ค.
  target = null    // target์„ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค.
}

ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ watcher ํ•จ์ˆ˜๋Š” myFunc๋ฅผ ์ธ์ž๋กœ ์ „๋‹ฌ๋ฐ›๊ณ , ์ „์—ญ ๋ณ€์ˆ˜์ธ target์œผ๋กœ ํ• ๋‹นํ•˜๊ณ , dep.depend()๋ฅผ ํ˜ธ์ถœํ•ด์„œ subscriber์— ์ถ”๊ฐ€ํ•˜๊ณ , target์„ ํ˜ธ์ถœํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  target๋ฅผ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค.

code 16

code 17

๋‹น์‹ ์€ ์•„๋งˆ ์™œ target์„ ํ•จ์ˆ˜์— ์ง์ ‘ ์ „๋‹ฌํ•˜์ง€ ์•Š๊ณ  ์ „์—ญ ๋ณ€์ˆ˜๋กœ ์„ค์ •ํ–ˆ๋Š”์ง€ ๊ถ๊ธˆํ•  ๊ฒƒ์ด๋‹ค. ์ด๋ ‡๊ฒŒ ๊ตฌํ˜„ํ•œ ๋ฐ์—๋Š” ์ด์œ ๊ฐ€ ์žˆ์œผ๋ฉฐ, ์ด ๊ธ€์˜ ๋‹ค ์ฝ์œผ๋ฉด ๊ทธ ์ด์œ ๊ฐ€ ๋ช…ํ™•ํ•ด์ง€๊ณ  ์ข‹์€ ๋ฐฉ๋ฒ•์ด์—ˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค.

โš ๏ธ ๋ฌธ์ œ

์šฐ๋ฆฌ๋Š” ํ•˜๋‚˜์˜ Dep ํด๋ž˜์Šค๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ๊ฐ€ ์ •๋ง๋กœ ์›ํ•˜๋Š” ๊ฒƒ์€ ๋ณ€์ˆ˜๋งˆ๋‹ค ๊ทธ๋งŒ์˜ Dep ํด๋ž˜์Šค๋ฅผ ๊ฐ€์ง€๋Š” ๊ฒƒ์ด๋‹ค. ๋” ์ง„ํ–‰ํ•˜๊ธฐ ์ „์— ๊ฐ’๋“ค์„ ๊ฐ์ฒด์˜ ์†์„ฑ์œผ๋กœ ์˜ฎ๊ธฐ๋„๋ก ํ•˜์ž.

code 18

๊ฐ๊ฐ์˜ ์†์„ฑ(price์™€ quantity)์ด ๊ฐ๊ฐ Dep ํด๋ž˜์Šค๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๊ณ  ์ž ์‹œ๋™์•ˆ ๊ฐ€์ •ํ•ด๋ณด์ž.

code 19

์ด์ œ๋Š” ์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

code 20

watcher์— ์ „๋‹ฌ๋œ ์ต๋ช… ํ•จ์ˆ˜(target) ๋‚ด๋ถ€์—์„œ data.price ๊ฐ’์ด ์‚ฌ์šฉ๋˜์—ˆ๋‹ค. ์žฌ์‹คํ–‰ํ•  ์ฝ”๋“œ์—์„œ data.price ๊ฐ’์ด ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์œผ๋‹ˆ price ์†์„ฑ์— ์—ฐ๊ฒฐ๋œ Dep ํด๋ž˜์Šค์˜ subscriber ๋ฐฐ์—ด(์ €์žฅ์†Œ)์— ์ด ์ต๋ช… ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€(dep.depend())ํ•˜๊ณ  ์‹ถ๋‹ค. ์ต๋ช… ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ data.quantity ๊ฐ’๋„ ์‚ฌ์šฉ๋˜์—ˆ์œผ๋‹ˆ data.quantity์— ์—ฐ๊ฒฐ๋œ Dep ํด๋ž˜์Šค์—๋„ ๊ฐ™์€ ์ž‘์—…์„ ํ•˜๊ณ  ์‹ถ๋‹ค.

code 21

๋งŒ์•ฝ data.price๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ ์ต๋ช… ํ•จ์ˆ˜๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด, ๊ทธ ํ•จ์ˆ˜๋Š” price ์†์„ฑ์˜ Dep ํด๋ž˜์Šค์—๋งŒ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ๋‹ค.

code 22 ์ถ”๊ฐ€๋˜๋Š” watcher๋Š” ์†์„ฑ๋“ค ์ค‘ ํ•˜๋‚˜์—๋งŒ ์ ์šฉ๋  ๊ฒƒ์ด๋‹ค

์–ด๋Š ์‹œ์ ์— price์˜ subscriber์— ์—ฐ๊ฒฐ๋œ dep.notify()๊ฐ€ ํ˜ธ์ถœ๋˜์–ด์•ผ ํ• ๊นŒ? ๋‚˜๋Š” ๊ทธ ์ˆœ๊ฐ„์ด price ์†์„ฑ์— ๊ฐ’์ด ํ• ๋‹น๋˜์—ˆ์„ ๋•Œ๊ฐ€ ๋˜๊ธธ ๋ฐ”๋ž€๋‹ค. ๋ชจ๋“  ๊ฒƒ์ด ๊ตฌํ˜„๋˜๋ฉด ์ฝ˜์†”์—์„œ ์•„๋ž˜์™€ ๊ฐ™์€ ์ถœ๋ ฅ์„ ๋ณด๊ณ  ์‹ถ๋‹ค.

code 23

์šฐ๋ฆฌ๋Š” data ์†์„ฑ(price๋‚˜ quantity)์— ์›ํ•˜๋Š” ๋™์ž‘์„ ์—ฐ๊ฒฐํ• (hook into) ์–ด๋–ค ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•˜๋‹ค. ๊ทธ๋Ÿฌ๋ฉด target ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ์–ด๋–ค ์†์„ฑ์ด ์ฐธ์กฐ๋˜๋ฉด ๊ทธ ์†์„ฑ์˜ subscriber ๋ฐฐ์—ด์— target์„ ์ €์žฅํ•  ์ˆ˜ ์žˆ๊ณ , ์†์„ฑ์ด ๋ณ€๊ฒฝ๋˜๋ฉด subscribers ๋ฐฐ์—ด์— ์ €์žฅ๋œ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

โœ… ํ•ด๊ฒฐ์ฑ…: Object.defineProperty()

ES5์—์„œ ์ œ๊ณตํ•˜๋Š” Object.defineProperty ํ•จ์ˆ˜์— ๋Œ€ํ•ด ๊ณต๋ถ€ํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค. ์ด ํ•จ์ˆ˜๋Š” ์šฐ๋ฆฌ์—๊ฒŒ ๊ฐ์ฒด ์†์„ฑ์˜ getter์™€ setter ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค. ์ด ํ•จ์ˆ˜๋ฅผ Dep ํด๋ž˜์Šค์— ์ ์šฉํ•˜๊ธฐ ์ „์— ๊ธฐ๋ณธ์ ์ธ ์‚ฌ์šฉ๋ฒ•์„ ์‚ดํŽด๋ณด์ž.

let data = { price: 5, quantity: 2 }

Object.defineProperty(data, 'price', { // data์˜ price ์†์„ฑ์— ๋Œ€ํ•ด์„œ๋งŒ ์ •์˜ํ•œ๋‹ค.
  get() { // get ํ•จ์ˆ˜ ์ƒ์„ฑ. price์˜ ๊ฐ’์„ ์ฐธ์กฐํ•˜๋Š” ์—ญํ• 
    console.log('I was accessed')
  }

  set(newValue) { // set ํ•จ์ˆ˜ ์ƒ์„ฑ. price์— ์ƒˆ๋กœ์šด ๊ฐ’์„ ํ• ๋‹นํ•˜๋Š” ์—ญํ• 
    console.log('I was changed')
  }
})

code 24

code 25

๋ณด์ด๋Š” ๋ฐ”์™€ ๊ฐ™์ด ๋‹จ์ง€ 2์ค„์ด ๋กœ๊ทธ์— ํ‘œ์‹œ๋œ๋‹ค. ํ•˜์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ์–ด๋–ค ๊ฐ’๋„ ๊ฐ€์ ธ์˜ค๊ฑฐ๋‚˜(get) ํ• ๋‹นํ•˜์ง€(set) ์•Š๋Š”๋‹ค. ์šฐ๋ฆฌ๊ฐ€ get, set ํ•จ์ˆ˜๋ฅผ ์ƒˆ๋กœ ๋ฎ์–ด์”Œ์› ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ทธ๋Ÿฌ๋‹ˆ ๋‹ค์‹œ ํ•„์š”ํ•œ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋„๋ก ํ•˜์ž. get() ํ•จ์ˆ˜๋Š” ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•˜๊ณ , set() ํ•จ์ˆ˜๋Š” ๊ฐ’์„ ๊ฐฑ์‹ ํ•ด์•ผ ํ•œ๋‹ค. ๊ทธ๋ฅผ ์œ„ํ•ด intervalValue๋ผ๋Š” ๋ณ€์ˆ˜์— ํ˜„์žฌ price๊ฐ’์„ ์ €์žฅํ•œ๋‹ค.

code 26 internalValue์—์„œ ์‹ค์ œ ๊ฐ’์„ ๊ด€๋ฆฌํ•œ๋‹ค.

์ด์ œ ์šฐ๋ฆฌ์˜ get, set ํ•จ์ˆ˜๋Š” ์ œ๋Œ€๋กœ ๋™์ž‘ํ•œ๋‹ค. ์ฝ˜์†”์—๋Š” ๋ฌด์—‡์ด ์ถœ๋ ฅ๋ ๊นŒ?

code 27

์ด๋ ‡๊ฒŒ ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๊ณ (get) ํ• ๋‹นํ•  ๋•Œ(set) ์•Œ๋ฆผ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์žฌ๊ท€(recursion)๋ฅผ ์กฐ๊ธˆ ์‚ฌ์šฉํ•˜๋ฉด ๋ชจ๋“  ์†์„ฑ์—์„œ ์ด ๊ธฐ๋Šฅ์ด ์ž‘๋™ํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.

code 28 Object.keys ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์„œ data ๊ฐ์ฒด์— ์กด์žฌํ•˜๋Š” ๋ชจ๋“  ์†์„ฑ์— ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ–ˆ๋‹ค

์ด์ œ ๋ชจ๋“  ์†์„ฑ์ด getter์™€ setter ํ•จ์ˆ˜๋ฅผ ๊ฐ€์ง€๊ฒŒ ๋œ ๊ฒƒ์„ ์ฝ˜์†”์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

code 29

๐Ÿ›  ์ง€๊ธˆ๊นŒ์ง€์˜ ์•„์ด๋””์–ด๋ฅผ ํ•ฉ์น˜๊ธฐ

code 30

์œ„์˜ ์ฝ”๋“œ์ฒ˜๋Ÿผ price์˜ ๊ฐ’์„ ์‚ฌ์šฉ(get)ํ•œ๋‹ค๋ฉด, ์œ„์˜ ์ฝ”๋“œ(target)๊ฐ€ price ๊ฐ’์— ์˜์กดํ•˜๊ณ  ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์„ ๊ธฐ๋กํ•ด๋‘๊ณ  ์‹ถ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ํ•ด ๋‘”๋‹ค๋ฉด price ๊ฐ’์˜ ๋ณ€๊ฒฝ์ด๋‚˜ ์ƒˆ๋กœ์šด ๊ฐ’์˜ ํ• ๋‹น์ด ์ €์žฅํ•ด๋‘” ์ฝ”๋“œ๋ฅผ ์žฌ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ณ„๊ธฐ(trigger)๊ฐ€ ๋˜๋„๋ก ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค. ์šฐ๋ฆฌ์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์–ด๋–ค ์ฝ”๋“œ๊ฐ€ price์— ์˜์กดํ•˜๊ณ  ์žˆ๋Š”์ง€ ์•Œ๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋”ฐ๋ผ์„œ getter์™€ setter๋ฅผ ์•„๋ž˜์ฒ˜๋Ÿผ ๋™์ž‘ํ•˜๋„๋ก ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๋‹ค.

Get => ์ด ์ต๋ช… ํ•จ์ˆ˜๋ฅผ ๊ธฐ์–ตํ•ด๋ผ, ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ ๋‹ค์‹œ ์‹คํ–‰ํ•  ๊ฒƒ์ด๋‹ค.

Set => ์ €์žฅ๋œ ์ต๋ช… ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•ด๋ผ. ๊ฐ’์€ ๋ฐฉ๊ธˆ ๋ณ€๊ฒฝ๋˜์—ˆ๋‹ค.

Dep Class์˜ ๊ฒฝ์šฐ์—๋Š”

Price๊ฐ€ ์‚ฌ์šฉ๋˜์—ˆ๋‹ค (get) => dep.depend() ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด์„œ ํ˜„์žฌ target์„ ์ €์žฅํ•ด๋ผ.

Price๊ฐ€ ํ• ๋‹น๋˜์—ˆ๋‹ค (set) => price์˜ dep.notify()๋ฅผ ํ•ด์„œ ๋ชจ๋“  targets๋ฅผ ์žฌ์‹คํ–‰ํ•ด๋ผ.

์ด ๋‘๊ฐ€์ง€ ์•„์ด๋””์–ด๋ฅผ ์กฐํ•ฉํ•œ ์ตœ์ข… ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด์ž.

let data = { price: 5, quantity: 2 }
let target = null

// ์•ž์—์„œ ์„ ์–ธํ•œ Dep ํด๋ž˜์Šค์™€ ๋™์ผํ•˜๋‹ค.
class Dep {
  constructor() {
    this.subscribers = []
  }

  depend() {
    if (target && !this.subscribers.includes(target)) {
      // target์ด ์กด์žฌํ•˜๋ฉฐ subscribers์— ํฌํ•จ๋˜์–ด ์žˆ์ง€ ์•Š์„ ๋•Œ๋งŒ ์ถ”๊ฐ€ํ•œ๋‹ค.
      this.subscribers.push(target)
    }
  }

  notify() {
    this.subscribers.forEach(sub => sub())
  }
}

// data ๊ฐ์ฒด๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ชจ๋“  ์†์„ฑ์— ์ ์šฉํ•œ๋‹ค
Object.keys(data).forEach(key => {
  let internalValue = data[key]

  // ๊ฐ๊ฐ์˜ ์†์„ฑ์€ ์ž๊ธฐ๋งŒ์˜ Dep ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€์ง„๋‹ค.
  const dep = new Dep()

  // data ๊ฐ์ฒด ์†์„ฑ์˜ getter, setter๋ฅผ ์žฌ์„ค์ •ํ•œ๋‹ค.
  Object.defineProperty(data, key, {
    get() {
      // getter๊ฐ€ ํ˜ธ์ถœ๋œ ์‹œ์ ์˜ target์„ ๊ธฐ์–ตํ•˜๋„๋ก ํ•œ๋‹ค.
      dep.depend()
      return internalValue
    },
    set(newVal) {
      internalValue = newVal
      dep.notify() // ์ €์žฅ๋œ ํ•จ์ˆ˜(target)๋ฅผ ์žฌ์‹คํ–‰
    }
  })
})

// watcher๋Š” ๋” ์ด์ƒ dep.depend๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๋Š”๋‹ค.
// ์™œ๋ƒํ•˜๋ฉด get ๋ฉ”์†Œ๋“œ ์•ˆ์—์„œ ์ž๋™์œผ๋กœ ํ˜ธ์ถœ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
function watcher(myFunc) {
  target = myFunc
  target() // ํ• ๋‹น๋œ ์ฝ”๋“œ๋Š” ๋ฌด์กฐ๊ฑด 1๋ฒˆ์€ ์‹คํ–‰๋˜์–ด์•ผ ํ•œ๋‹ค.
  target = null
}

// watcher์— ์ „๋‹ฌ๋œ ์ด ์ต๋ช…ํ•จ์ˆ˜์—์„œ price์™€ quantity์˜ getter ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋œ๋‹ค.
// watcher๊ฐ€ ์‹คํ–‰๋œ ์‹œ์ ์—์„œ ์ „์—ญ ๋ณ€์ˆ˜ target์—๋Š” watcher์˜ ์ธ์ž๋กœ ์ „๋‹ฌ๋œ ์ต๋ช… ํ•จ์ˆ˜๊ฐ€ ํ• ๋‹น๋œ๋‹ค
watcher(() => {
  data.total = data.price * data.quantity
})

์ด์ œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ์ฝ˜์†”์— ๋ฌด์—‡์ด ์ถœ๋ ฅ๋˜๋Š”์ง€ ํ™•์ธํ•ด๋ณด์ž.

code 32

์šฐ๋ฆฌ๊ฐ€ ํ•˜๊ณ  ์‹ถ์—ˆ๋˜ ๊ฒƒ๊ณผ ์ •ํ™•ํžˆ ์ผ์น˜ํ•œ๋‹ค! price์™€ quantity ๋ชจ๋‘ ํ™•์‹คํžˆ ๋ฐ˜์‘ํ•œ๋‹ค! watcher ํ•จ์ˆ˜์— ์ „๋‹ฌํ•œ ์ต๋ช… ํ•จ์ˆ˜๋Š” price ๋˜๋Š” quantity ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ์žฌ์‹คํ–‰๋˜๊ณ  ์žˆ๋‹ค.

Vue ๋ฌธ์„œ์—์„œ ๊ฐ€์ ธ์˜จ ์ด ๊ทธ๋ฆผ์€ ์ด์ œ ์ดํ•ด๊ฐ€ ๋  ๊ฒƒ์ด๋‹ค.

code 33

Data์™€ getter, setter๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์•„๋ฆ„๋‹ค์šด ๋ณด๋ผ์ƒ‰ ๋™๊ทธ๋ผ๋ฏธ๊ฐ€ ๋ณด์ด๋Š”๊ฐ€? ์•„๋งˆ ์ต์ˆ™ํ•˜๊ฒŒ ๋ณด์ผ ๊ฒƒ์ด๋‹ค! ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ ์ธ์Šคํ„ด์Šค๋Š” getter๋ฅผ ํ†ตํ•ด ์ข…์†๋ฌผ์„ ์ˆ˜์ง‘ํ•˜๋Š”(๋ถ‰์€ ์ ์„ ) watcher ์ธ์Šคํ„ด์Šค(ํŒŒ๋ž€์ƒ‰)๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. setter๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด Data๋Š” watcher์—๊ฒŒ ์•Œ๋ฆผ(Notify)์„ ๋ณด๋‚ด์„œ ์ปดํฌ๋„ŒํŠธ re-render๋กœ ์ด์–ด์ง€๊ฒŒ ํ•œ๋‹ค. ์•„๋ž˜๋Š” ๋‚ด๊ฐ€ ์ฃผ์„์„ ์ถ”๊ฐ€ํ•œ ๊ทธ๋ฆผ์ด๋‹ค.

code 34

์–ด๋–ค๊ฐ€, ์ด์ชฝ์ด ์šฐ๋ฆฌ๊ฐ€ ์ง€๊ธˆ๊นŒ์ง€ ์‚ดํŽด๋ณธ ์ฝ”๋“œ๋ฅผ ๋– ์˜ฌ๋ฆฌ๊ฒŒ ํ•˜๋ฉด์„œ ๋” ์ž˜ ์™€๋‹ฟ์ง€ ์•Š๋Š”๊ฐ€??

์‚ฌ์‹ค Vue์˜ ๋ฐ˜์‘์„ฑ ์—”์ง„์€ ์ด๊ฒƒ๋ณด๋‹ค ํ›จ์”ฌ ๋” ๋ณต์žกํ•˜๋‹ค. ํ•˜์ง€๋งŒ ๋‹น์‹ ์€ ์ด์ œ ๊ธฐ์ดˆ๋ฅผ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค.

โช ์ง€๊ธˆ๊นŒ์ง€ ํ•™์Šตํ•œ ๋‚ด์šฉ

  • ์ข…์†๋ฌผ(์ข…์†๋œ ์ฝ”๋“œ, dependencies)๋ฅผ ์ˆ˜์ง‘ํ•˜๋Š”(depend) Dep class๋ฅผ ์–ด๋–ป๊ฒŒ ์„ ์–ธํ•˜๊ณ , ์–ด๋–ป๊ฒŒ ์˜์กด ์ฝ”๋“œ๋ฅผ ์žฌ์‹คํ–‰ํ•˜๋Š”์ง€(notify)
  • ์ข…์†๋ฌผ๋กœ ์ถ”๊ฐ€๋  ์ˆ˜ ์žˆ๋Š” ์‹คํ–‰ ์ฝ”๋“œ(target)๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด watcher๋ฅผ ์–ด๋–ป๊ฒŒ ์ƒ์„ฑํ•˜๋Š”์ง€.
  • getter์™€ setter๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด Object.defineProperty()๋ฅผ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€

์ด ๋‹ค์Œ์€?

์ด ๊ธ€์„ ํ†ตํ•ด ๋ฐฐ์šด ๋‚ด์šฉ์— ํฅ๋ฏธ๋ฅผ ๋Š๊ผˆ๋‹ค๋ฉด ๋‹ค์Œ ๋‹จ๊ณ„๋Š” Reactivity with Proxies๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‚ด๊ฐ€ Vue ๊ฐœ๋ฐœ์ž์ธ Evan You์™€ ํ•จ๊ป˜ ์ด ์ฃผ์ œ์— ๋Œ€ํ•ด์„œ ์ด์•ผ๊ธฐํ•˜๋Š” ๋ฌด๋ฃŒ ๋™์˜์ƒ๋„ VueMastery.com์—์„œ ๊ผญ ํ™•์ธํ•ด ๋ณด๊ธธ ๋ฐ”๋ž€๋‹ค.