본문 바로가기
개발지식

[Javascript] 클로저가 무엇인가?

by 구라미 2024. 2. 15.

 

 

1. 클로저란?

클로저는 외부 변수를 기억하고, 이 외부 변수에 접근할 수 있는 함수를 의미한다. 자신이 생성될 때의 환경을 기억하는 함수인 것이다. 클로저는 함수와 해당 함수가 선언될 때의 렉시컬 환경을 함께 기억한다. 이는 함수가 선언될 당시의 스코프 체인을 기억하고, 이 함수가 실행될 때에도 그 스코프 체인에 접근할 수 있도록 하는 메커니즘이다. 이는 해당 함수 내부에서 선언된 변수들을 포함하여, 함수가 선언된 위치에 대한 정보를 가지고 있다. 이렇게 클로저가 기억하는 렉시컬 환경은 해당 함수가 실행되는 동안에도 유지된다.

이러한 클로저의 특성을 이용하면, 함수가 선언될 때 생성된 렉시컬 환경에 있는 변수를 계속해서 사용할 수 있다. 예를 들어, 함수 내부에서 선언된 변수를 함수 외부에서 사용하려고 할 때, 해당 변수를 클로저를 통해 접근할 수 있다. 

정리하자면, 

1. 함수 내부에서 선언된 함수가 외부 함수의 변수에 접근할 수 있다.
2. 외부 함수의 변수가 외부 스코프에서 제거되더라도 내부 함수가 여전히 그 변수에 접근할 수 있다.
3. 클로저를 통해 함수의 상태를 유지하고 비공개 데이터를 가질 수 있다.

 

 

2. 클로저 예시


예시 1) 외부함수와 내부함수

function outerFunction() {
  let outerVariable = 'I am outer!';
  
  function innerFunction() {
    console.log(outerVariable);
  }
  
  return innerFunction;
}

let testClosure = outerFunction();
testClosure(); // 'I am outer!'


위의 예제에서 innerFunction은 outerFunction의 외부 변수인 outerVariable에 접근할 수 있다. outerVariable이 실행을 마치고 반환된 후에도 innerFunction은 여전히 outerVariable에 접근할 수 있다. 

 

예시 2) Counter 만들기 

function counter() {
  let count = 0;
  return function() {
    count++;
    console.log(count);
  }
}

const increment = counter();
increment(); // 1
increment(); // 2
increment(); // 3

위 예시에서 counter() 함수는 내부에서 count 변수를 선언하고, 이 변수를 증가시키는 익명 함수를 리턴한다. increment 상수는 counter() 함수를 호출한 결과를 저장하고 있으며, 이 결과는 익명 함수이다.

이제 increment() 함수를 호출할 때마다, count 변수의 값이 1씩 증가되고 그 값을 출력한다. 클로저는 counter() 함수가 반환한 익명 함수가 count 변수를 참조할 수 있도록 한다. 그래서 increment() 함수가 호출될 때마다 count 변수의 값을 증가시키는 것을 가능하게 한다.

 

예시 3) 비동기 콜백 함수

function createAsyncTask(callback) {
  let count = 0;
  setInterval(function() {
    count++;
    callback(count);
  }, 1000);
}

createAsyncTask(function(count) {
  console.log(`The count is ${count}`);
});

위 예시에서 createAsyncTask() 함수는 매초마다 실행되는 콜백 함수를 생성하는데 이 콜백 함수는 count 변수의 값을 증가시키고, 이 값을 출력한다. 이 예시에서도 클로저를 이용하여 콜백 함수가 count 변수를 참조할 수 있게 만들었다. 이렇게 하면 콜백 함수가 실행될 때마다 count 변수의 값이 유지되며, 이 값은 계속해서 증가된다.

 

3. Javascript 엔진에서 클로저를 생성하는 과정

  1. 함수가 호출되면 해당 함수의 실행 컨텍스트가 생성된다. 실행 컨텍스트는 함수가 실행되는 동안 필요한 정보를 저장한다.
  2. 실행 컨텍스트 내부에 현재 함수가 속한 렉시컬 스코프 정보가 포함된다. 이 정보는 함수가 호출될 때 해당 함수의 변수에 접근하기 위해 사용된다.
  3. 함수 내부에서 내부 함수가 선언되면, 해당 함수의 렉시컬 스코프 정보가 내부 함수의 스코프 체인에 추가된다.

위와 같은 방식으로 자바스크립트 엔진은 클로저를 구현하고, 함수 실행 도중에 변수를 유지하고, 내부 함수가 호출될 때마다 해당 변수에 대한 정보를 유지하게 된다. 이를 통해 클로저를 사용하여 함수의 상태를 유지하거나, 비동기 처리를 할 수 있다.

 

참고

https://ko.javascript.info/closure

 

변수의 유효범위와 클로저

 

ko.javascript.info

https://poiemaweb.com/js-closure

 

Closure | PoiemaWeb

클로저(closure)는 자바스크립트에서 중요한 개념 중 하나로 자바스크립트에 관심을 가지고 있다면 한번쯤은 들어보았을 내용이다. execution context에 대한 사전 지식이 있으면 이해하기 어렵지 않

poiemaweb.com

 

댓글