본문 바로가기

Language/Javascript

클로저란 무엇인가요?

클로저(Closure)란?

실행 컨텍스트가 생성되면서 Lexical Environment에는 두가지 객체가 생성이 됩니다. 하나는 Outer Environment Reference이고, 다른 하나는 Environment Record 입니다. Outer Environment Reference는 현재 실행 컨텍스트가 실행되기 전에 생성된 실행컨텍스트의 Lexical Environment를 참조하고 있는 형태를 이루고 있습니다. 그래서 Scope Chain이 가능한 이유가 이때문으로 나와있습니다.

이 상황에서 클로저라는 것은 어떤 함수 A(현재 실행 컨텍스트가 실행되기 전에 생성된 실행 컨텍스트)에서 선언한 변수 a를 참조하는 내부함수 B(현재 실행 컨텍스트)를 외부로 전달할 때, 전달되는 상황은 return으로 반환되는 것을 의미합니다. 외부로 전달 될 때 A의 실행 컨텍스트가 종료가 되었어도 변수 a가 사라지지않고, 반환된 내부 함수가 참조할 수 있는 현상을 의미합니다. 

외부로 전달 될 때인데, 사실 외부로 전달될 때만 생성되는 것은 아닙니다. 내부 함수가 외부 함수의 변수를 참조하기만 해도 클로저 현상이 발생합니다.

- 내부 함수를 변수에 할당하거나
- 이벤트 핸들러로 사용하거나
- 다른 객체의 메서드로 전달될 때

클로저 현상이 발생합니다. 클로저는 함수와 그 함수가 선언된 Lexical Environment를 기억하고 있다고 생각하면 됩니다.


클로저로 인해 발생할 수 있는 문제는 무엇이 있을까?

해당 함수를 호출했을때, 외부 함수의 변수를 참조하고 있는 형태로 이루어져 있습니다. 그래서, 자바스크립의 GC(Garbage Collection)은 참조하고 있는 대상은 GC 대상으로 포함되지 않습니다. 그래서 이러한 방식으로 코드를 작성하게 된다면? 메모리 누수의 위험이 존재합니다.

그래서, 해당 참조가 전부 끝났다면? undefined, null을 할당해서 어떤 것도 참조하지 않는다를 명시해야합니다. 클로저 현상을 사용하게 된다면, 이러한 방식으로 메모리 누수를 방지할 수 있습니다.

또한, WeakMap 또는 WeakSet을 사용해 참조를 약하게 만들어 GC가 대상 객체를 해제할 수 있게 유도합니다. 함수 설계에서 불필요한 참조를 피하고, 클로저 사용을 최소화하거나 명시적으로 해제시키게 됩니다.



애매한 부분

  • "외부로 전달될 때 클로저가 생성된다"는 설명
    • 클로저는 외부로 전달될 때만 생성되는 것이 아닙니다. 내부 함수가 외부 함수의 변수를 참조하기만 해도 클로저는 생성됩니다. 반환(return)뿐 아니라, 내부 함수를 변수에 할당하거나, 이벤트 핸들러로 사용하거나, 다른 객체의 메서드로 전달할 때도 클로저가 생성됩니다. 즉, "전달될 때"라는 조건이 필요 이상으로 제한적으로 표현되었습니다.
    • 더 정확히 말하면, 클로저는 함수와 그 함수가 선언된 렉시컬 환경(Lexical Environment)을 함께 기억하는 함수입니다.

틀린 부분

  • "클로저는 항상 return으로 반환될 때 생성된다"는 오해
    • 클로저는 **반환(return)**에 국한되지 않습니다. 외부 변수의 참조가 지속되는 모든 상황에서 클로저가 생성됩니다. 반환 외에도 변수에 저장되거나, 다른 함수로 전달되거나, 이벤트 리스너로 등록될 때도 클로저가 형성됩니다.

채워 넣어야 하는 부분

  • 실제 클로저의 활용 예시
    • 설명에는 클로저가 어떻게 사용되는지 명확한 예시가 부족합니다. 클로저는 실무에서 다음과 같은 상황에 사용됩니다:
      • 데이터 캡슐화 및 정보 은닉: 외부에서 접근할 수 없는 private 데이터를 유지하기 위해 사용.
      • 이벤트 핸들러 및 콜백: 상태를 유지하면서 비동기 작업을 처리.
      • 함수 커링: 파라미터 일부를 고정시켜 새로운 함수를 생성.
      • 예시 코드를 추가하는 것이 이해를 돕는 데 유용합니다.
  • GC 관련 해결책 추가
    • 클로저로 인한 메모리 누수를 방지하는 방법은 단순히 null을 할당하는 것 외에도 여러 방법이 있습니다:
      • WeakMap 또는 WeakSet을 사용해 참조를 약하게 만들어 GC가 대상 객체를 해제할 수 있도록 유도.
      • 함수 설계에서 불필요한 참조를 피하고, 클로저 사용을 최소화하거나 명시적으로 해제.

수정된 설명과 코드 예제

정확한 설명

클로저란? 클로저는 함수와 그 함수가 선언된 렉시컬 환경(Lexical Environment)의 조합입니다. 클로저는 내부 함수가 외부 함수의 변수에 접근하고, 외부 함수가 실행된 후에도 이 변수를 유지할 수 있는 메커니즘입니다. 클로저는 반환(return), 변수 저장, 콜백 전달 등 다양한 방식으로 형성될 수 있습니다.

GC 관련 메모리 누수 방지

  • 클로저를 사용할 때 참조를 명시적으로 해제하거나, 약한 참조를 활용해 메모리 누수를 예방할 수 있습니다.