클로저 (closer)

심서현·2022년 11월 18일
post-thumbnail

클로저는 어떤 함수가 자신의 내부가 아닌 외부에서 선언된 변수에 접근하는 것이다.

면접을 보러 다니면서 클로저에 관한 질문을 자주 접했고, 답변을 하며 클로저에 대한 지식이 많이 부족하다는 것을 느끼게 되었다.

그래서 오늘은 클로저에 대해 정리하는 시간을 가져보고자 한다.




클로저

클로저는 외부 변수를 기억하고 외부 변수에 접근할 수 있는 함수를 의미한다.
자바스트립트의 렉시컬 환경은 외부 렉시컬 환경을 가리키는 outer가 존재한다.

  • 자바스크립트는 *렉시컬 스코프를 따르므로 식별자가 현재 스코프에 존재하지 않으면 선언된 위치를 기준으로 외부 환경에서 해당 변수를 찾는다.

  • 결과적으로 자바스크립트의 함수는 모두 클로저이다.


렉시컬 스코프(Lexical scope)?

프로그래밍에서 scope란 변수의 유효범위를 나타내는 용어이다.

자바스크립트는 Lexical scope를 따르고 있는데 이는 함수를 어디서 선언하였는지에 따라 상위 스코프를 결정하는 것이다.
중요한 것은 함수의 호출이 아니라 함수에 선언에 따라 결정된다는 것이다.


자 그럼 이제 다시 클로저로 돌아와 예시 코드를 보며 세부적으로 알아보자.

function outer() {
	const num = 10;
  	return function inner() {
      console.log(num, '이 출력된다.');
    }
}

const result = outer();

result(); // 10이 출력된다.

위 코드에서 result라는 변수에 outer()의 반환값인 새로운 함수 inner()를 담은 후 호출하였더니 num의 값이 없음에도 외부 변수였던 num을 기억하고 10을 출력하였다.

여기서 inner()를 클로저(closer)라고 한다.


클로저는 스코프 체인(scope chain)으로 표현되기도 하는데 크게 3가지 스코프 체인을 가진다.

  • 자신에 대한 접근 (자신의 블럭내에 정의된 변수)
  • 외부 함수의 변수에 대한 접근
  • 전역 변수에 대한 접근




특징

1. 함수를 리턴하는 함수

const adder = function (x) {
  return function (y) {
    return x + y;
  }
}

클로저의 정의로부터 알 수 있듯이 클로저는 리턴 값이 함수의 형태이다.


2. 외부함수의 변수에 접근 가능한 내부함수

const adder = function (x) { // x는 외부 함수의 변수이다.
  return function (y) { // y는 내부 함수의 변수이다.
    return x + y;
  }
}
  • 리턴하는 함수에 의해 스코프가 분리되어 있으며, 내부 함수는 외부 함수에 선언된 변수에 접근이 가능하다.
  • 스코프를 이용해 변수의 접근 범위를 닫아 폐쇠할 수 있다. (closer)
  • 내부함수는 클로저에 의해 변수 x를 참조할 수 있다. 이렇게 참조된 변수 x를 자유변수라고 한다.




활용

데이터 보존

일반적으로 함수는 실행이 끝나면 내부 변수를 사용할 수 없다.
그러나 클로저 함수는 외부함수의 실행이 끝나도 외부함수 내 변수가 렉시컬 환경에 저장되기 때문에 외부함수의 변수를 사용할 수 있다.

따라서 외부함수의 변수가 가비지 컬렉션에 포함되지 않아 데이터가 보존된다.


클로저를 통한 은닉화

클로저는 내부에서 외부 함수의 변수를 참조하기 때문에 외부 함수에서 외부 함수의 변수를 참조할 수가 없다.

따라서 클로저를 사용하여 외부에서 변수에 직접 접근하는 것을 제한하는 은닉화가 가능하다.


정보의 접근 제한 (캡슐화)

클로저 활용 시 내부 함수를 객체에 담아 여러개 리턴이 가능하다.

const makeCounter = () => {
  let value = 0;
  
  return {
    increase : () => {
      value = value + 1;
    },
    decrease : () => {
      value = value - 1;
    },
    getValue : () => value
    },
}
  
const counter1 = makeCounter();
counter1 //{increase: f, decrease: f, getValue: f}

counter1 : 함수를 여러개 포함한 객체
캡슐화 : makeCounter 함수를 바뀌지 않고 변수 value에 새로운 값 할당 불가능
*스코프 규칙 : 외부 스코프는 내부 스코프에 접근 불가

리턴하는 객체를 활용해 value 값을 조작해야 하기 때문에 캡슐화이다.


모듈화

클로저는 함수 하나를 완전히 독립적인 형태로 분리하여 재사용성을 극대화 할 수 있다.

profile
안녕하세요?

0개의 댓글