CoreJavaScript Chapter 5. [Closure]

요번 챕터는 Closure 에 대해서 확인해보려 한다 !
해당 내용은 클로저의 의미와 어떨때에 작용을 하는지 정도만 확인하고 넘어가자

CoreJavaScript

1. Closure ?

클로저는 MDN에 아래와 같이 정의 되어 있다.

“A closure is the combination of a function and the lexical environment within which that function was declared.”
클로저는 함수와 그 함수가 선언됐을 때의 렉시컬 환경(Lexical environment)과의 조합이다.

선언될 당시의 lexical environment는 CoreJavaScript Chapter 2. [execution context]에서 소개한
실행 컨텍스트의 구성 요소 중 하나인 outerEnvironmentReference에 해당한다.

LE(LexicalEnvironment)의 ER(environmentRecord)과 OE(outerEnvironmentReference)에 의해 변수의 유효범위인 스코프가 결정이되고 스코프 체인이 가능해진다고 했었다.

어떤 컨텍스트 A에서 선언한 내부함수 B의 실행 컨텍스트가 활성화된 시점에는 B의 OE가 참조하는 대상인 A의 LE에도 접근이 가능했다! 또한 A에서는 B에서 선언한 변수에 접근할 수 없지만 B에서는 A에서 선언한 변수에 접근이 가능했다

하지만 우리는 내부함수 B가 A의 LE를 언제나 사용하는 것은 아니라는걸 알아야 한다.

내부함수에서 외부 변수를 참조하는 경우에 한해서만 선언될 당시의 LE와의 상호관계가 의미가 생기게 된다.


현재까지 알아본 바로 클로저를 정리하자면 ? ? ?

어떤 함수에서 선언한 변수를 참조하는 내부함수에서만 발생하는 현상이라고 할 수 있다.

또한 위의 의미는 외부 함수의 LE가 가비지 컬렉팅이 되지 않는 현상이라고도 말할 수 있다.

함수안에 사용되었던 변수의 경우 함수가 사용되지 않는 이상 가비지 컬렉팅에 수거가 된다

마지막으로 정리하자면 .. 함수 A안에 선언한 변수a를 참조하는 내부함수 b를 외부로 전달할 경우 A의 실행 컨텍스트가 종료된 이후에도 변수 a가 사라지지 않는 현상을 의미한다 !!

2. Closure와 메모리의 관계 ??

클로저라는 개념은 위에서 충...분히 이해했을거라 생각한다.

클로저는 객체지향과 함수형 모두를 아우르는 매우 중요한 개념이지만 클로저라는 개념은 메모리가 누수의 위험이 있으므로 사용을 조심해야 한다거나 심지어 지양해야 한다고 주장하는 사람들이 있다.

하지만 메모리 소모는 클로저의 본질적은 특성!! 일 뿐 오히려 이러한 특성을 정확하게 이해하고!! 잘 활용하도록 노력해야 한다

메모리 누수는 개발자의 의도와는 달리 어떤 값의 카운트가 0이 되지 않아 가비지 컬렉터의 수거 대상이 되지 않는 경우에는 맞는 표현이지만 만약에 개발자가 의도적으로 설계를 한 것이라면 ??

그게 과연 메모리 누수라고 말할 수 있을까 ? 아니라는거다 !

그렇다면 메모리 소모를 관리한다는 것은 어떻게 컨트롤 할 수 있을까?

방법은 간단하다!

필요성이 사라진 변수에 대해 참조 카운트를 0으로 만들면 언젠간 가비지 컬렉터가 수거를 하게 된다 그렇게 된다면 메모리가 회수가 되지 않을까??
(참조 카운트를 0으로 만들려면 보통 null이나 undefined를 할당하면 된다)

아래의 코드로 메모리 컨트롤을 확인하고 넘어가자

//return에 의한 클로저의 메모리 해체
var outer = (function () {
  var a = 1;
  var inner = function () {
    return ++a;
  };
  return inner;
})();
console.log(outer());
console.log(outer());
outer = null; // outer 식별자의 inner 함수 참조를 끊는다
//setInterval에 의한 클로저의 메모리 해제

(function () {
  var a = 0;
  var intervalId = null;
  var inner = function () {
    if(++a >= 10) {
      clearInterval(intervalId);
      inner = null;  // inner 식별자의 함수 참조를 끊음 !!
    }
    console.log(a);
  };
  intervalId = setInterval(inner, 1000);
})();

3. Closure의 활용

클로저의 의미와 작동 원리는 알았으니
어떤 상황에서 클로저가 사용되는지 알아보도록 한다!
다양한 예제가 있지만 이 중에서는 나는 접근 권한 제어(정보 은닉) 이라는 개념에 대해 설명하려 한다

정보 은닉은 어떤 모듈의 내부 로직안에서의 외부로 노출을 최소화 하기 위한 개념중에 하나이다

흔히 권한으로는 public private protected 세 종류가 있다

자바스크립트의 경우에는 기본적으로 변수 자체에 이러한 접근 권한을 직접 부여하도록 설계되어 있지 않다.

하지만 클로저를 이용한다면? public과 private으로 나눌 수가 있다!


결국 클로저는 어떤 함수에서 선언한 변수를 참조하는 내부함수를 외부로 전달할 경우, 함수의 실행 컨텍스트가 종료된 후에도 해당 변수가 사라지지 않는 현상을 의미한다 !

내부함수를 외부로 전달하는 방법은 함수를 return 하는 경우도 있지만 콜백으로도 전달할 수도 있으며 이러한 클로저는 본질 자체가 가비지 컬렉팅을 당하지 않고 메모리를 계속 차지하므로 더는 사용하지 않는 클로저에 대해서는 메모리를 차지하지 않도록 컨트롤 해줘야 한다!!

내가 이해한 클로저에 대한 정리 요약 끝 !


출처
모든 내용은 코어자바스크립트 공부를 하며 책 내용을 발췌해 이해한 내용들만 추려 적은 내용입니다 해당 코드들은 책 내용의 코드의 값들을 변경하거나 이해를 위해 그대로 가지고 왔습니다.

좋은 웹페이지 즐겨찾기