코딩 스쿨 JavaScript

언어선택 : HTMLCSSJAVAJAVASCRIPTMYSQLSQL PHP

JavaScript Function Closures

JavaScript Closures: 클로저 개념과 사용법

  • *클로저(Closure)**는 JavaScript 함수외부 함수의 변수에 접근할 수 있는 강력한 기능입니다. 클로저는 내부 함수가 외부 함수의 실행 컨텍스트가 종료된 후에도 외부 함수의 변수를 기억하고 참조할 수 있게 해줍니다. 이로 인해 데이터 은닉이나 상태 유지 같은 중요한 프로그래밍 기법을 구현할 수 있습니다.

이 가이드는 JavaScript 클로저의 개념사용법을 설명하고, 실용적인 예시를 제공합니다.


1. 클로저의 기본 개념

  • *클로저(Closure)**는 함수가 선언된 스코프에서 변수에 접근할 수 있는 함수를 말합니다. 즉, 내부 함수외부 함수의 변수기억하고 참조할 수 있을 때, 해당 내부 함수는 클로저라고 합니다.

1.1. 클로저의 기본 구조

function outer() {
    const outerVar = 'I am from outer';

    function inner() {
        console.log(outerVar);  // 외부 함수의 변수에 접근
    }

    return inner;
}

const innerFunction = outer();  // outer() 호출 시 inner 함수 반환
innerFunction();  // 'I am from outer' 출력

1.2. 클로저의 특징

  • 내부 함수외부 함수의 변수에 접근할 수 있습니다.
  • 외부 함수가 종료된 후에도 내부 함수는 외부 함수의 변수를 기억하고 참조할 수 있습니다.
  • 함수가 선언된 위치에 따라 변수 스코프가 결정되며, **this*와는 무관합니다.

2. 클로저 동작 방식

클로저는 외부 함수가 종료된 후에도 외부 함수의 변수 환경저장하고 유지합니다. 이는 내부 함수가 외부 함수의 변수를 참조할 수 있게 해줍니다.

2.1. 클로저가 변수에 접근하는 방식

function counter() {
    let count = 0;

    return function() {
        count++;
        console.log(count);
    };
}

const increment = counter();  // counter() 호출로 내부 함수 반환
increment();  // 1
increment();  // 2
increment();  // 3

  • counter() 함수는 count 변수를 생성하고, 내부 함수를 반환합니다.
  • 반환된 함수는 count 변수를 참조하며, 함수가 호출될 때마다 count이 증가합니다.
  • 외부 함수(counter)가 종료된 후에도, 내부 함수count 변수를 계속 기억하고 있습니다.

3. 클로저의 실용적인 사용 예시

3.1. 데이터 은닉과 캡슐화

클로저는 변수를 은닉하고, 외부에서 직접 접근할 수 없도록 보호할 수 있습니다. 이를 통해 데이터를 안전하게 관리하는 캡슐화 기법을 구현할 수 있습니다.

function createCounter() {
    let count = 0;

    return {
        increment: function() {
            count++;
            console.log(count);
        },
        getCount: function() {
            return count;
        }
    };
}

const counter = createCounter();
counter.increment();  // 1
counter.increment();  // 2
console.log(counter.getCount());  // 2

  • count 변수createCounter() 함수 내부에서만 존재하며, 외부에서 직접 접근할 수 없습니다.
  • *increment()*와 getCount() 메서드를 통해서만 **count*에 접근할 수 있습니다.
  • 이를 통해 데이터의 무분별한 변경을 막을 수 있습니다.

3.2. 함수 공장(Function Factory)

클로저를 사용하면 함수를 반환하는 함수, 즉 함수 공장을 만들 수 있습니다. 이를 통해 동일한 함수 논리다양한 값을 적용하여 유사한 동작을 하는 함수들을 쉽게 생성할 수 있습니다.

function createMultiplier(multiplier) {
    return function(value) {
        return value * multiplier;
    };
}

const double = createMultiplier(2);
const triple = createMultiplier(3);

console.log(double(5));  // 10
console.log(triple(5));  // 15

  • *createMultiplier()*는 곱셈 함수를 반환하는 함수 공장입니다.
  • multiplier 값에 따라 다른 함수를 생성하여, 다양한 동작을 수행할 수 있습니다.

4. 클로저의 메모리 관리

클로저는 외부 함수의 변수를 계속 유지하기 때문에, 메모리 관리에 주의해야 합니다. 클로저가 너무 많거나, 오랫동안 사용되지 않는 클로저가 존재할 경우 메모리 누수가 발생할 수 있습니다.

4.1. 클로저와 메모리 누수 방지

클로저를 사용한 후에는, 필요하지 않은 참조를 제거하여 메모리 누수를 방지하는 것이 좋습니다.

function createCounter() {
    let count = 0;

    return {
        increment: function() {
            count++;
            console.log(count);
        },
        reset: function() {
            count = 0;  // 외부 변수 초기화
        }
    };
}

const counter = createCounter();
counter.increment();  // 1
counter.increment();  // 2
counter.reset();      // count 값을 0으로 리셋
counter.increment();  // 1

  • reset() 메서드를 추가하여 외부 변수를 필요할 때 초기화할 수 있습니다.
  • 이를 통해 메모리 누수를 방지하고, 클로저 내부 변수를 적절히 관리할 수 있습니다.

5. 즉시 실행 함수와 클로저 (IIFE와 클로저)

  • *즉시 실행 함수(IIFE: Immediately Invoked Function Expression)**는 즉시 호출되며, 클로저를 활용하여 변수를 은닉하거나 초기화하는 데 사용될 수 있습니다.

5.1. IIFE와 클로저 사용 예시

const counter = (function() {
    let count = 0;

    return function() {
        count++;
        console.log(count);
    };
})();

counter();  // 1
counter();  // 2

  • 즉시 실행 함수한 번 호출되며, 내부 변수를 은닉하고, 클로저를 통해 외부에서 계속 참조할 수 있습니다.
  • 변수 스코프지역적으로 제한하고, 전역 오염을 방지합니다.

6. 클로저의 this 바인딩

클로저 내에서 **this**는 외부 함수의 **this**를 그대로 유지하지 않습니다. 클로저 내에서 **this**가 다른 컨텍스트를 가리킬 수 있으므로, 이를 주의해서 사용해야 합니다.

6.1. 클로저와 this 예시

const person = {
    name: 'Alice',
    greet: function() {
        console.log(`Hello, my name is ${this.name}`);

        const innerFunction = function() {
            console.log(`Inner function: ${this.name}`);  // `this`는 전역 객체를 가리킴
        };

        innerFunction();
    }
};

person.greet();
// Hello, my name is Alice
// Inner function: undefined (브라우저에서는 전역 객체의 this를 가리키므로 undefined)

6.2. 클로저 내에서 this 해결 방법

해결 방법 1: 변수에 this 저장

const person = {
    name: 'Alice',
    greet: function() {
        const self = this;  // `this`를 변수로 저장
        console.log(`Hello, my name is ${self.name}`);

        const innerFunction = function() {
            console.log(`Inner function: ${self.name}`);
        };

        innerFunction();
    }
};

person.greet();
// Hello, my name is Alice
// Inner function: Alice

해결 방법 2: 화살표 함수 사용

const person = {
    name: 'Alice',
    greet: function() {
        console.log(`Hello, my name is ${this.name}`);

        const innerFunction = () => {
            console.log(`Inner function: ${this.name}`);  // 화살표 함수는 상위 스코프의 this를 상속
        };

        innerFunction();
    }
};

person.greet();
// Hello, my

 name is Alice
// Inner function: Alice


요약

JavaScript 클로저는 함수가 외부 함수의 변수영구적으로 접근할 수 있는 능력을 제공하여 데이터 은닉상태 유지 같은 중요한 기능을 구현할 수 있습니다.

  • 클로저외부 함수의 변수기억하고, 내부 함수에서 참조할 수 있습니다.
  • 이를 통해 데이터 은닉, 상태 유지, 함수 공장과 같은 다양한 프로그래밍 패턴을 구현할 수 있습니다.
  • 메모리 관리에 주의해야 하며, 필요할 때는 변수 초기화 등을 통해 메모리 누수를 방지해야 합니다.
  • this 바인딩에 주의하여, 화살표 함수this 저장 같은 방법으로 클로저 내에서 올바르게 사용할 수 있습니다.

클로저는 JavaScript의 유연성과 강력함을 보여주는 중요한 개념으로, 상태를 유지하면서도 은닉할 수 있는 함수를 만들 때 유용하게 사용됩니다.


copyright ⓒ 스타트코딩 all rights reserved.
이메일 : startcodingim@gamil.com