Skip to main content

Command Palette

Search for a command to run...

클로저 Closure

Updated
•View as Markdown
클로저 Closure

클로저

어떤 함수 A에서 선언한 변수 a를 참조하는 내부함수 B를 외부로 전달할 경우 A의 실행 컨텍스트가 종료된 이후에도 변수 a가 사라지지 않는 현상을 말합니다.

다른 표현들

  • 함수를 선언할 때 만들어지는 유효범위가 사라진 후에도 호출할 수 있는 함수

  • 이미 생명 주기가 끝난 외부 함수의 변수를 참조하는 함수

  • 자신이 생성될 때의 스코프에서 알 수 있었던 변수들 중 언젠가 자신이 실행될 때 사용할 변수들만을 기억하여 유지시키는 함수

var outer = function () {
    var a = 1;
    var inner = function () {
        return ++a;
    };
    return inner;
};

var outer2 = outer();
console.log(outer2()); // 2
console.log(outer2()); // 3

클로저가 발생하는 이유

가비지 컬렉터는 어떤 값을 참조하는 변수가 하나라도 있다면 그 값은 수집 대상에 포함시키지 않습니다. 외부함수인 outer의 실행이 종료되더라도 내부함수인 inner 함수는 언젠가 outer2를 실행함으로써 호출될 가능성이 있습니다. 언젠가 inner 함수의 실행 컨텍스트가 활성화되면 outerEnvironmentReference가 outer 함수의 LexicalEnvironment를 필요로 할 것이므로 수집 대상에서 제외됩니다. 그 덕에 inner 함수가 이 변수에 접근할 수 있는 것입니다.

클로저의 메모리 관리 방법

클로저는 어떤 필요에 의해 의도적으로 함수의 지역변수를 메모리를 소모하도록 함으로써 발생합니다. 따라서 그 필요성이 사라진 시점에는 더는 메모리를 소모하지 않게 만들어야 합니다. 참조 카운트를 0으로 만들면 언젠가 GC가 수거해갈 것이고 이때 소모됐던 메모리가 회수될 것입니다. 참조 카운트를 0으로 만드려면 식별자에 참조형이 아닌 기본형 데이터(보통 null이나 undefined)를 할당하면 됩니다.

var outer = function () {
    var a = 1;
    var inner = function () {
        return ++a;
    };
    return inner;
};

var outer2 = outer();
console.log(outer2()); // 2
console.log(outer2()); // 3
outer = null; // outer 식별자의 inner 함수 참조를 끊음

클로저의 활용 사례?

  1. 콜백 함수 내부에서 외부 데이터를 사용하고자 할 때

  2. 접근 권한 제어(정보 은닉)

  3. 부분 적용 함수

  4. 커링 함수

자바스크립트에서 접근 권한 제어(정보 은닉)를 하려면?

자바스크립트는 기본적으로 변수 자체에 이러한 접근 권한을 직접 부여하도록 설계되어 있지 않지만 클로저를 이용하면 함수 차원에서 public한 값과 private한 값을 구분하는 것이 가능합니다. 외부에서는 오직 outer 함수가 return한 정보에만 접근할 수 있습니다. return 값이 외부에 정보를 제공하는 유일한 수단인 것입니다. 외부에 제공하자 하는 정보들을 모아서 return하고, 내부에서만 사용할 정보들은 return하지 않는 것으로 접근 권한 제어가 가능합니다.

클로저를 활용해 접근권한을 제어하는 방법

먼저 함수에서 지역변수 및 내부함수 등을 생성합니다. 그리고 외부에 접근권한을 주고자 하는 대상들로 구성된 참조형 데이터를 return합니다 return한 변수들은 공개 멤버(public)가 되고, 그렇지 않은 변수들은 비공개 멤버가 됩니다

부분 적용 함수

n개의 인자를 받는 함수에 미리 m개의 인자만 넘겨 기억시켰다가, 나중에 (n-m)개의 인자를 넘기면 비로소 원래 함수의 실행 결과를 얻을 수 있게끔 하는 함수입니다.

부분 적용 함수를 활용하여 디바운스 코드를 작성하면?

var debounce = function (eventName, func, wait) {
    var timeoutId = null;
    return function (event) {
        var self = this;
        console.log(eventName, 'event 발생');
        clearTimeout(timeoutId);
        timeoutId = setTimeout(func.bind(self, event), wait);
    };
};

var moveHandler = function (e) {
    console.log('move event 처리');
};
var wheelHandler = function (e) {
    console.log('wheel event 처리');
};

document.body.addEventListener('mousemove', debounce('move', moveHandler, 500));
document.body.addEventListener('mousemove', debounce('mousewheel', wheelHandler, 700));

커링 함수

여러 개의 인자를 받는 함수를 하나의 인자만 받는 함수로 나눠서 순차적으로 호출될 수 있게 체인 형태로 구성한 것을 말합니다. 커링은 한 번에 하나의 인자만 전달하는 것을 원칙으로 합니다. 또한 중간 과정상의 함수를 실행한 결과는 그 다음 인자를 받기 위해 대기만 할 뿐이므로, 마지막 인자가 전달되기 전까지는 원본 함수가 실행되지 않습니다. (부분 적용 함수는 여러 개의 인자를 전달할 수 있고, 실행 결과를 재실행할 때 원본 함수가 무조건 실행됩니다.)

var curry3 = function (func) {
    return function (a) {
        return function (b) {
            return func(a, b);
        };
    };
};

var getMaxWith10 = curry3(Math.max)(10);
console.log(getMaxWith10(8)); // 10
console.log(getMaxWith10(25)); // 25

var getMinWith10 = curry3(Math.min)(10);
console.log(getMaxWith10(8)); // 8
console.log(getMaxWith10(25)); // 10

More from this blog

이터레이션/이터러블/이터레이터

이터레이션 프로토콜 (Iteration protocols) 순회할 수 있는 데이터 컬렉션(배열, 문자열, 유사 배열 객체, DOM 컬렉션 등)을 만들기 위해 ES6에서 도입한 규칙입니다. ES6 이전에도 순회 가능한 데이터 컬렉션들은 통일된 규약 없이 각자 나름의 구조를 가지고 for 문, for...in 문, forEach 메서드 등 다양한 방법으로 순회할 수 있었습니다. 하지만 ES6에서 순회 가능한 데이터 컬렉션을 이터레이션 프로토콜을 준...

Apr 3, 2023
이터레이션/이터러블/이터레이터

자바스크립트의 함수는 일급 객체

일급 객체란 일급 객체란 다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체입니다. 다음과 같은 조건을 만족하는 객체를 일급 객체라 합니다. 무명의 리터럴로 생성할 수 있다. 즉, 런타임에 생성이 가능하다 변수나 자료구조(객체, 배열 등)에 저장할 수 있다 함수의 매개변수에 전달할 수 있다 함수의 반환값으로 사용할 수 있다 자바스크립트의 함수는 위의 조건을 모두 만족하므로 일급 객체입니다. // 1. 함수는 무명의 리터럴...

Feb 21, 2023
자바스크립트의 함수는 일급 객체

콜백 함수 Callback function

콜백함수 다른 코드(함수 또는 메서드)에게 인자로 넘겨줌으로써 그 제어권도 함께 위임한 함수입니다. 콜백 함수를 위임받은 코드는 자체적인 내부 로직에 의해 이 콜백 함수를 적절한 시점에 실행할 것입니다. 콜백 함수 내부에서 this가 가리키는 대상 콜백 함수도 함수이기 때문에 기본적으로는 this가 전역객체를 참조하지만, 제어권을 넘겨받을 코드에서 콜백 함수에 별도로 this가 될 대상을 지정한 경우에는 그 대상을 참조하게 됩니다. setTim...

Dec 12, 2022
콜백 함수 Callback function

EuiJin's blog

10 posts

프론트엔드 개발자