μλ°μ€ν¬λ¦½νΈ λ°μνμ λν μ’μ μ€λͺ (The Best Explanation of JavaScript Reactivity)
The Best Explanation of JavaScript Reactivity π
μ΄ κΈμ μμμμ νλ½μ λ°μ λ²μνμμΌλ©°, κΈμ μΆμ²λ https://medium.com/vue-mastery/the-best-explanation-of-javascript-reactivity-fea6112dd80d μ
λλ€.
κΈ°μ μ΄λ λ²μμ λν΄ μκ²¬μ΄ μμΌμλ©΄ λκΈμ λ¨κ²¨μ£Όμλ©΄ λ°μνλλ‘ νκ² μ΅λλ€. κ°μ¬ν©λλ€.
μ΄ κΈμ μμμμ νλ½μ λ°μ λ²μνμμΌλ©°, κΈμ μΆμ²λ https://medium.com/vue-mastery/the-best-explanation-of-javascript-reactivity-fea6112dd80d μ λλ€.
κΈ°μ μ΄λ λ²μμ λν΄ μκ²¬μ΄ μμΌμλ©΄ λκΈμ λ¨κ²¨μ£Όμλ©΄ λ°μνλλ‘ νκ² μ΅λλ€. κ°μ¬ν©λλ€.
λ§μ νλ‘ νΈμλ μλ°μ€ν¬λ¦½νΈ νλ μμν¬ (μ : Angular, React, and Vue)μλ μ체 λ°μν μμ§μ΄ μμ΅λλ€. λ°μνμ μλ μ리λ₯Ό μ΄ν΄νλ©΄ κ°λ° κΈ°μ μ ν₯μμν¬ μ μκ³ JavaScript νλ μμν¬λ₯Όλ³΄λ€ ν¨κ³Όμ μΌλ‘ μ¬μ© ν μ μμ΅λλ€. μλμ μμκ³Ό μν°ν΄μμλ Vue μμ€ μ½λμμ λ³Ό μ μλ κ²κ³Ό λμΌν μ’ λ₯μ λ°μν(Reactivity)μ λΉλν©λλ€.
κΈ°μ¬λ₯Ό μ½λ λμ μ΄ λΉλμ€λ₯Ό 보λ κ²½μ°μ΄ μλ¦¬μ¦ μμ μ 보μΈμ. Vueμ μ°½μμ μΈ Evan Youμ λ°μν λ° νλ‘μλ₯Ό λ Όμν©λλ€.
π‘ λ°μν μμ€ν
Vueμ λ°μν μμ€ν μ μ²μ μλμν¬ λ λ§μ μ²λΌ λ³΄μΌ μ μμ΅λλ€. μ΄ Vue μ±μ μ΄ν΄λ΄ μλ€.
Vueλ price κ°μ΄ λ°λλ©΄ μΈ κ°μ§ μμ
μ νκ² λ©λλ€.
μΉ νμ΄μ§μμ
priceκ°μ μ λ°μ΄νΈprice*quantityλ₯Ό κ³±νλ ννμμ λ€μ κ³μ°νκ³ νμ΄μ§λ₯Ό μ λ°μ΄νΈtotalPriceWithTaxν¨μλ₯Ό λ€μ νΈμΆνκ³ νμ΄μ§λ₯Ό μ λ°μ΄νΈ
μ¬κΈ°μ κΆκΈμ¦μ΄ μκΈ°μ€ν
λ°μ, priceκ° λ°λλ©΄ Vueλ 무μμ μ
λ°μ΄νΈ ν΄μΌ νλμ§λ₯Ό μ΄λ»κ² μ μ μμΌλ©°, μ΄λ»κ² μ λΆ μΆμ ν μ μμκΉμ?
μ΄λ μλ°μ€ν¬λ¦½νΈ νλ‘κ·Έλλ°μ΄ μ μμ μΌλ‘ μλνλ λ°©μμ΄ μλλλ€
μ΄ λ§μ΄ λͺ ννκ² λκ»΄μ§μ§ μμΌμλ€λ©΄, μ°λ¦¬κ° λ€λ£° μμ μ νλ‘κ·Έλλ°μ΄ λκ° μ΄λ° μμΌλ‘ μλνμ§ μλλ€λ μ μ λλ€. μλ₯Ό λ€μ΄μ μλ μ½λλ₯Ό μ€ννλ©΄ λ€μκ³Ό κ°μ΅λλ€.
μ΄λ€ κ°μ΄ λμ¬κ±° κ°λμ? Vueλ₯Ό μ¬μ©νλκ²μ΄ μλλ―λ‘ 10μ λνλΌ κ²λλ€.
Vueμμλ total λλ quantityκ° μ
λ°μ΄νΈ λ λλ§λ€ totalμ΄ μ
λ°μ΄νΈ λκΈ°λ₯Ό λ°λλλ€.
μνκΉκ²λ JavaScriptλ μ μ°¨νμ΄μ§, λ°μνμ΄ μλλ―λ‘ μ€μ λ‘λ λμνμ§ μμ΅λλ€. totalμ λ°μνμΌλ‘ λ§λ€κΈ° μν΄μ JavaScriptλ₯Ό μ¬μ©νμ¬ λ€λ₯΄κ² μλνκ² ν©λλ€.
β οΈ λ¬Έμ
totalμ κ³μ°ν΄μΌνκΈ° λλ¬Έμ price λλ quantityκ° λ³κ²½ λ λλ§λ€ μ¬μ€νν΄μΌ νλ€.
β μ루μ
μ°μ μ μΌλ‘λ μ±μ μ릴 μ μλ λ°©λ²μ΄ νμν©λλ€. "λ΄κ° μ€ννλ €κ³ νλ μ½λλ₯Ό μ μ₯ν΄ λμλ€κ° λ€λ₯Έ λ μ€νν μλ μμ΅λλ€." κ·Έλ¬λ©΄ μν λ μ½λλ₯Ό μ€ν ν μ μκ² μ£ . price λλ quantity λ³μκ° μ
λ°μ΄νΈ λλ©΄, μ μ₯λ μ½λλ₯Ό λ€μ μ€ννκ² ν©λλ€.
ν¨μλ₯Ό λ€μ μ€ννκΈ° μν΄μ μ΄ ν¨μλ₯Ό κΈ°λ‘ν΄ λ‘λλ€.
μ΅λͺ
μ ν¨μλ₯Ό target λ³μ μμ μ μ₯νκ³ ,record ν¨μλ₯Ό νΈμΆν©λλ€. ES6 νμ΄ν ꡬ문μ μ¬μ©νμ¬ λ€μκ³Ό κ°μ΄ μμ±ν μλ μμ΅λλ€.
recordμ μ μλ κ°λ¨ν©λλ€.
μ°λ¦¬λ targetμ μ μ₯νκ³ μμ΅λλ€. (ν΄λΉ μ½λμ κ²½μ° { total = price * quantity }). κΈ°λ‘ν λͺ¨λ κ²μ μ€ννλ replay ν¨μλ₯Ό λμ€μ μ€νν μλ μμ΅λλ€. .
μ΄κ²μ μ€ν λ¦¬μ§ λ°°μ΄ λ΄λΆμ μ μ₯λ λͺ¨λ μ΅λͺ ν¨μμ κ±°μ³ κ°κ°μ μ€νν©λλ€.
κ·Έλ¬λ©΄ μ½λμμ λ€μκ³Ό κ°μ΄ ν μ μμ΅λλ€.
κ°λ¨νμ£ ? μλλ μ 체 μ½λμ λλ€. μ²μλΆν° λκΉμ§ μ μ½κ³ μ΄ν΄νκ³ μ νλ κ²½μ° μ°Έκ³ νμΈμ.
β οΈ λ¬Έμ
νμμ λ°λΌμ κΈ°λ‘ν targetμ μ€νν μλ μμ§λ§, μ±μΌλ‘ νμ₯ν μ μλ λ κ°λ ₯ν μ루μ μ κ°λκ² μ’μ κ²μ λλ€. μλ§λ μ¬μ€νμ μν λ, μλ¦Όμ λ°λ νκ² λͺ©λ‘μ μ μ§ κ΄λ¦¬νλ ν΄λμ€μΌ κ²μ λλ€.
β μ루μ : μ’ μ ν΄λμ€
μ΄ λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ μμν μ μλ ν κ°μ§ λ°©λ²μ μ체 ν΄λμ€μ μ΄ λμμ μΊ‘μν ν¨μΌλ‘μ¨, κ΄μ°°μ ν¨ν΄(observer pattern)μ μ’ μ ν΄λμ€λ‘ ꡬννλ κ²μ λλ€.
λ°λΌμ μ’ μμ± (Vueκ° μΌμ μ²λ¦¬νλ λ°©λ²μ λ κ°κΉμ΅λλ€.)μ κ΄λ¦¬νκΈ° μν JavaScript ν΄λμ€λ₯Ό λ§λ λ€λ©΄ λ€μκ³Ό κ°μ κ²μ λλ€.
storage λμ μ μ΅λͺ
ν¨μλ₯Ό subscribersμ μ μ₯νκ³ μμ΅λλ€. record ν¨μ λμ μ dependμ νΈμΆνκ³ replay λμ notifyλ₯Ό μ¬μ©ν©λλ€. μ΄λ₯Ό μ€ννλ €λ©΄ λ€μ μ½λλ₯Ό μμ±νμΈμ.
μ¬μ ν μλνλ©° μ½λκ° λ μ¬μ¬μ© κ°λ₯ν΄ μ‘μ΅λλ€. μ‘°κΈ μ΄μν 건 target μ€μ κ³Ό μ€νλΏμ
λλ€.
β οΈ λ¬Έμ
μμΌλ‘λ κ° λ³μμ λν΄ Dep ν΄λμ€λ₯Ό κ°κ² λ κ²μ΄λ©°, μ
λ°μ΄νΈκ° νμν μ΅λͺ
ν¨μλ₯Ό λ§λλ λμμ μΊ‘μννλ κ²μ΄ μ’μ΅λλ€. μλ§λ κ°μμ (watcher) κΈ°λ₯μ΄ μ΄λ¬ν νλμ μ²λ¦¬ν κ²λλ€.
(μμμ μμ±ν μ½λμ κ°μ΅λλ€.)
μ μ½λλ₯Ό νΈμΆνλ λμ μ, λ€μμ νΈμΆνλλ‘ ν©μλ€.
β μ루μ : κ°μμ (Watcher) ν¨μ
Watcher ν¨μμμ μ°λ¦¬λ λͺ κ°μ§ κ°λ¨ν μΌμ ν μ μμ΅λλ€ :
보μλ€μνΌ, watcher ν¨μλ myFunc μΈμλ‘ μ·¨ν΄μ μ μ target νλ‘νΌν°λ‘ μ€μ νκ³ dep.depend()λ₯Ό νΈμΆνμ¬ νκ²μ ꡬλ
μ(subscriber)λ‘ μΆκ°νκ³ target ν¨μλ₯Ό νΈμΆνκ³ , targetμ 리μ
ν©λλ€.
μλλ μ€ν κ²°κ³Όμ λλ€.
You might be wondering why we implemented target as a global variable, rather than passing it into our functions where needed. There is a good reason for this, which will become obvious by the end of our article.
targetμ μ μ λ³μλ‘ κ΅¬ν ν μ΄μ κ° κΆκΈνμ€ν
λ°μ, μ΄λ μ°λ¦¬ μν°ν΄μ λ§μ§λ§ λΆλΆ κ·Έ μ΄μ κ° λͺ
νν΄μ§ κ²λλ€.
β οΈ λ¬Έμ
μ°λ¦¬λ νλμ Dep classλ₯Ό κ°μ§κ³ μμ§λ§, μ°λ¦¬κ° μ λ§λ‘ μνλ κ²μ κ°κ°μ λ³μκ° μμ μ Depλ₯Ό κ°λλ‘ νλ κ²μ
λλ€. μ§λλ₯Ό λ λκ°κΈ° μ μ νλ‘νΌν°λ₯Ό μ΄ν΄λ΄
μλ€.
μ°λ¦¬μ κ° νλ‘νΌν° (price μ quantity)κ° κ·Έλ€ μμ μ λ΄λΆ Dep ν΄λμ€λ₯Ό κ°μ§κ³ μλ€κ³ κ°μ ν΄ λ΄
μλ€.
μλ μ½λλ₯Ό μ€νμν΅μλ€.
data.price κ°μ μ κ·ΌνμΌλ―λ‘ price νλ‘νΌν°μ Dep ν΄λμ€κ° targetμ μ μ₯λμ΄ μλ μ΅λͺ
ν¨μλ₯Ό subscriber λ°°μ΄μ pushνκ³ μ ν©λλ€(dep.depend() λ₯Ό νΈμΆν¨μΌλ‘μ). data.quantityμ μ κ·ΌνμΌλ―λ‘ amount νλ‘νΌν°μ Dep ν΄λμ€κ° μ΄ targetμ μ μ₯λμ΄ μλ μ΅λͺ
ν¨μλ₯Ό subscriber λ°°μ΄μ push νκ³ μ ν©λλ€.
data.price λ§ μ‘μΈμ€νλ λ λ€λ₯Έ μ΅λͺ
μ ν¨μκ° μμΌλ©΄ price μμ± Dep ν΄λμ€μ κ·Έλ₯ pushνκ³ μ ν©λλ€.
μΈμ dep.notify()κ° priceμ ꡬλ
μ(subscribers)μκ² νΈμΆλκ² ν κΉμ? priceκ° μ ν΄μ§λ©΄ ν¨μκ° νΈμΆλκ² νκ³ μ ν©λλ€. μ΄ μν°ν΄μ λ λΆλΆμμ μ λ μ½μμ λ€μ΄κ°μ λ€μκ³Ό κ°μ΄ ν μ μκ² νκ³ μ ν©λλ€.
μ°λ¦¬λ λ°μ΄ν° νλ‘νΌν° (price λ quantityμ κ°μ)μ μ κ·Όν λ°©λ²μ΄ νμν©λλ€. κ·Έλμ μ κ·Ό ν λ targetμ ꡬλ
μ(subscriber) λ°°μ΄μ μ μ₯ν μ μμ΅λλ€. κ·Έλ¦¬κ³ λ³κ²½λλ©΄ subscriber λ°°μ΄μ μ μ₯ν ν¨μλ₯Ό μ€νν©λλ€.
β μ루μ : Object.defineProperty()
νμ€ ES5 JavaScript μΈ Object.defineProperty() ν¨μμ λν΄ μμμΌν©λλ€. μ΄λ νλ‘νΌν°μ λν getterμ setter ν¨μλ₯Ό μ μ ν μ μκ² ν΄μ€λλ€. Dep ν΄λμ€μμ μ¬μ©νλ λ°©λ²μ 보μ¬λ리기 μ μ λ¨Όμ μμ£Ό κΈ°λ³Έμ μΈ μ¬μ©λ²μ λ³΄μ¬ λλ¦¬κ² μ΅λλ€.
보μλ€μνΌ λ μ€μ λ‘κ·Έκ° μ°νλλ€. κ·Έλ¬λ μ°λ¦¬κ° μ€λ²λ‘λνκΈ° λλ¬Έμ μ€μ λ‘λ κ°μ get νκ±°λ set νμ§ μμ΅λλ€. λ€μ μ½λλ₯Ό μΆκ°ν©μλ€. get()μ κ°μ λ°ν ν κ²μΌλ‘ κΈ°λνκ³ , set()μ μ¬μ ν κ°μ κ°±μ ν νμκ° μμΌλ―λ‘, νμ¬μprice κ°μ μ μ₯νκΈ° μν΄ internalValue λ³μλ₯Ό μΆκ°ν©μλ€.
μ΄μ getκ³Ό setμ΄ μ λλ‘ μλνλ―λ‘ μ½μμ μ΄λ€ λ΄μ©μ΄ μΆλ ₯ λ κΉμ?
λ°λΌμ μ°λ¦¬λ κ°μ μ»κ³ μ€μ ν λ ν΅λ³΄ λ°μ μ μλ λ°©λ²μ κ°μ§κ³ μμ΅λλ€. κ·Έλ¦¬κ³ μ¬κ·λ₯Ό ν΅ν΄ λ°μ΄ν° λ°°μ΄μ λͺ¨λ νλͺ©μ λν΄ μ΄ μμ μ μνν μ μμ΅λλ€.
μ°Έκ³ λ‘, Object.keys(data)λ κ°μ²΄μ ν€ λ°°μ΄μ λ°νν©λλ€.
μ΄μ λ λͺ¨λ getterμ setterκ° μμΌλ©° μ½μμμ λ³Ό μ μμ΅λλ€.
π κ°λ (idea) λͺ¨μΌκΈ°
μμ κ°μ μ½λκ° μ€νλλ©΄ priceμ κ°μ μ»μ΅λλ€.priceκ° μ΄ μ΅λͺ
μ ν¨μ (target)λ₯Ό κΈ°μ΅νκ³ μ ν©λλ€. μ΄λ°μμΌλ‘ priceκ° λ³κ²½λκ±°λ setμ΄ μλ‘μ΄ κ°μΌλ‘ μ€μ λλ©΄ μ΄ ν¨μλ μ΄ ν¨μκ° μ’
μλμ΄ μλ€λ κ²μ μκ³ μκΈ° λλ¬Έμ μ΄ ν¨μκ° λ€μ μ€νλλλ‘ νΈλ¦¬κ±°ν©λλ€. κ·Έλμ μ΄λ κ² μκ°ν μ μμ΅λλ€.
Get => μ΅λͺ ν¨μλ₯Ό κΈ°μ΅νλ€. κ°μ΄ λ³κ²½λλ©΄ λ€μ μ€ννλ€.
Set => μ μ₯λ μ΅λͺ ν¨μλ₯Ό μ€ννλ©΄ κ°μ΄ λ³κ²½λλ€.
Dep ν΄λμ€μ κ²½μ°
Priceμ μ κ·Όμ (get) => dep.depend()λ₯Ό νΈμΆνμ¬ νμ¬ targetμ μ μ₯νλ€.
Price μ€μ => dep.notify()λ₯Ό priceμ νΈμΆνκ³ λͺ¨λ targetμ λ€μ μ€ννλ€.
μ΄ λ κ°μ§ κ°λ (idea)λ₯Ό κ²°ν©νμ¬ μ΅μ’ μ½λλ₯Ό μ΄ν΄ λ³΄κ² μ΅λλ€.
μ±μ κ°μ§κ³ λ λ μ½μμμ μ΄λ€ μΌμ΄ μΌμ΄λλμ§ λ³΄μΈμ.
μ°λ¦¬κ° μνλ λ°κ° νμ€ν μ΄λ€μ§λ€μ! price μ quantityλ λͺ¨λ λ°μνμ
λλ€! λͺ¨λ μ½λλ price λλ quantity κ°μ΄ μ
λ°μ΄νΈ λ λλ§λ€ μ¬μ€νλ©λλ€.
Vue λ¬Έμμ κ·Έλ¦Όμ΄ μ΄μ μ΄ν΄κ° λμ€κ²λλ€.
getterμ setterκ° λ€μ΄μλ μμ 보λΌμ λ°μ΄ν° λκ·ΈλΌλ―Έκ° 보μ΄μλμ? μΉμν΄ λ³΄μ΄μ
μΌ ν©λλ€! λͺ¨λ μ»΄ν¬λνΈ μΈμ€ν΄μ€μλ getter (λΉ¨κ°μ μ )μ μ’
μμ±μ μμ§νλ watcher μΈμ€ν΄μ€(νλμ)κ° μμ΅λλ€. λμ€μ setterκ° νΈμΆλλ©΄ μ»΄ν¬λνΈκ° λ€μ λ λλ§ λλλ‘ νλ κ°μμμκ² μλ¦Όμ 보λ
λλ€. μλλ μ μ€λͺ
μ΄ λ€μ΄κ° μ΄λ―Έμ§μ
λλ€.
μΌνΈ, μ΄μ μ’ λ λͺ νν΄μ‘μ£ ?
Vueκ° μ»€λ² μλμμ μ΄ μμ μ νλ λ°©λ²μ λΆλͺ λ 볡μ‘νμ§λ§, μ΄μ λ μ¬λ¬λΆμ κΈ°λ³Έμ μΈ κ²μ μκ³ μμ΅λλ€.
βͺ μ°λ¦¬λ 무μμ λ°°μ λκ°?
μ’
μμ±(dependencies)μ μμ§νκ³ (depend) λͺ¨λ μ’
μμ±μ λ€μ μ€ννλ (notify) Dep ν΄λμ€λ₯Ό μμ±νλ λ°©λ².
μ°λ¦¬κ° μ€νμ€μΈ μ½λλ₯Ό κ΄λ¦¬νκΈ°μν κ°μμ(watcher)λ₯Ό λ§λλ λ°©λ². μ’
μμ±μΌλ‘ μΆκ° (target) ν΄μΌ ν μλ μμ΅λλ€.
getter λ° setterλ₯Ό λ§λ€κΈ° μν΄ Object.defineProperty()λ₯Ό μ¬μ©νλ λ°©λ².
μ’ μμ±(dependencies)μ μμ§νκ³ (depend) λͺ¨λ μ’ μμ±μ λ€μ μ€ννλ (notify) Dep ν΄λμ€λ₯Ό μμ±νλ λ°©λ².
μ°λ¦¬κ° μ€νμ€μΈ μ½λλ₯Ό κ΄λ¦¬νκΈ°μν κ°μμ(watcher)λ₯Ό λ§λλ λ°©λ². μ’ μμ±μΌλ‘ μΆκ° (target) ν΄μΌ ν μλ μμ΅λλ€.
getter λ° setterλ₯Ό λ§λ€κΈ° μν΄ Object.defineProperty()λ₯Ό μ¬μ©νλ λ°©λ².
λ€μμ?
μ΄ μν°ν΄μ΄ μ μ΅νμ ¨λ€λ©΄, νμ΅ κ²½λ‘μ λ€μ λ¨κ³λ νλ‘μμ λ°μν μ λν΄ λ°°μ°λ κ²μ λλ€. VueMastery.comμμ μ΄ μ£Όμ μ λν λ΄ λ¬΄λ£ λΉλμ€ λ₯Ό κΌ νμΈνμμμ€. μ¬κΈ°μ λλ Vue.jsμ μ°½μμ Evan Youμ ν΄λΉ μ£Όμ μ λν΄ μ΄μΌκΈ°ν©λλ€.
Originally published atwww.vuemastery.com