클로저 ( Closure )

j901207·2021년 1월 12일
1

클로저는 무엇인가?

클로저는 함수와 함수가 연결된 어휘적 환경의 조합이다. - Javascript MDN -

클로저에 대해 검색했을 때, MDN에서 찾을 수 있는 설명이다.
하지만 함수와 함수가 연결(?)된 어휘적 환경(?)이 무엇인지 생각해보자면,

함수와 함수가 연결 => 두 개의 함수 이상이 존재한다..?
어휘적 환경 => 어휘가 뜻하는 내용은 무엇인가...?

단순한 정의만으로 뜻을 파악하기 어려워,
그 예시를 보고 다시 뜻을 살펴보기로 한다.

클로저에 앞서서

클로저를 알아보려면 Javascript에서의
어휘적 범위 지정(Lexical scoping)을 알 필요가 있다.

어휘적 범위 지정은 간단하게
지역변수전역변수로 생각하면 된다.

지역변수와 전역변수에 대한 설명은 생략하고,
필요한 내용을 짚어 보자면, 지역변수는 전역함수에서 그 값을 참조할 수 없는 것이다.

그렇다면,
다음의 예시를 보자.

const makeName = () => { // makeName 선언
    let name = 'Mozila'; // 지역변수
    let displayName = () => alert(name); // 내부함수 displayName 선언
    
    return displayName; // makeName의 return을 displayName 설정
    }

const myName = makeName(); // myName 변수에 displayName을 리턴함

myName(); // myName() 실행 => 'Mozilla'

함수외부에서 선언된 myName이
지역변수 name값을 참조하여 실행할 수 있게 된다.

함수를 변수에 할당함으로써 클로저가 생성된 것이다.

클로저는 이처럼 변수에 함수를 할당하여 그 함수가 실행되어 반환하는 때의 문맥적 상태를 저장하는 역할을 한다.

그렇다면 클로저는 리턴값을 저장하는 것일까?
결론부터 말하자면 아니다.

다음을 살펴보자

const makeAdder = (x) => {
  let y = 1;
  let sum = (z) => {
  	y = 100;
    return x + y + z;
  }
  return sum;
}

var add5 = makeAdder(5);
var add10 = makeAdder(10);
//클로저에 x와 y의 환경이 저장됨

console.log(add5(2));  // 107
console.log(add10(2)); // 112

//함수 실행 시 클로저에 저장된 x, y값에 접근하여 값을 계산

add5add10이라는 변수에 makeAdder에 각각 다른 5,10이라는 값을 할당하여 클로저로 만든 뒤
makeAdder안의 내부함수 sum()에 각각 2라는 값을 할당 해주는 클로저를 호출 하였다.

이미 내부함수에서는 let y = 1 을 통해 값을 할당 하였지만, 클로저의 호출 시 sum이라는 내부 함수가 외부 함수에 접근하여 y 값을 100으로 변경하는 것을 볼 수 있다.

이를 통해 클로저는 생성시기의 함수의 환경을 저장한다고 볼 수 있다.
환경을 저장하기 때문에 private 키워드를 흉내 낼 수 있다.

private keyword의 closure

const increase = () => {
	let count = 0
    return count++;
}
increase();

다음과 같이 increase 함수를 만들고 실행하면 count 라는 변수의 변조를 막을 수 있지만 (함수 내부에 선언 되었기 때문에 외부에서 접근이 불가능), 매호출시의 count값을 0으로 초기화하는 과정을 거치기 때문에 1이라는 return만 얻을 수 있게 된다.

const increase = () => {
	let count = 0;
    return () => {
    	return count++ ;
    }};
 
const incAction = increase();

위와 같이 incAction으로 클로저를 생성하면
지역변수였던 count가 increase()의 scope level
상위 스코프의 자유변수(전역변수와 비슷 한 뜻)로 그 값이 저장되게 된다.

return에 함수를 할당하여 기존에 있던 count라는 변수를 상위함수의 자유변수로 변경해준 것이다.

또한, 하나의 함수에서도 클로저 각각이 각자의 저장 상태를 갖기 때문에 increase함수를 여러가지 변수에 할당 하더라도 각각의 자유변수 값을 저장하게 된다.

const incAction1 = increase();
const incACtion2 = increase();

incAction1() // 1
incAction1() // 2
incAciont2() // 1
incAction1() // 3

이처럼 비슷한 기능을 하는 함수를 리턴하여 사용하는 것을 Closure Moduling이라고 한다.

function adder(x) {
  return (y) => {
    return x + y
  }
}

let adder10 = adder(10);
adder10(2); // 12

let adder100 = adder(100);
adder100(20); // 120

내가 생각하는 클로저

Javascript는 객체 지향 언어로써 각각의 객체가 가지고 있는 역할을 구분하여 할당한다.
이러한 이유로 클로저가 필요할 것이라고 생각한다.

자주 사용하는 기능을 모듈화 하여 재사용하는것이 쉬워진다. (function factory)

0개의 댓글