🦎 [λ”₯λ‹€μ΄λΈŒ μŠ€ν„°λ””] 23. μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ, ν΄λ‘œμ €

이지·2021λ…„ 12μ›” 16일
0

DeepDive

λͺ©λ‘ 보기
12/13

μ‹€ν–‰μ»¨ν…μŠ€νŠΈ?

μžλ°”μŠ€νŠΈλ¦½νŠΈμ˜ λ™μž‘μ›λ¦¬λ₯Ό λ‹΄κ³ μžˆλ‹€. μ†ŒμŠ€μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λŠ”λ° ν•„μš”ν•œ ν™˜κ²½μ„ μ œκ³΅ν•˜κ³ , μ‹€ν–‰κ²°κ³Όλ₯Ό μ‹€μ œλ‘œ κ΄€λ¦¬ν•œλ‹€. 즉, μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλŠ” μ‹λ³„μžλ₯Ό λ“±λ‘ν•˜κ³  κ΄€λ¦¬ν•˜λŠ” μŠ€μ½”ν”„μ™€ μ½”λ“œ μ‹€ν–‰ μˆœμ„œ 관리λ₯Ό κ΅¬ν˜„ν•œ λ‚΄λΆ€ λ©”μ»€λ‹ˆμ¦˜μœΌλ‘œ λͺ¨λ“  μ½”λ“œλŠ” μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλ₯Ό 톡해 μ‹€ν–‰λ˜κ³  κ΄€λ¦¬λœλ‹€. μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ μŠ€νƒμ€ μ½”λ“œ μ‹€ν–‰ μˆœμ„œλ₯Ό κ΄€λ¦¬ν•œλ‹€.그렇기에 ν΄λ‘œμ €, ν˜Έμ΄μŠ€νŒ…, μŠ€μ½”ν”„λ“±μ˜ κ°œλ…μ„ μ΄ν•΄ν•˜λŠ” 데 핡심적이닀.

(μ†ŒμŠ€μ½”λ“œν‰κ°€κ³Όμ •)
1.처음 μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λ©΄ μ „μ—­ μ»¨ν…μŠ€ν¬κ°€ μƒμ„±λœλ‹€.
2.ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  λ•Œλ§ˆλ‹€ ν•¨μˆ˜ μ»¨ν…μŠ€νŠΈκ°€ ν•˜λ‚˜μ”© 더 생긴닀.
(μ†ŒμŠ€μ½”λ“œ μ‹€ν–‰κ³Όμ • = λŸ°νƒ€μž„)
3.λ³€μˆ˜λŠ” λ³€μˆ˜ κ°μ²΄μ•ˆμ—μ„œ 값을 μ°Ύκ³ , μ—†λ‹€λ©΄ μŠ€μ½”ν”„ 체인을 따라 μ˜¬λΌκ°€λ©° μ°ΎλŠ”λ‹€.
4.ν•¨μˆ˜ 싀행이 λλ‚˜λ©΄ ν•΄λ‹Ή μ»¨ν…μŠ€νŠΈλŠ” 사라진닀 (단, ν΄λ‘œμ € μ œμ™Έ)

β€œA closure is the combination of a function and the lexical environment within which that function was declared.”
ν΄λ‘œμ €λŠ” ν•¨μˆ˜μ™€ κ·Έ ν•¨μˆ˜κ°€ 선언됐을 λ•Œμ˜ λ ‰μ‹œμ»¬ ν™˜κ²½(Lexical environment)과의 쑰합이닀.
(좜처: MDN)

μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진은 ν•¨μˆ˜λ₯Ό μ–΄λ””μ„œ ν˜ΈμΆœν–ˆλŠ”μ§€κ°€ μ•„λ‹ˆλΌ ν•¨μˆ˜λ₯Ό 어디에 μ •μ˜ν–ˆλŠ”μ§€μ— 따라 μƒμœ„ μŠ€μ½”ν”„λ₯Ό κ²°μ •ν•œλ‹€. 이λ₯Ό λ ‰μ‹œμ»¬ μŠ€μ½”ν”„(정적 μŠ€μ½”ν”„)라 ν•œλ‹€. μœ„ μ •μ˜μ—μ„œ λ§ν•˜λŠ” β€œν•¨μˆ˜β€λž€ λ°˜ν™˜λœ λ‚΄λΆ€ν•¨μˆ˜λ₯Ό μ˜λ―Έν•˜κ³  β€œκ·Έ ν•¨μˆ˜κ°€ 선언될 λ•Œμ˜ λ ‰μ‹œμ»¬ ν™˜κ²½(Lexical environment)β€λž€ λ‚΄λΆ€ ν•¨μˆ˜κ°€ 선언됐을 λ•Œμ˜ μŠ€μ½”ν”„λ₯Ό μ˜λ―Έν•œλ‹€. 즉, ν΄λ‘œμ €λŠ” λ°˜ν™˜λœ λ‚΄λΆ€ν•¨μˆ˜κ°€ μžμ‹ μ΄ 선언됐을 λ•Œμ˜ ν™˜κ²½(Lexical environment)인 μŠ€μ½”ν”„λ₯Ό κΈ°μ–΅ν•˜μ—¬ μžμ‹ μ΄ 선언됐을 λ•Œμ˜ ν™˜κ²½(μŠ€μ½”ν”„) λ°–μ—μ„œ ν˜ΈμΆœλ˜μ–΄λ„ κ·Έ ν™˜κ²½(μŠ€μ½”ν”„)에 μ ‘κ·Όν•  수 μžˆλŠ” ν•¨μˆ˜λ₯Ό λ§ν•œλ‹€. 이λ₯Ό 쑰금 더 κ°„λ‹¨νžˆ λ§ν•˜λ©΄ ν΄λ‘œμ €λŠ” μžμ‹ μ΄ 생성될 λ•Œμ˜ ν™˜κ²½(Lexical environment)을 κΈ°μ–΅ν•˜λŠ” ν•¨μˆ˜λ‹€λΌκ³  말할 수 μžˆκ² λ‹€.


//example

const x = 1;

function foo() {
  const x = 10;
  bar();
}

function bar() {
  console.log(x);
}

foo(); //1 
bar(); //1 

// 두 ν•¨μˆ˜ λͺ¨λ‘ μ „μ—­μ—μ„œ μ •μ˜ λ˜μ—ˆκΈ° λ•Œλ¬Έμ—, bar()λŠ” foo() λ‚΄λΆ€ λ³€μˆ˜μ— μ ‘κ·Ό λΆˆκ°€λŠ₯.

ν˜Έμ΄μŠ€νŒ…?

ν˜Έμ΄μŠ€νŒ…μ΄λž€ λ³€μˆ˜λ₯Ό μ„ μ–Έν•˜κ³  μ΄ˆκΈ°ν™”ν–ˆμ„ λ•Œ μ„ μ–Έ 뢀뢄이 μ΅œμƒλ‹¨μœΌλ‘œ λŒμ–΄μ˜¬λ €μ§€λŠ” ν˜„μƒμ„ μ˜λ―Έν•œλ‹€. λ³€μˆ˜λŠ” μ„ μ–ΈλΆ€λΆ„λ§Œ λŒμ–΄μ˜¬λ €μ§„λ‹€. ν•¨μˆ˜ ν‘œν˜„μ‹μ΄ μ•„λ‹ˆλΌ ν•¨μˆ˜ 선언식일 λ•ŒλŠ” 식 μžμ²΄κ°€ ν†΅μ§Έλ‘œ λŒμ–΄μ˜¬λ €μ§„λ‹€. 즉 μ„ μ–Έκ³Ό λ™μ‹œμ— λŒ€μž…λœλ‹€. κ·Έλž˜μ„œ ν˜ΈμΆœμ„ μ„ μ–Έ 이전에 해도 λ™μž‘ν•œλ‹€. 단, ν‘œν˜„μ‹μœΌλ‘œ μ„ μ–Έν•œ 경우 μ—λŸ¬ λ°œμƒ.

ν΄λ‘œμ €?

ν΄λ‘œμ €λŠ” js만의 κ°œλ…μ€ μ•„λ‹ˆλ‹€. ν•¨μˆ˜λ₯Ό μΌκΈ‰κ°μ²΄λ‘œ μ·¨κΈ‰ν•˜λŠ” ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄μ—μ„œ μ‚¬μš©λ˜λŠ” μ€‘μš” νŠΉμ„±μ΄λ‹€. μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ λͺ¨λ“  ν•¨μˆ˜λŠ” μƒμœ„ μŠ€μ½”ν”„λ₯Ό κΈ°μ–΅ν•˜λ©°, μ–΄λ””μ„œ ν˜ΈμΆœν•˜λ“ μ§€ 상관없이 μœ μ§€λœλ‹€. κ·ΈλŸ¬λ‚˜, μƒμœ„ μŠ€μ½”ν”„μ˜ μ–΄λ–€ μ‹λ³„μžλ„ μ°Έμ‘°ν•˜μ§€ μ•ŠλŠ” ν•¨μˆ˜λŠ”, λΈŒλΌμš°μ €μ˜ μ΅œμ ν™”λ₯Ό μœ„ν•΄ μƒμœ„ μŠ€μ½”ν”„λ₯Ό κΈ°μ–΅ν•˜μ§€ μ•ŠλŠ”λ‹€. ν΄λ‘œμ €λŠ” 1. 쀑첩 ν•¨μˆ˜κ°€ μƒμœ„ μŠ€μ½”ν”„μ˜ μ‹λ³„μžλ₯Ό μ°Έμ‘°ν•˜κ³  있고 2.쀑첩 ν•¨μˆ˜κ°€ μ™ΈλΆ€ ν•¨μˆ˜λ³΄λ‹€ 더 였래 μœ μ§€λ˜λŠ” κ²½μš°μ— ν•œμ •ν•˜λŠ” 것이 μΌλ°˜μ μ΄λ‹€.

//ν΄λ‘œμ €λΌκ³  ν•˜μ§€ μ•ŠλŠ”λ‹€.
function foo() {
  const x = 1;
  
  //μƒμœ„ μŠ€μ½”ν”„μ˜ μ‹λ³„μžλ₯Ό μ°Έμ‘°ν•˜μ§€ μ•ŠλŠ”λ‹€.
  function bar() {
    const z = 3;
    debugger;
    console.log(z);
  }
}
function foo() {
  const x = 1;
  
  //barλŠ” ν΄λ‘œμ €μ˜€μ§€λ§Œ κ³§λ°”λ‘œ μ†Œλ©Έν•˜λ©° μ™ΈλΆ€λ‘œ λ°˜ν™˜λ˜μ§€ μ•ŠλŠ”λ‹€.
  //ν΄λ‘œμ €λΌκ³  ν•˜μ§€ μ•ŠλŠ”λ‹€.
  function bar() {
    console.log(x);
  }
  bar();
}

foo();
function foo() {
  const x = 1;
  
  //ν΄λ‘œμ €
  //μ™ΈλΆ€ ν•¨μˆ˜λ³΄λ‹€ 더 였래 μœ μ§€λ˜λ©° μƒμœ„ μŠ€μ½”ν”„μ˜ μ‹λ³„μžλ₯Ό μ‚¬μš©ν•œλ‹€.
  function bar() {
    console.log(x);
  }
  return bar();
}

const bar = foo();
bar();

ν΄λ‘œμ €λ₯Ό μ‚¬μš©ν•˜λŠ” 이유

  1. ν΄λ‘œμ €λŠ” μƒνƒœκ°€ μ˜λ„μΉ˜ μ•Šκ²Œ λ³€κ²½λ˜μ§€ μ•Šλ„λ‘ μ•ˆμ „ν•˜κ²Œ μ€λ‹‰ν•˜κ³  νŠΉμ • ν•¨μˆ˜μ—κ²Œλ§Œ μƒνƒœ 변경을 ν—ˆμš©ν•˜μ—¬ μƒνƒœλ₯Ό μ•ˆμ „ν•˜κ²Œ λ³€κ²½ν•˜κ³  μœ μ§€ν•˜κΈ° μœ„ν•΄ μ‚¬μš©ν•œλ‹€. (λΆˆλ³€μ„± μœ μ§€) 일반적으둜 λ³€μˆ˜ 값은 λˆ„κ΅°κ°€μ— μ˜ν•΄ μ–Έμ œλ“ μ§€ 변경될 수 μžˆμ–΄ 였λ₯˜ λ°œμƒμ˜ 근본적 원인이 될 수 μžˆλ‹€. μ™ΈλΆ€ μƒνƒœ λ³€κ²½μ΄λ‚˜ κ°€λ³€ 데이터λ₯Ό ν”Όν•˜κ³  λΆˆλ³€μ„±μ„ μ§€ν–₯ν•˜λŠ” ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°μ—μ„œ λΆ€μˆ˜ 효과λ₯Ό μ΅œλŒ€ν•œ μ–΅μ œν•˜μ—¬ 였λ₯˜λ₯Ό ν”Όν•˜κ³  ν”„λ‘œκ·Έλž¨μ˜ μ•ˆμ „μ„±μ„ 높이기 μœ„ν•΄ ν΄λ‘œμ €λŠ” 적극적으둜 μ‚¬μš©λœλ‹€.

  1. ν΄λ‘œμ €κ°€ κ°€μž₯ μœ μš©ν•˜κ²Œ μ‚¬μš©λ˜λŠ” 상황은 ν˜„μž¬ μƒνƒœλ₯Ό κΈ°μ–΅ν•˜κ³  λ³€κ²½λœ μ΅œμ‹  μƒνƒœλ₯Ό μœ μ§€ν•˜λŠ” 것이닀.
    ν΄λ‘œμ €λŠ” ν˜„μž¬ μƒνƒœλ₯Ό κΈ°μ–΅ν•˜κ³  이 μƒνƒœκ°€ λ³€κ²½λ˜μ–΄λ„ μ΅œμ‹  μƒνƒœλ₯Ό μœ μ§€ν•΄μ•Ό ν•˜λŠ” 상황에 맀우 μœ μš©ν•˜λ‹€. λ§Œμ•½ μžλ°”μŠ€ν¬λ¦½νŠΈμ— ν΄λ‘œμ €λΌλŠ” κΈ°λŠ₯이 μ—†λ‹€λ©΄ μƒνƒœλ₯Ό μœ μ§€ν•˜κΈ° μœ„ν•΄ μ „μ—­ λ³€μˆ˜λ₯Ό μ‚¬μš©ν•  수 밖에 μ—†λ‹€. μ „μ—­ λ³€μˆ˜λŠ” μ–Έμ œλ“ μ§€ λˆ„κ΅¬λ‚˜ μ ‘κ·Όν•  수 있고 λ³€κ²½ν•  수 있기 λ•Œλ¬Έμ— λ§Žμ€ λΆ€μž‘μš©μ„ μœ λ°œν•΄ 였λ₯˜μ˜ 원인이 λ˜λ―€λ‘œ μ‚¬μš©μ„ μ–΅μ œν•΄μ•Ό ν•œλ‹€.

function makeCounter(){
	let num = 0; //은닉화 
    return function(){
    	return num++;
    }
}

let counter = makeCounter();
console.log(counter()); //0;
console.log(counter()); //1;
console.log(counter());//2; 




function Counter() {
  // 카운트λ₯Ό μœ μ§€ν•˜κΈ° μœ„ν•œ 자유 λ³€μˆ˜
  var counter = 0;

  // ν΄λ‘œμ €
  this.increase = function () {
    return ++counter;
  };

  // ν΄λ‘œμ €
  this.decrease = function () {
    return --counter;
  };
}

const counter = new Counter();

console.log(counter.increase()); // 1
console.log(counter.decrease()); // 0

좜처:
https://poiemaweb.com/js-closure

profile
μ΄μ§€ν”Όμ§€λ ˆλͺ¬μŠ€ν€΄μ§€πŸ‹

0개의 λŒ“κΈ€