클로저란 무엇이냐...
A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives a function access to its outer scope. In JavaScript, closures are created every time a function is created, at function creation time.
Closures - JavaScript | MDN
A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives a function access to its outer scope. In JavaScript, closures are created every time
developer.mozilla.org
Closure(클로저)는 함수와 그 함수가 선언된 렉시컬 환경(Lexical Environment)을 묶어놓은 조합입니다. 간단히 말하면, 클로저는 함수가 자신의 외부 스코프(상위 스코프)에 접근할 수 있도록 해주는 기능이라고 합니다...

이렇게 하면 이해가 안되니 먼저 Lexical Environment가 뭔지부터 알아봅시다.
const x = 1;
function outerFunc() {
const x = 10;
function innerFunc() {
console.log(x); // 10
}
innerFunc();
}
outerFunc();

innerFunc 스코프 내에서 x 값은 존재하지 않으니 상위 스코프인 outerFunc로 이동해 x값을 참조합니다. => scope chain
innerFunc의 outer는 outerFunc의 Lexical Environment이므로 x는 outerFunc()에서의 x 값이 10을 참조합니다.
그렇다면 아래의 예에서는 어떨까요?
const x = 1;
function outerFunc() {
const x = 10;
innerFunc(); // 1
}
function innerFunc() {
console.log(x); // 1
}
outerFunc();
innerFunc가 outerFunc 내에서 실행되는데 x = 10이 안되냐....
바로 정의된 위치가 중요하기 때문입니다.(어디서 호출됐는지는 중요하지 않음)
innerFunc와 outerFunc는 서로 다른 스코프를 가지고 있어 변수를 공유할 수 없습니다.
따라서 innerFunc의 x는 상위 스코프인 전역 Lexical Environment의 x를 참조합니다.
그럼 이제 클로저와 렉시컬 환경에 대해서 알아봅시다.
const x = 1;
// 1
function outer() {
const x = 10;
const inner = function () {
console.log(x);
};
return inner;
}
const innerFunc = outer();
innerFunc();
먼저 실행 순서를 콜스택으로 보면

outer 함수가 실행된 후 빠져 나가고 그 후에 innerFunc가 실행되게 됩니다.
그럼 innerFunc의 x는 상위 스코프인 outer 함수의 x를 참조할까요? 아니면 전역 스코프의 x를 참조할까요?
outer가 실행된 후 스택에서 제거되어도 여전히 innerFunc의 outer는 outer 함수의 Lexical Environment입니다.
그 말인 즉슨, outer의 x를 참조하고 있다는 것입니다.
그러면 어떻게 outer 함수가 스택에서 제거되지만 Lexical Environment는 유지될 수 있을까요?
outer 함수가 실행되면 Activation Object가 생성되어 함수 내의 지역 변수인 x = 10을 저장합니다.
일반적으로 함수 실행이 끝나게 되면 이 객체는 가비지 컬렉션에 의해 제거되게 됩니다.
하지만!!! innerFunc의 x가 outer 함수의 x를 참조하고 있기 때문에 가비지 컬렉터가 x = 10이라는 Lexical Environment를 수거하지 않고 유지하게 됩니다.
이처럼, 클로저에서 Lexical Environment는 함수가 실행된 후에도 그 스코프 내의 변수를 참조하는 다른 함수가 있을 경우 계속해서 메모리에서 유지되며, 가비지 컬렉터에 의해 제거되지 않습니다
클로저를 이용한 count
function createCounter() {
let count = 0;
return function() {
count++;
console.log(count);
};
}
const counter = createCounter();
counter(); // 1
counter(); // 2
counter(); // 3
위와 같이 클로저를 사용하면 count라는 변수 값을 바꿔줄 수 있는 것은 createCounter 내부의 함수입니다.
이처럼 메서드를 통해서만 데이터를 변경하거나 조회할 수 있어 데이터 은닉이 가능합니다.
이거 어디서 본 거 같지 않나요....?
바로 React의 useState도 비슷한 역할을 합니다!
const [count, setCount] = useState(0);
setCount(count + 1);
이렇게 setCount를 통해서만 count 값을 변경할 수 있는....
