Javascript

[javascript] 클로저 / 스코프

<Eunhak> 2024. 9. 2. 14:50

스코프

참조 대상 식별자를 찾아내기 위한 규칙

변수 / 함수의 유효범위를 뜻함

전역 스코프 (Global scope) : 스크립트 전체에서 참조되는 것을 의미하며, 어느 곳에서든 참조 된다.

지역 스코프 (Local scope) : 정의된 함수 내에서만 참조되는 것을 의미하며, 밖에서는 참조 되지 않는다.

렉시컬 스코프

함수를 어디 선언하는지에 따라 상위 스코프가 결정되는 자바스크립트를 포함한 대부분의 프로그래밍 언어는 렉시컬 스코프를 따름

var x = 1;

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

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

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

위와 같은 상황에서 bar 함수에서 참조하는 x 변수는 bar 함수의 상위 스코프가 무엇인지에 따라 결정된다. 따라서, 상위 스코프가 무엇인지 알려면 bar 함수가 어디에 선언되었는지 봐야되는데, 위 코드에서는 bar 함수가 전역에 선언되었으므로 상위 스코프는 전역 스코프가 된다. 그래서 bar 함수 내의 x 변수는 전역에 선언된 x 변수를 참조하게 된다.

클로저

반환된 내부함수가 자신의 렉시컬스코프를 기억하여 자신의 스코프 밖에서 호출되어도 그 환경에 접근할 수 있는 것

const outerFunc = () => {
		let x = 10; // '자유 변수' 라고 한다.

		// 클로저
		const innerFunc = (y) => {
				x = x + y;
				console.log(x);
		}

		return innerFunc;
}

const addFunc = outerFunc();
addFunc(5); // 15
addFunc(10); // 25

위 코드에서 innerFunc의 x는 렉시컬 스코프에 의해 outerFunc의 지역변수 x를 참조하고 있다.

그리고 outerFunc는 const addFunc = outerFunc(); 구문에서 호출된 후 콜스택에서 제거된다.

따라서, 이후에 addFunc를 호출 할 때 innerFunc의 x를 참조할 수 없어 보이는데, 외부함수 실행 컨텍스트 내의 *활성 객체가 내부함수에 의해 참조되는 한 유효하기 때문에 그렇지 않다.

즉, 내부함수가 유효한 상태에서 외부함수가 종료되어도, 외부함수의 x 변수를 참조할 수 있다. 여기서 내부함수를 클로저라고 한다.

클로저가 필요한 이유

1. 전역변수를 줄일 수 있다.

전역변수는 예상치 못한 Side Effect를 일으킬 수 있기에 최대한 줄이는 것이 좋다.문에 최대한 전역변수를 줄여서 코딩해야한다.

하지만 프로그램 구현 시 함수 하나에 사용하는 전역변수가 필요한 순간이 있다. 이럴 때 클로저가 유용하게 사용된다.

2. 비슷한 형태의 코드를 재사용률을 높일 수 있다.

인자에 open,close,content를 한번에 다 받는다면,This is my content! 와 같은 값을 출력을 하고 싶을 때 가독성이 떨어질 수 있다.

하지만 클로져로 구현하면 코드의 가독성도 좋은 재사용하기 편한 코드를 구현할 수 있음.