자바스크립트 클로저와 가비지 컬렉션
자바스크립트 핵심 개념· 8 / 9
Closure
클로저는 함수와 그 함수가 선언될 당시의 LexicalEnvironment(outerEnvironmentReference)의 상호관계에 따른 현상으로 함수형 프로그래밍 언어에서 등장하는 보편적인 특성이다.
- 어떤 함수에서 선언한 변수를 참조하는 내부함수에서만 발생한다.
- 클로저는 외부함수의
LexicalEnvironment가 가비지 컬렉팅되지 않을 때 발생한다.
* 가비지 컬렉팅(GC)
더 이상 사용되지 않는 데이터(변수 등)의 메모리 공간을 회수하는 작업이다.
대표적으로 실행 컨텍스트가 종료될 때 해당 컨텍스트의 LexicalEnvironment에 속한
변수와 데이터가 더 이상 참조되지 않으면 가비지 컬렉션의 대상이 된다.- 가비지 컬렉터는 어떤 값을 참조하는 변수가 하나라도 있다면 그 값은 수집 대상에 포함시키지 않는다.
예시)
var outer = function () {
var a = 1;
var inner = function () {
return ++a;
};
return inner;
};
var outer2 = outer();
console.log(outer2()); // 2
console.log(outer2()); // 3
outer 함수는 실행 종료 시점에 inner 함수를 반환하기에 외부함수인 outer가 실행이 종료되더라도 내부함수인 inner 함수가 언젠가 다시 호출될 가능성이 열린 것이다.
이 경우 outer 함수의 LexicalEnvironment는 가비지 컬렉터의 수집 대상에서 제외 된다.(크롬과 Node.js의 경우 필요한 변수만 제외된다.)
⇒ 클로저란 어떤 함수 A에서 선언한 변수 a를 참조하는 내부함수 B를 외부로 전달할 경우 A의 실행 컨텍스트가 종료된 이후에도 변수 a가 사라지지 않는 현상이다.
클로저로 인한 메모리 누수
개발자의 의도와 달리 어떤 값의 참조 카운트가 0이 되지 않아 가비지 컬렉터의 수거 대상이 되지 않는 경우 불필요하게 메모리가 소모된다는 표현이다.
해결방안)
⇒ 참조 카운트 0으로 만들기: 식별자에 참조형이 아닌 기본형 데이터(null 또는 undefined)를 할당한다.
(function () {
var a = 0;
var intervalId = null;
var inner = function () {
if (++a >= 10) {
clearInterval(intervalId);
inner = null; // 참조 카운트 → 0
}
console.log(a);
};
intervalId = setInterval(inner, 1000);
})();클로저 활용 사례
클로저가 실무에서 활용되는 대표적인 사례는 다음과 같다.
- 콜백 함수 내부에서 외부 데이터를 사용하고자 할 때
- 접근 권한 제어(정보 은닉)
- 부분 적용 함수
- 커링 함수