옹재
소소한 개발 블로그
옹재
전체 방문자
오늘
어제
  • 분류 전체보기 (66)
    • 개발 관련 서적 스터디 (6)
    • 프론트엔드 스터디 (36)
      • Javascript (16)
      • Typescript (13)
    • Vue 스터디 (22)
    • 개발 관련 스터디 (2)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 개발서적 스터디
  • 프론트엔드 스터디
  • CSS
  • 프레임워크 없는 프론트엔드 개발
  • scss

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
옹재

소소한 개발 블로그

프론트엔드 스터디/Javascript

클로저(closure)란???

2021. 7. 13. 13:28
728x90
반응형

클로저(closure)

자바스크립트를 공부하다보면 클로저라는 개념을 자주 보게 되는데, 처음 접했을 때는 closure가 아닌 closer라고 생각했었습니다. 아무튼 클로저는 실행 컨텍스트에 대한 사전 지식이 있어야 이해하기 쉬운 개념이라고 볼 수 있습니다.

개념

클로저는 자바스크립트의 고유 개념이 아니라 함수를 일급 객체로 취급하는 함수형 프로그래밍 언어(얼랭, 스칼라, 하스켈 등..)에서 사용되는 중요한 특성입니다. 클로저에 대해 MDN은 아래와 같이 정의하고 있습니다.

“A closure is the combination of a function and the lexical environment within which that function was declared.”
클로저는 함수와 그 함수가 선언됐을 때의 렉시컬 환경과의 조합입니다.

역시나 어떤 개념이 되든간에 정의를 보고 바로 이해하기란 쉽지가 않은 것 같습니다. 위의 정의에서 중요한 키워드는 "함수가 선언됐을 때의 렉시컬 환경"입니다.

예제를 들어 이해해보도록 합시다.

function outerFunc() {
  var x = 10;
  var innerFunc = function () { console.log(x); };
  innerFunc();
}

outerFunc(); // 10

위의 코드를 보면 outerFunc내에서 내부 함수 innerFunc가 선언되고 호출되었습니다. 이때 내부함수 innerFunc는 자신을 포함하고 있는 외부함수 outerFunc의 변수 x에 접근할 수 있습니다.

스코프는 함수를 호출할 때가 아니라 어디에서 선언하였는지에 따라 결정됩니다. 이를 렉시컬 스코핑이라 합니다.

이를 실행 컨텍스트의 관점에서 살펴보면 내부함수가 호출되면 자신의 실행 컨텍스트가 스택에 쌓이고 vo와 스코프체인, this에 바인딩할 객체가 결정됩니다. 이때 스코프 체인은 전역 스코프를 가리키는 전역 객체와 외부 함수의 스코프를 가리키는 외부 함수의 활성 객체 그리고 자신의 스코프를 가리키는 활성 객체를 순차적으로 바인딩합니다.

내부함수가 자신을 포함하고 있는 외부함수의 변수 x에 접근할 수 있는 것, 다시 말해 상위 스코프에 접근할 수 있는 것은 렉시컬 스코프의 레퍼런스를 차례대로 저장하고 있는 스코프 체인을 검색하였기에 가능합니다.

이번에는 내부함수를 상위 함수 내에서 호출하는 것이 아니라 반환하도록 변경해보겠습니다.

function outerFunc() {
  var x = 10;
  var innerFunc = function () { console.log(x); };
  return innerFunc;
}

/**
 *  함수 outerFunc를 호출하면 내부 함수 innerFunc가 반환된다.
 *  그리고 함수 outerFunc의 실행 컨텍스트는 소멸한다.
 */
var inner = outerFunc();
inner(); // 10

이렇게 되면 outerFunc()가 innerFunc를 반환하고 스택에서 제거되었으므로 변수 x에 접근할 수 있는 방법이 없어보입니다. 하지만 코드를 실행해보면 10이 출력됩니다.

이처럼 자신을 포함하는 외부함수보다 내부함수가 더 오래 유지되는 경우, 외부 함수 밖에서 내부함수를 호출되더라도 지역 변수에 접근할 수 있는데 이러한 함수를 콜로저라고 부릅니다.

위의 정의를 다시 살펴보면 함수란 반환된 내부함수를 그 함수가 선언될 떄의 렉시컬 환경이란 내부 함수가 선언됐을 때의 스코프를 의미합니다. 즉, 클로저는 반환된 내부함수가 자신이 선언됐을 때의 환경인 스코프를 기억하여 환경 밖에서 호출되어도 그 환경에 접근할 수 있는 함수를 말합니다. 더 쉽게 말하자면 자신이 생성될 때의 환경을 기억하는 함수라고 기억하면 될 것 같습니다.

클로저에 의해 참조되는 외부함수의 변수를 자유 변수라고 부릅니다. 클로저라는 이름은 자유변수에 엮여있는 함수라는 뜻입니다.

closure

위의 그림을 보면 외부함수가 종료하여 외부함수의 실행 컨텍스트가 반환되어도 활성 객체는 내부함수에 의해 참조되는 한 유효하여 스코프 체인을 통해 참조할 수 있습니다. 외부함수가 반환되었어도 외부함수 내의 변수는 이를 필요로 하는 내부함수가 하나 이상 존재하는 경우 계속 유지됩니다.

활용

그럼 이 클로저를 어디서 사용할 수 있을까? 잘못사용하면 함수가 생성될 때를 기억하고 있어야하므로 메모리적으로 낭비가 될 수 있습니다.

상태 유지

현재 상태를 기억하고 변경된 최신 상태를 유지하는 것입니다.

<!DOCTYPE html>
<html>
<body>
  <button class="toggle">toggle</button>
  <div class="box" style="width: 100px; height: 100px; background: red;"></div>

  <script>
    var box = document.querySelector('.box');
    var toggleBtn = document.querySelector('.toggle');

    var toggle = (function () {
      var isShow = false;

      // ① 클로저를 반환
      return function () {
        box.style.display = isShow ? 'block' : 'none';
        // ③ 상태 변경
        isShow = !isShow;
      };
    })();

    // ② 이벤트 프로퍼티에 클로저를 할당
    toggleBtn.onclick = toggle;
  </script>
</body>
</html>

전역 변수 사용 억제

<!DOCTYPE html>
<html>
  <body>
  <p>클로저를 사용한 Counting</p>
  <button id="inclease">+</button>
  <p id="count">0</p>
  <script>
    var incleaseBtn = document.getElementById('inclease');
    var count = document.getElementById('count');

    var increase = (function () {
      // 카운트 상태를 유지하기 위한 자유 변수
      var counter = 0;
      // 클로저를 반환
      return function () {
        return ++counter;
      };
    }());

    incleaseBtn.onclick = function () {
      count.innerHTML = increase();
    };
  </script>
</body>
</html>
728x90
반응형

'프론트엔드 스터디 > Javascript' 카테고리의 다른 글

자바스크립트에서 객체지향 프로그래밍이란?  (0) 2021.07.14
자바스크립트 core 개념 간단 정리  (0) 2021.07.13
자바스크립트 실행 컨텍스트  (0) 2021.07.12
자바스크립트에서 scope란?  (0) 2021.07.12
Prototype이란?  (0) 2021.07.12
    '프론트엔드 스터디/Javascript' 카테고리의 다른 글
    • 자바스크립트에서 객체지향 프로그래밍이란?
    • 자바스크립트 core 개념 간단 정리
    • 자바스크립트 실행 컨텍스트
    • 자바스크립트에서 scope란?
    옹재
    옹재

    티스토리툴바