Javascript - 클로저

박한솔·2021년 6월 7일
0
let number = 0;
function sum (n){
  return number + n;
}

console.log(

number가 있고 number에 n을 더해주는 함수가 있다. number는 전역에 나와있어서 console.log를 통해 직접 값을 확인할 수 있다.
하지만 number를 비밀유지를 위해서 숨겨야 할 때가 있을것이다.

또한 계산을 간결하게 묶어주고 싶은 순간이 있다. 이 것을 해결해주는 함수가 클로저 함수다.

Closure

클로저는 함수와 함수가 선언된 어휘적(lexical) 환경의 조합...이라고 MDN은 설명하고 있다.
하지만 어휘적 환경? 너무 정의가 어렵다. 그래서 이렇게 더 간단하게 설명할 수 있다.

내부함수가 외부에 선언된 변수에 접근할 수 있는 것
즉 외부함수에 접근할 수 있는 내부함수

그렇다면 왜 lexical 환경이라고 쓰게 되었을까?

함수와 함수가 선언된 어휘적 환경의 조합

여기서 함수는 외부함수가 아닌 내부함수를 의미한다. 그리고 lexical 환경이라는 것은 내부함수가 선언되었을 때의 스코프를 의미한다.
내부함수는 자신의 스코프(전역변수, 외부함수 등등)에 있는 변수를 참조할 수 있다.

가장 간단한 예시이다.

function addText(){
  let firstText = "hello"
  let nextText = function(next){
    return firstText + next;
  }
  return nextText
}

let hello = addText();
console.log(hello(" 영희")) // "hello 철수"
console.log(hello(" 철수")) // "hello 영희"
console.log(fisrtText); //Uncaught ReferenceError: fisrtText is not defined

예시를 보듯이 가장 대표적인 클로저 사용의 이유는 3가지이다.

캡슐화은닉화, 그리고 변수 저장

캡슐화

복잡한 계산식이 있다고 가정한다. 그리고 그 계산은 매우 자주 쓴다고 생각한다면, 계산식을 사용하기 앞서서 하나로 묶어준다면 이용하기 쉽게 사용할 수 있다.

위의 예시에서도 hello를 정의하고 addText를 넣어줌으로써 내부함수의 복잡한 과정을 간략하게 정리해주었다.

이렇게 기능을 하나로 묶어주는 캡슐화를 통해서 코드를 간결하게 짤 수 있게 도와준다.

은닉화

세번째 console.log를 주목해보자. firstText는 외부에서는 읽을 수가 없다. 함수 내에서 정의된 변수이기 때문이다. 따라서 저 변수는 함수를 뜯어보지 않는 이상은 확인할 수 없다.


function makeSalted(){
  let salt = "Iloveyou";
  let merged = function(text){
    return salt + text
  }
  return merged
}

만약 위의 예시가 아닌 salt를 더하여 해쉬값을 만드는 함수라면 salt라는 값은 절대 전역변수에 두면 안된다. 자칫하면 비밀정보가 드러날 수 있기 때문이다. 그래서 클로저 내에 두게 된다면 salt값을 효율적으로 숨길 수 있게 된다.

이처럼 클로저는 전역변수의 남용으로 인한 보안위험을 줄이고 효과적으로 변수를 은닉할 수 있는 기능을 제공한다.

변수의 저장

function count(){
  let data = 0;
  let clicked = function(){
    data++;
    return data;
  }
  return clicked
}

let clickCount= count();
console.log(clickCount());// 1
console.log(clickCount());// 2
console.log(clickCount());// 3

내부함수 clicked는 data의 값을 기억하고 있다. 따라서 초기화가 되는 것이 아니라 계속해서 더해주게 된다.

이것을 응용하면 toggle 기능도 만들 수 있게 된다.

function toggleButton(){
  let data = false;
  let clicked = function(){
   data?data = false:data = true;
    return data;
  }
  return clicked
}

let onClick = toggleButton();
console.log(onClick()); //true
console.log(onClick()); //false

//이 것을 통해 버튼 클릭 상태를 제어할 수 있다.
profile
치열하게, 하지만 즐겁게

0개의 댓글