Develope/Javascript

JavaScript 클로저(Closure)

oper0116 2024. 8. 27. 15:48
반응형

클로저(Closure)는 JavaScript의 중요한 개념 중 하나로, 함수와 함수가 선언된 어휘적 환경(Lexical Environment)을 함께 기억하는 구조이다.
클로저는 주로 함수 내부에서 정의된 또 다른 함수를 통해 외부 함수의 변수에 접근할 수 있도록 하며, 이를 통해 다양한 유용한 기능을 구현할 수 있다.

클로저의 기본 개념

클로저는 내부 함수가 외부 함수의 변수에 접근할 수 있는 메커니즘이며, 내부 함수가 외부 함수의 범위에 있는 변수를 "기억"하기 때문에 클로저가 형성된다.

function outerFunction() {
    const outerVariable = "I am outside!";

    function innerFunction() {
        console.log(outerVariable); // "I am outside!" 출력
    }

    return innerFunction;
}

const myInnerFunction = outerFunction();
myInnerFunction();

이 예제에서 outerFunction은 innerFunction을 반환한다. myInnerFunction은 outerFunction의 외부 변수인 outerVariable에 접근할 수 있다.
이처럼 innerFunction이 외부 함수의 변수에 접근할 수 있는 능력을 클로저라고 한다.

클로저의 특징

클로저는 몇 가지 중요한 특징을 가지고 있다.

변수의 유지

클로저는 외부 함수가 종료된 후에도 외부 함수의 변수 값을 유지할 수 있기에, 함수가 호출되고 종료된 이후에도 해당 함수의 변수에 접근할 수 있는 방법을 제공한다.

function counter() {
    let count = 0;

    return function () {
        count += 1;
        return count;
    };
}

const myCounter = counter();
console.log(myCounter()); // 1 출력
console.log(myCounter()); // 2 출력
console.log(myCounter()); // 3 출력

여기서 counter 함수는 count 변수를 포함하는 내부 함수를 반환한다. 이 반환된 함수는 count 변수에 접근할 수 있으며, count 값은 클로저에 의해 유지된다.

캡슐화

클로저는 데이터를 은닉하고 캡슐화하는 데 사용된다.
외부 함수의 변수는 외부에서 직접 접근할 수 없지만, 클로저를 통해서만 접근할 수 있으며, 이로 인해 변수를 안전하게 보호할 수 있다.

function createCounter() {
    let count = 0;

    return {
        increment: function () {
            count += 1;
            return count;
        },
        decrement: function () {
            count -= 1;
            return count;
        },
    };
}

const counter = createCounter();
console.log(counter.increment()); // 1 출력
console.log(counter.increment()); // 2 출력
console.log(counter.decrement()); // 1 출력

createCounter 함수는 count 변수를 직접적으로 노출하지 않지만, 클로저를 통해 increment와 decrement 메서드를 통해 안전하게 접근할 수 있게 한다.

클로저의 활용

클로저는 다양한 실용적인 상황에서 사용될 수 있다.

함수의 결과를 저장

클로저를 사용하여 함수의 실행 결과를 메모이제이션(Memoization) 하여 성능을 최적화할 수 있습니다.

이벤트 핸들러

클로저는 이벤트 핸들러 내부에서 유용하다. 예를 들어, 반복문 내에서 클로저를 사용하면 각 반복마다 고유한 변수를 유지할 수 있다.

for (var i = 0; i < 3; i++) {
    setTimeout(
        (function (i) {
            return function () {
                console.log(i);
            };
        })(i),
        1000
    );
}

이 코드는 1초 후에 0, 1, 2를 출력한다. 클로저를 사용하지 않으면 모든 타이머가 동일한 변수를 참조하게 되어 반복문의 마지막 값만 출력된다.

모듈 패턴

클로저는 모듈 패턴을 구현하여 공개와 비공개 메서드를 정의하는 데 사용되며, 이는 데이터 은닉과 캡슐화를 지원한다.

const Module = (function () {
    let privateVar = "I am private";

    return {
        publicMethod: function () {
            console.log(privateVar);
        },
    };
})();

Module.publicMethod(); // "I am private" 출력

클로저 사용 시 주의점

메모리 관리

클로저는 변수를 유지하기 때문에 메모리 누수(memory leak)를 일으킬 수 있다. 필요하지 않은 클로저는 사용 후 제거해야 한다.

디버깅 어려움

클로저는 종종 디버깅을 어렵게 만들 수 있는데, 변수가 어느 스코프(scope)에 속하는지 헷갈릴 수 있기 때문이다.

결론

클로저는 JavaScript의 함수가 어떻게 작동하는지를 깊이 이해할 수 있게 해주는 중요한 개념이기에, 클로저를 사용하면 변수와 함수를 더 유연하고 강력하게 관리할 수 있다.
클로저의 특성과 활용법을 잘 이해하면, 더 나은 JavaScript 코드를 작성할 수 있다.

반응형