본문 바로가기

Frontend/JavaScript

[JavaScript] 코어 자바스크립트 5장 - 클로저

반응형

아래 책을 읽고 정리한 내용입니다.

http://www.yes24.com/Product/Goods/78586788

 

코어 자바스크립트 - YES24

자바스크립트의 근간을 이루는 핵심 이론들을 정확하게 이해하는 것을 목표로 합니다최근 웹 개발 진영은 빠르게 발전하고 있으며, 그 중심에는 자바스크립트가 있다고 해도 결코 과언이 아니

www.yes24.com

 

💡A closure is the combination of a function and the lexical environment within which that function was declared.

 

클로저란?

클로저는 여러 함수형 프로그래밍 언어에서 등장하는 보편적인 특성이다. MDN에 따르면, 클로저란 함수와 그 함수가 선언될 당시의 lexical environment의 상호관계에 따른 현상이다. 여기서 선언될 당시의 lexical environment란 실행 컨텍스트의 구성 요소 중 하나인 outerEnvironmentReference에 해당하며, 상호관계란 내부 함수에서 외부 변수를 참조하는 경우를 말한다.

 

즉, 클로저란 "어떤 함수에서 선언한 변수를 참조하는 내부함수에서 발생하는 현상"으로 볼 수 있다.

 

대표적인 클로저 예시를 통해 자세히 살펴보자. 

  • outer는 inner함수 자체를 반환하는 함수이다. 
  • outer 함수의 실행 컨텍스트가 종료될 때, outer2 변수는 inner함수를 참조하게 된다. 
  • 따라서 outer2를 통해 outer의 실행 컨텍스트가 종료된 후에도 inner함수를 호출할 수 있다.
var outer = function() {
  var a = 1;
  var inner = function() {
    return ++a;
  };
  return inner;
};

var outer2 = outer(); //outer 종료, outer2는 inner 참조
console.log(outer2()); //2
console.log(outer2()); //3

 

inner 실행(outer2 호출) 시점에 outer는 이미 실행이 종료된 상태인데 어떻게 a에 접근할 수 있는 것일까?

  • 이는 가비지 컬렉터의 동작 방식 때문이다. 가비지 컬렉터는 어떤 값을 참조하는 변수가 하나라도 있다면 그 값은 수집 대상에 포함시키지 않는다. 
  • outer의 실행이 종료되더라도 내부 함수인 inner를 참조하는 변수 outer2가 있기 때문에 outer는 가비지 컬렉터의 수집 대상에서 제외되는 것이다.
  • outer2에 의해 inner 함수의 실행 컨텍스트가 활성화되면 outerEnvironmentReference가 outer함수의 LexicalEnviornment를 필요로 할 것이기 때문이다.

따라서 inner함수가 a에 접근할 수 있는 것이다.

 

그래서 클로저란?

  • 어떤 함수에서 선언한 변수를 참조하는 내부함수에서만 발생하는 현상
  • 외부 함수의 LexicalEnvironment가 가비지 컬렉팅되지 않는 현상
  • 어떤 함수 outer에서 선언한 변수 a를 참조하는 내부 함수 inner를 외부로 전달할 경우, outer의 실행 컨텍스트가 종료된 이후에도 변수 a가 사라지지 않는 현상. 그래서 접근할 수 있는 현상.

 

 

클로저와 메모리 관리

클로저는 GC의 수거 대상이 되지 않는 현상을 말하기 때문에, 메모리 누수에 대한 문제가 있다. 따라서 클로저의 필요성이 사라진 시점에는 더 이상 메모리를 소모하지 않도록 해주어야 한다. How? 참조 카운트를 0으로 만들면 된다.

 

참조 카운트를 0으로 만드는 방법은?

  • 식별자에 참조형이 아닌 기본형 데이터를 할당하면 된다.
  • 일반적으로 null이나 undefined를 할당한다.
var outer = (function() {
  var a = 1;
  var inner = function() {
    return ++a;
  };
  return inner;
})();

console.log(outer); //[Function: inner]
outer = null;
console.log(outer); //null

 

 

클로저 활용 사례

  1. 콜백 함수 내부에서 외부 데이터를 사용하고자 할 때
  2. 접근 권한 제어(정보 은닉)
    • 클로저를 이용하면 함수 차원에서 public 한 값과 privat 한 값을 구분하는 것이 가능하다.
    • 외부 스코프에서 함수 내부의 변수들 중 선택적으로 일부 변수에 대한 접근 권한을 부여할 수 있다.
    • 외부에 제공하고자 하는 정보를 모아서 return 하고, 내부에서만 사용할 정보들은 return 하지 않는 것으로 접근 권한 제어가 가능한 것이다.
  3. 부분 적용 함수
    • 부분 적용 함수란 n개의 인자를 받는 함수에 미리 m개의 인자만 넘기고, 나중에 (n-m) 개의 인자를 넘겨 함수 실행 결과를 얻을 수 있는 함수이다.
    • 미리 일부 인자를 넘겨두어 기억하게끔 하고 추후 필요한 시점에 기억했던 인자들까지 함께 실행하게 하는 것이 클로저의 정의에 부합하다.
    • ex) 디바운스: 짧은 시간 동안 동일한 이벤트가 많이 발생할 경우 이를 전부 처리하지 않고 처음 또는 마지막에 발생한 이벤트에 대해 한 번만 처리하는 것
  4. 커링 함수
    • 커링 함수는 여러 개의 인자를 받는 함수를 하나의 인자만 받는 함수로 나눠서 순차적으로 호출될 수 있게 체인 형태로 구성한 것을 말한다.
    • 당장 필요한 정보만 받아서 전달하고 또 필요한 정보가 들어오면 전달하는 식으로, 마지막 인자가 넘어갈 때까지 함수 실행을 미루는 "지연 실행"을 수행한다.

각 사례의 구체적 예시는 책을 참고하자.

 

 

반응형