[Javascript] 클로저(Closure)란?

곽태민·2023년 4월 20일
0

TIL

목록 보기
13/65
post-custom-banner

클로저(Closure)란?


Closure는 Javascript 고유 개념이 아니라 함수를 일급 객체로 취급하는 함수형 프로그래밍 언어에서 사용되는 중요한 특성이다. (Erlang, Scala, Haskell, Lisp)

위에서 말하는 함수는 반한된 내부함수를 의미하고, 그 함수가 선언될 때 렉시컬 환경이다. 렉시컬 환경은 내부 함수가 선언됐을 때 스코프를 의미한다.

즉, Closure는 반환된 내부함수가 자신이 선언됐을 때의 환경(Lexical Environment)인 스코프를 기억해서 자신이 선언됐을 때의 환경(스코프) 밖에서 호출이 되어도 그 환경(스코프)에 접근할 수 있는 함수를 말한다.

💡 간단하게 말하면 Closure는 자신이 생성될 때의 환경 (Lexical Environment)을 긱억하는 함수다.

Closure에 의해서 참조되는 외부함수의 변수 즉, OuterFunc 함수의 변수 x를 자유 변수(Free Variable)라고 부른다.

Closure라는 이름은 자유 변수에 함수가 닫혀있다(closed)라는 의미로 자유 변수에 엮여있는 함수라는 뜻이다.

실행 컨텍스트의 관점으로 설명을 해보자, 내부함수가 유효한 상태에서 외부함수가 종료되어 외부함수의 실행 컨텍스트가 반한되어도, 외부함수 실행 컨텍스트 내의 활성 객체(Activation Object) (변수, 함수 선언 등의 정보를 갖고 있음.)는 내부함수에 의해 참조되는 한 유효하여 내부함수가 스코프 체인을 통해 참조할 수 있는 것의 의미한다.

Closure가 필요한 이유?

전역 변수를 줄일 수 있다.

전역변수는 예상치 못한 Side Effect를 일으킬 수 있어서 최대한 줄이는게 좋다. 하지만 프로그램 구현 시 함수 하나에 사용하는 전역변수가 필요한 순간에는 Closure를 이용해서 유용하게 사용하면 된다.

const btn = document.querySelector('button');
btn.addEnventListener('click', handleClick);

let cnt = 0;

function handleClick() {
	cnt ++;
  	return cnt;
}

// 위와 같은 경우는 cnt를 전역변수로 사용해줘야 cnt 증가를 해줄 수 있음.
// 이럴 경우 Closure를 사용해서 해결할 수 있다.

// Closure
const btn = document.querySelector('button');
btn.addEventListener('click', handleClick());

function handleClick() {
	let cnt = 0;
  
  	return function () {
      cnt ++
      return count
    }
}

// 위와 같이 코드를 짜면 외부함수인 handleClick의 Lexical Environment를 참조하는 함수를
// btn의 콜백함수로 이용하여 전역객체 없이 구현할 수 있다.

비슷한 형태의 코드를 재사용성을 높일 수 있다.

// 새로운 태그를 만들 수 있는 함수 Closure 구현
const order = (food) => {
  console.log(food + '을(를) 주문하셨습니다.');
  return function (drink) {
  	return drink + '을(를) 추가로 주문하셨습니다.';
  };
  
  const orderBurgger = order('햄버거');
  const orderPizza = order('피자');
  
  console.log(orderBugger('콜라'));
  console.log(orderPizza('사이다'));
}

인자에 open, close, content를 한번에 다 받는다면, This is my content!와 같은 값을 출력하고 싶을 때 가독성이 떨어질 수 있다.

하지만 Closure로 구현하면 코드 가독성이나 재사용하기 좋은 코드를 구현할 수 있다.

profile
Node.js 백엔드 개발자입니다!
post-custom-banner

0개의 댓글