Closure...

wonyoung·2024년 3월 31일

Javascript

목록 보기
29/36

클로저(Closure)는 JavaScript에서 매우 중요한 개념 중 하나로, 함수가 선언될 때의 환경(렉시컬 환경)을 기억하고, 그 함수가 나중에 어디서 호출되더라도 해당 환경에 접근할 수 있게 하는 기능입니다. 클로저를 통해 함수는 자신이 생성될 때의 스코프에 있는 변수들에 계속해서 접근할 수 있습니다. 이는 JavaScript의 함수가 "First Class Citizens"으로 간주되기 때문에 가능한 것입니다.

클로저(Closure)는 프로그래밍 언어에서 중요한 개념 중 하나입니다. 특히 함수형 프로그래밍에서 자주 등장하는 개념이죠. 간단히 말해, 클로저는 함수가 생성될 때 그 함수가 생성된 환경을 "기억"하는 함수입니다. 다시 말해서, 클로저는 어떤 함수 내부에서 사용된 외부 변수들에 대한 접근을 가능하게 해주는 기능을 말합니다.

클로저의 작동 원리

  1. 함수 중첩: JavaScript에서는 함수 내부에 다른 함수를 선언할 수 있습니다. 내부 함수는 외부 함수의 변수에 접근할 수 있습니다.
  2. 외부 함수의 반환: 내부 함수는 외부 함수에 의해 반환될 수 있습니다. 이때, 내부 함수는 외부 함수가 종료된 후에도 외부 함수의 변수에 접근할 수 있는데, 이 기능이 바로 클로저입니다.
  3. 환경 기억: 내부 함수는 외부 함수의 환경을 "기억"합니다. 즉, 외부 함수의 실행 컨텍스트가 종료되어도, 외부 함수의 변수에 접근할 수 있는 참조를 유지합니다.

클로저의 예시

function makeAdder(x) {
    return function(y) {
        return x + y;
    };
}

var add5 = makeAdder(5);
var add10 = makeAdder(10);

console.log(add5(2));  // 7
console.log(add10(2)); // 12

이 예시에서 makeAdder 함수는 함수를 반환합니다. 반환된 함수는 makeAdder 함수의 파라미터 x에 접근할 수 있는 클로저를 형성합니다. makeAdder(5)를 호출하면, x의 값으로 5가 설정된 새로운 함수가 생성됩니다. 이 함수는 어디서 호출되든 x의 값인 5에 접근할 수 있습니다. 이것이 클로저의 핵심 기능입니다.

클로저의 용도

  • 데이터 캡슐화: 클로저를 이용해 특정 데이터를 외부로부터 숨기고, 특정 함수를 통해서만 접근하게 할 수 있습니다. 이를 통해 객체 지향 프로그래밍의 캡슐화와 유사한 효과를 낼 수 있습니다.
  • 콜백 함수: 비동기 처리나 이벤트 리스너에서 클로저는 특정 상태를 유지하면서 필요할 때 해당 상태에 접근해야 할 때 유용합니다.
  • 고차 함수: 함수를 반환하는 함수에서 클로저는 반환된 함수가 선언될 때의 환경을 "기억"하게 하여, 더 강력한 추상화와 모듈화를 가능하게 합니다.

쉽게 설명하면 클로저는 함수와 그 함수가 만들어질 때 주변 상황을 함께 담아두는 기능을 말해요. 함수가 어떤 외부 변수를 사용하고 있을 때, 그 함수와 변수가 서로 붙어 다니게 되는 거죠.

이렇게 생각해볼까요? 당신이 한 카페의 단골이고, 그 카페에서는 당신이 항상 아메리카노를 주문한다는 걸 기억해둔다고 해보세요. 다음 번에 카페에 갈 때, 직원은 "아메리카노를 드릴까요?"라고 물을 수 있습니다. 여기서 카페 직원이 클로저라고 생각해볼 수 있어요. 왜냐하면, 직원은 당신의 주문(외부 변수)을 기억하고 있으니까요.

프로그래밍에서 클로저의 예를 들어볼게요:

  1. 어떤 함수(makeAdder)가 있습니다. 이 함수는 또 다른 함수를 만들어 반환하는데, 반환되는 함수는 makeAdder로부터 받은 특정 숫자(x)를 기억하고 있습니다.
  2. makeAdder 함수에 5라는 숫자를 주고 호출하면, 새 함수가 만들어지는데 이 함수는 "5를 더하는 일"을 항상 기억합니다.
  3. 이제, 이 새로운 함수에 어떤 숫자를 주고 호출하면, 그 숫자에 5를 더해서 결과를 줍니다.

클로저는 특정 기능을 가진 "함수"
즉, 클로저는 함수와 그 함수가 참조하는 외부 변수들의 조합으로 이루어진 특별한 종류의 함수입니다. 이를 통해, 함수가 자신이 생성될 당시의 환경(변수, 상태 등)을 "기억"하고, 그 환경에 접근할 수 있는 기능을 가지게 됩니다.
간단하게 말해서, 클로저는 두 가지를 합니다:

  1. 함수: 클로저는 일을 수행하는 코드 덩어리, 즉 함수입니다.
  2. 환경 기억: 클로저는 자신이 생성될 때 주변 환경(특정 변수의 값 등)을 기억하고, 나중에 그 환경에 있는 변수를 사용할 수 있습니다.

클로저는 주로 다음과 같은 상황에서 생성됩니다:

  1. 내부 함수가 외부 함수의 변수를 참조할 때: 가장 일반적인 클로저의 생성 상황입니다. 외부 함수가 내부 함수를 반환하고, 이 내부 함수가 외부 함수의 변수를 참조할 경우, 이 내부 함수는 클로저가 됩니다. 이 클로저는 외부 함수의 변수들을 "기억"하고, 외부 함수의 실행이 끝난 후에도 이 변수들에 접근할 수 있습니다.

  2. 데이터 은닉과 캡슐화를 위해: 클로저를 사용하여 특정 데이터를 함수 외부로부터 보호하고, 오직 특정 함수를 통해서만 데이터에 접근하도록 할 수 있습니다. 이 경우, 클로저는 private 변수와 같은 역할을 하며, 객체 지향 프로그래밍의 캡슐화와 유사한 개념을 구현할 수 있습니다.

  3. 콜백 함수에서: 비동기 작업이나 이벤트 처리와 같이 나중에 호출되는 콜백 함수에서 외부 스코프의 변수를 사용할 때 클로저가 생성될 수 있습니다. 이를 통해, 콜백 함수는 비동기 작업의 결과나 이벤트 발생 시 필요한 추가 정보를 "기억"하고 사용할 수 있습니다.

  4. 고차 함수에서 반환될 때: 고차 함수(higher-order function)는 다른 함수를 반환하는 함수입니다. 고차 함수에 의해 반환된 함수가 외부 스코프의 변수를 참조하면, 이 반환된 함수는 클로저가 됩니다. 이를 통해 함수를 동적으로 생성하고, 생성된 함수가 실행 시점에 필요한 정보를 가질 수 있도록 합니다.

이러한 상황들은 클로저가 생성될 수 있는 대표적인 예시들입니다. 클로저를 이용하면, 함수가 자신이 생성될 때의 환경을 "기억"하게 만들어, 프로그래밍에서 매우 유용하게 활용할 수 있습니다.

js 예시

이 예시는 간단한 카운터 기능을 구현한 것으로, 클로저를 통해 어떻게 내부 상태(변수)를 안전하게 숨기고 관리할 수 있는지 보여줍니다.

예시: 간단한 카운터 만들기

function createCounter() {
    let count = 0; // `createCounter` 함수의 지역 변수
    return function() {
        count = count + 1; // 외부 함수의 변수 `count`를 참조
        return count;
    };
}
// 카운터 인스턴스 생성
const counter1 = createCounter();
const counter2 = createCounter();
console.log(counter1()); // 1
console.log(counter1()); // 2
console.log(counter2()); // 1
console.log(counter2()); // 2

작동 방식:

  1. createCounter 함수는 내부 함수(익명 함수)를 반환합니다. 이 내부 함수는 createCounter의 지역 변수 count에 접근합니다.
  2. createCounter 함수가 호출될 때마다 새로운 count 변수가 생성되고, 각각의 내부 함수(클로저)는 자신이 생성될 때의 count 변수에 대한 참조를 유지합니다. 이렇게 하여, 각 클로저는 독립적인 count 변수의 상태를 "기억"하게 됩니다.
  3. counter1과 counter2는 서로 독립적인 클로저 인스턴스입니다. 따라서 각각 별도의 count 변수를 가지고, 서로에게 영향을 주지 않고 독립적으로 카운트를 증가시킵니다.
  4. 이 내부 함수(클로저)가 실행될 때마다, count 변수의 값이 증가하고, 그 값이 반환됩니다. 외부에서는 count 변수에 직접 접근할 수 없으며, 오직 이 클로저를 통해서만 count 값을 변경하고 조회할 수 있습니다.
    이 예시에서 클로저의 핵심적인 특징 두 가지를 확인할 수 있습니다:
  • 데이터 은닉과 캡슐화: count 변수는 외부로부터 직접 접근할 수 없으며, 오직 클로저를 통해서만 조작할 수 있습니다. 이는 객체 지향 프로그래밍의 캡슐화와 비슷한 개념입니다.
  • 상태 유지: 각 클로저는 자신만의 독립적인 상태(count 변수)를 유지하며, 여러 번 호출되더라도 해당 상태를 기억합니다.
    클로저를 이용하면, 이처럼 각 함수의 실행 맥락에 따라 독립적인 상태를 유지하고 관리할 수 있는 강력한 방법을 제공합니다.
profile
😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀

0개의 댓글