Programming/JavaScript

[JavaScript] 클로저(Closure)와 콜백함수(callback)

Juun 2023. 3. 16. 17:36
반응형

클로저(Closure)란???

함수 내부에서 외부 스코프에 선언된 변수를 참조하는 것을 클로저(Closure)라고 합니다.

클로저는 함수와 함수가 선언된 어휘적 환경(Lexical Environment)의 조합입니다. 

클로저는 함수가 선언될 당시의 환경을 기억하고, 함수가 호출될 때 그 환경을 다시 만들어내는 기능을 합니다. 

이를 통해 함수 안에서 선언한 변수를 함수 외부에서도 사용할 수 있게 됩니다.

 

클로저는 자바스크립트에서 매우 중요한 개념으로, 다른 함수에 인자로 함수를 전달하거나, 객체의 메서드로 함수를 정의할 때 클로저를 사용하여 특정한 상태를 유지할 수 있습니다. 클로저를 사용하면 상태를 보존하고, 함수를 더 유연하고 재사용 가능하게 만들 수 있습니다.

 

또한, 클로저는 자바스크립트에서 비동기 처리를 할 때 매우 유용하게 사용됩니다.

클로저를 이용하여 비동기 함수에서 비동기 처리가 완료되었을 때 실행해야 하는 콜백 함수에 필요한 상태 정보를 전달할 수 있습니다.

이를 통해 비동기 함수 내부의 변수를 외부에서도 참조하고, 상태를 보존할 수 있습니다.

그러나, 클로저를 사용할 때는 메모리 누수(Memory Leak)에 유의해야 합니다. 클로저는 함수가 반환될 때 함수를 선언한 Lexical Environment를 계속 유지하기 때문에, 메모리 사용량이 늘어날 수 있습니다. 따라서, 필요하지 않은 클로저는 적극적으로 해제해야 합니다.

 

콜백(callback)이란?

콜백(callback) 함수는 다른 함수의 인자로 전달되어, 특정 이벤트나 비동기적인 작업이 끝나면 호출되는 함수입니다.

즉, 콜백 함수는 특정 함수의 작업 결과를 처리하는 작업을 수행합니다. 자바스크립트에서는 비동기적인 작업이 많기 때문에 콜백 함수가 매우 중요한 역할을 합니다. 예를 들어, setTimeout 함수는 콜백 함수를 사용합니다.


클로저와 콜백은 자바스크립트에서 비동기 처리를 위한 매우 중요한 개념이라 볼 수 있습니다.

클로저를 사용하면 함수 내에서 선언된 변수를 함수 외부에서 액세스할 수 있으므로, 이를 이용하여 콜백 함수를 생성할 수 있습니다. 이러한 콜백 함수는 비동기 작업이 완료되면 호출되어 결과를 처리하는 데 사용됩니다. 

이러한 특징 때문에 클로저와 콜백은 항상 같이 실행될거라는 착각을 할 수 있습니다.

클로저와 콜백은 항상 같이 실행이 될까???

 

클로저는 함수가 정의될 때 함수 내부에서 선언된 변수를 포함하여 외부 스코프의 변수에 접근할 수 있도록 하는 기술입니다.

클로저를 이용하면 함수를 리턴하거나 다른 함수의 인자로 전달할 때, 내부 변수를 계속 유지하면서 사용할 수 있습니다.

 

반면에 콜백은 비동기적인 처리를 위해 사용되는 함수를 말합니다. 콜백은 함수를 인자로 전달하고, 처리가 완료된 후에 이 함수를 호출하여 결과를 전달합니다. 이를 이용하여 비동기적인 작업을 수행하거나 이벤트를 처리하는 등의 작업을 처리할 수 있습니다.

 

물론, 클로저와 콜백은 함께 사용되는 경우가 많기 때문에 서로 연관되어 있는 것처럼 느껴질 수 있습니다.

예를 들어, 비동기적으로 처리된 결과를 콜백 함수에서 사용해야 하는 경우에 클로저를 이용하여 결과를 유지할 수 있습니다. 그러나 이는 클로저와 콜백이 서로 다른 개념임을 보여주는 예시일 뿐입니다.

따라서, 클로저와 콜백은 함께 움직이는 경우가 많을뿐 항상 같이 실행되지는 않습니다!

 

개념적 설명은 이까지하고 이해를 돕기 위한 코드를 통해 확인해보겠습니다.

다음은 클로저와 콜백을 함께 사용하여 비동기적으로 데이터를 처리하는 예시 코드입니다.

 

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

const increment = counter();

function delayedIncrement(callback) {
  setTimeout(function() {
    increment();
    callback();
  }, 1000);
}

delayedIncrement(function() {
  console.log("increment completed");
});

이 예제 코드에서는 counter 함수가 정의됩니다. 이 함수는 클로저를 사용하여 count 변수를 내부에 가지고 있습니다.

이후 counter 함수가 반환하는 함수가 increment 변수에 할당됩니다.

delayedIncrement 함수는 콜백 함수를 인자로 받으며, 1초 후에 increment 함수를 호출한 후, 전달된 콜백 함수를 실행합니다.

 

따라서, increment 함수가 클로저를 이용하여 count 변수에 접근하여 값이 증가하고 콘솔에 출력됩니다.

그리고 delayedIncrement 함수가 실행되면서 1초 후에 increment 함수가 호출되고, 다시 delayedIncrement 함수의 콜백 함수가 실행되어 "increment completed" 메시지가 콘솔에 출력됩니다.

이렇게 클로저와 콜백 함수를 함께 사용하면 비동기적으로 데이터를 처리하거나 이벤트를 처리하는 등 다양한 상황에서 유용하게 사용할 수 있습니다.

 

클로저 없이 콜백만 사용하는 예시로는 Node.js에서 자주 사용되는 콜백 패턴이 있습니다. 이를 통해 비동기적으로 작업을 수행할 수 있습니다. 예를 들어, 다음은 Node.js의 파일 시스템 모듈을 사용하여 파일을 읽는 코드입니다.

 

const fs = require('fs');

fs.readFile('example.txt', 'utf8', function(err, data) {
  if (err) throw err;
  console.log(data);
});

위의 코드에서는 fs.readFile() 함수를 호출하고, 파일 이름과 인코딩 방식을 전달합니다. 그리고 마지막 인자로 콜백 함수를 전달합니다. 이 함수는 파일 읽기 작업이 완료되면 호출되며, 첫 번째 인자로는 오류가 발생한 경우 해당 오류를 전달하고, 두 번째 인자로는 파일 내용을 전달합니다.

이 콜백 함수를 사용하여 파일을 읽은 후, 파일 내용을 출력하고 있습니다. 이 코드에서는 클로저를 사용하지 않았고, 대신에 비동기적으로 작업을 수행하기 위해 콜백 패턴을 사용하고 있습니다.

 

 

 

 

 

반응형