[자바스크립트] 클로저

Megan·2023년 11월 9일
0
post-custom-banner

클로저를 이해하기 위한 개념

렉시컬 환경
해당 개념을 모르신다면 실행 컨텍스트 포스팅을 먼저 읽는 것을 추천드립니다!
실행 컨텍스트 포스팅 바로가기

클로저

1.외부 함수보다 오래 유지되어
2.생명 주기가 끝난 외부 함수의 변수를 참조하고 있는 중첩 함수


예제


function coffeeMachine() {
  let coffeeBeans = 10;

  const makeCoffee = () => {
    if (coffeeBeans < 4) {
      console.log('원두가 부족합니다');
      return;
    }

    coffeeBeans -= 4;
    console.log('커피 한 잔을 만들었습니다.');
  };

  const checkCoffeeBeans = () => {
    console.log(`현재 남아 있는 원두는 ${coffeeBeans}g 입니다.`);
  };

  const fillCoffeeBeans = (gram) => {
    coffeeBeans += gram;
    console.log(
      `원두 ${gram}g을 채웠습니다. 현재 남아 있는 원두는 ${coffeeBeans}g 입니다.`,
    );
  };

  return {
    makeCoffee,
    checkCoffeeBeans,
    fillCoffeeBeans,
  };
}

const coffeeMachine1 = coffeeMachine();

coffeeMachine1.checkCoffeeBeans();
//현재 남아 있는 원두는 10g 입니다.
coffeeMachine1.makeCoffee();
//커피 한 잔을 만들었습니다.
coffeeMachine1.checkCoffeeBeans();
// 현재 남아 있는 원두는 6g 입니다.
coffeeMachine1.fillCoffeeBeans(10); 
//원두 10g을 채웠습니다. 현재 남아 있는 원두는 16g 입니다.

예제에서 coffeeMachine의 생명 주기는 끝났지만 반환된 메서드들을 통해서
coffeeMachine 함수 내부의 coffeeBeans 변수에 접근 가능한 것을 확인할 수 있습니다.

이처럼 외부 함수보다 오래 살아남아 외부 함수의 변수를 참조하는 함수를 클로저라고 부릅니다.

리액트를 사용하시는 분들은 익숙하실텐데 사실 저렇게 함수를 반환하는 것은 훅과 비슷하죠.
useState훅도 클로저를 사용한 예 중에 하나입니다.
또, 커스텀 훅을 만들 때 자연스럽게 클로저를 사용하고 있었던겁니다.

그래서 클로저랑 렉시컬 환경이랑 무슨 관련인가?

MDN에서는 클로저에 대해 이렇게 정의했습니다.

클로저는 함수와 그 함수가 선언된 렉시컬 환경과의 조합이다.

렉시컬 환경은 식별자와 스코프를 관리하는 자료구조로 실행 컨텍스트를 구성하는 컴포넌트입니다.

실행컨택스트는
렉시컬 환경으로 식별자와 스코프를 관리하고,
실행 컨텍스트 스택으로 코드 실행 순서를 관리합니다.

함수의 실행이 종료되면 함수의 실행 컨텍스트가 컨텍스트 스택에서 제거됩니다.
하지만 예제처럼
1. 반환된 내부 함수가 전역 변수에 의해 참조되어 외부함수보다 오래 생존하는 상태이고
2. 내부 함수가 외부 함수의 변수를 참조하고 있다면 외부 함수의 렉시컬 환경은 유지됩니다.

렉시컬 환경에는 외부 렉시컬 환경에 대한 참조를 저장하기 때문에
상위 스코프를 참조할 수 있고, 상위 스코프의 식별자를 참조할 수 있습니다.

이처럼 실행 컨텍스트에 대한 이해를 바탕으로 클로저의 원리를 이해할 수 있습니다.

클로저는 왜 사용할까?

캡슐화와 정보 은닉을 위해 사용합니다.

위의 예제에서는 coffeeMachine이라는 함수 안에 coffeeBeans와 관련된 함수들을 묶어서 캡슐화 하고 offeeBeans에 대한 접근을 막기 위해 특정 함수에게만 상태 변경을 허용했습니다.

이처럼 클로저를 사용하면 내부 구현 사항을 숨기고 외부에서 직접적으로 변수에 접근할 수 없게 만들 수 있습니다.

profile
프론트엔드 개발자입니다
post-custom-banner

0개의 댓글