[F-Lab 모각코 챌린지 - 49일차] - 클로저(1)

Big One·2023년 6월 28일
0

F-Lab

목록 보기
22/69

클로저란?

클로저는 자바스크립트 고유개념이 아닌 여러 함수형 프로그래밍 언어에서 등장하는 보편적인 특성이다.

클로저는 어떤 함수 A 에서 선언한 변수 a 를 참조하는 내부 함수 B 를 외부로 전달할 경우 A의 실행 컨텍스트가 종료된 이후에도 a변수가 사라지지 않는 현상을 말한다.

A의 실행 컨텍스트가 종료되었음에도 불구하고 A의 렉시컬 환경(Lexical Environment) 를 참조하는 것이다.

클로저 예시

const outer = function () {
	let a = 1;
	const inner = function() {
		return ++a;
	}
	return inner;
}
const outer2 = outer();  // inner 함수의 실행 값을 리턴한 것이 아닌 inner 자체를 리턴했다.
outer2();  // 2
outer2();  // 3

inner 함수의 실행 시점에는 outer 함수의 실행 컨텍스트는 종료된 상태인데 어떻게 outer 함수의 렉시컬 환경에 접근할 수 있는 것일까? 바로 가비지 컬렉터의 동작 방식 때문이다. 외부 함수인 outer가 종료 되었더라도 inner 는 outer2에 의해 언젠가 실행될 가능성이 열려있어 수집 대상에서 제외 된다.

즉, Lexical Environment 가 가비지 컬렉터의 수거 대상에서 제외되는 경우는 지역 변수를 참조하는 내부 함수가 외부로 전달된 경우가 유일하다. “외부 함수의 렉시컬 환경이 가비지 컬렉팅 되지 않는 현상”

클로저와 메모리 관리

메모리 누수

더 이상 참조되지 않음에도 불구하고 가비지 컬렉터의 수거대상에서 제외되는 것이다.

개발자의 의도와 달리 어떤 값의 참조 카운트가 0이 되지않아 GC의 수거 대상이 되지 않는 경우 메모리 누수라 할 수 있지만 개발자가 의도적으로 참조 카운트가 0 이 되지 않게 설계했다면 메모리 누수라 할 수 없다.

어떻게 관리할까?

기본적으로 자바스크립트는 직접적으로 메모리 관리를 할 수 없다. 하지만 메모리 누수가 일어나지 않게 하려면 참조 카운트를 0 으로 만들면 된다.

참조 카운트를 0으로 만드는 방법은 식별자에 null 또는 undefined값을 할당하면 된다.

setInterval, return 으로 메모리 해제하는 것을 코드로 확인해보겠다.

const outer = (function(){
	let a = 1;
	let inner = function() {
		return ++a;
	};
	return inner;
})();
console.log(outer());
console.log(outer());
outer = null;  // 해제
(function () {
		let a = 0;
		let intervalId = null;
		let inner = function() {
			if(++a >= 10){
				clearInterval(intervalId);
				inner = null;  // 해제
			}
		console.log(a);
		}
		intervalId = setInterval(inner, 1000);
	})();

클로저가 무조건 안좋은가?

개발자가 의도하지 않은 곳에서 클로저가 일어나 메모리 누수가 발생한 경우에는 좋지 않은 상황이다. 하지만 개발자가 의도적으로 클로저를 만들고 활요한다면 메모리 누수라고 할 수 없어서 무조건적으로 좋지 않다고 할 수 없다.

궁금한 점

메모리 누수는 클로저에서만 일어나는 것인가?

profile
이번생은 개발자

0개의 댓글