클로저는 함수가 선언될 때의 스코프를 기억하며, 함수가 생성된 이후에도 그 스코프에 접근할 수 있는 기능을 말합니다. 즉, 함수가 자신이 생성된 환경을 '기억'하는 것이라고 할 수 있습니다. 클로저는 js의 함수가 일급 객체라는 특성과 렉시컬 스코프의 조합으로 만들어집니다.
function 외부함수(외부변수) {
return function 내부함수(내부변수){
console.log('외부 변수: ' + 외부변수);
console.log('내부 변수: ' + 내부변수);
};
}
const My함수 = 외부함수('밖');
My함수('안');
여기서 내부함수는 외부함수의 내부에 정의되어 있습니다. 내부함수는 자신이 생성된 스코프, 즉 외부함수의 스코프를 기억하고, 외부함수의 호출이 완료된 이후에도 그 스코프에 접근할 수 있습니다. 그리고 이에 따라 내부함수는 외부변수에도 접근할 수 있습니다.
클로저는 변수와 함수의 접근 범위를 제어하고 특정 데이터와 상태를 유지하기 위해 자주 활용됩니다.
클로저는 외부에서 접근할 수 없는 비공개 변수와 함수를 만들 수 있습니다. 이를 통해 데이터를 은닉하여 외부 접근을 막고, 데이터 무결성을 유지할 수 있습니다. 예를 들어, 특정 함수 내부에서만 접근 가능한 변수를 생성하고, 이를 조작할 수 있는 함수만 외부로 노출하여 안전하게 데이터를 관리할 수 있습니다.
클로저는 비동기 작업에서 이전의 실행 컨텍스트를 유지해야 할 때 유용합니다. 콜백 함수가 비동기적으로 실행될 때 클로저를 사용하면 함수 실행 시점의 변수를 참조할 수 있습니다.
function 로그생성(name) {
return function() {
console.log(`로그: ${name}`);
};
}
const 로거 = 로그생성('김현중짱');
setTimeout(로거, 1000); // 1초 후에 `로그: 김현중짱` 출력
위의 예시에서 클로저가 name 변수 '김현중짱'을 저장하여 1초 후에도 해당 값이 유지되어 출력됩니다.
모듈 패턴은 특정 기능을 캡슐화하고, 외부에 공개하고자 하는 부분만 선택적으로 노출하여 코드의 응집력을 높이고, 유지보수성을 향상시키는 패턴입니다. 클로저를 활용하면 필요한 함수와 데이터만 외부로 노출함으로써 모듈 패턴을 쉽게 구현할 수 있습니다.
즉, 함수가 생성될 때 그 함수는 자신이 속한 렉시컬 환경을 기억합니다(클로저). 이 렉시컬 환경은 실행 컨텍스트의 일부로, 함수가 나중에 다른 위치에서 실행되더라도 원래 선언된 환경의 변수에 접근할 수 있게 해줍니다.