Javascript Closure

Kingmo·2022년 4월 17일
0

1. Closure(클로저)

클로저내부함수외부함수의 context에 접근할 수 있는 것을 가르킨다.
여기서 context는 한국말로 직역하면 문맥이란 뜻으로 쉽게 코드의 실행 환경이라 이해하면 된다.

클로저내부함수외부함수실행 환경에 접근할 수 있는 것을 가르킨다라고 생각하면 된다.


2. 클로저 이해하기

먼저 클로저를 이해하고, 사용하기 위해서는
전역변수지역변수그리고
scopelexical scoping(렉시컬 스코핑)대한 이해가 필요하다.
필요한 개념 : Scope


2-1. 전역변수

전역변수는 해당 컴포넌트 혹은 페이지 안이라면
스크립트 영역 어디서든 사용할 수 있는 변수를 의미한다.


2-2. 지역변수

지역변수는 함수 안에서 정의된 변수로써,
해당 함수 안에서만 사용되는 변수를 의미한다.
보통 블록{}안이나, 함수 안에서만 변수에 접근할 수 있다.


2-3. 렉시컬 스코핑(lexical scoping)

스코프에 대해 어느 정도 알고 있다면 꼭 알아둬야 할 사항이 있다.
스코프는 함수를 호출할 때가 아니라 선언할 때 생긴다는 것을 꼭 알아야한다.
이는 정적 스코프라고도 불린다.

다음 코드의 결과를 예상해보자

let name = 'kingmo'
function log() {
	console.log(name)
}

function wrapper() {
	name = 'haha'
  	log()
}
wrapper()

wrapper()를 호출하면 콘솔에 'haha'가 찍힌다.
이는 간단하다 호출하기 전에 name을 'haha'로 바꿨기 때문이다.

그렇다면 다음 코드를 봐보자.

let name = 'kingmo'
function log() {
	console.log(name)
}

function wrapper() {
	let name = 'haha'
    log()
}
wrapper()

여기서는 wrapper()의 호출결과는 어떻게 될까?
똑같이 'haha'가 나올까?
아니다 콘솔에는 'kingmo'가 찍힌다.
스코프는 함수를 선언할 때 생기기 때문에
log()함수 안의 namewrapper()안의 지역 변수 name이 아니라
전역변수 name을 가리킨다.
이런 것을 lexical scoping(렉시컬 스코핑)이라 한다.

이를 이해하기 쉽게 다시 설명하자면
함수를 처음 선언하는 순간, 함수 내부의 변수는
스코프 체인에 의해서 자기 스코프와 가장 가까운 상위 범위의 변수를 참조한다.

따라서 log()함수 안의 name 변수는 선언 시
가장 가까운 전역변수 name을 참조한다.

그래서 wrapper()함수 안에서 log를 호출해도
지역변수 name = 'haha'를 참조하는 것이 아니라
전역변수 name = 'kingmo'를 참조하는 것이다.


2-4. 모듈 패턴

자바스크립트 코드로 협업할 때에 전역변수를 만드는 일은 최대한 지양해야한다.
그 이유는 변수가 섞일 수 있고, 우연의 일치로 같은 변수 이름을 사용해서
기존의 변수를 덮어쓰는 불상사가 발생할 수 있기 때문이다.

ES6에서 var보다 let, const으로 변수를 선언하는 것도
위와 같은 이유 때문이다.

여기서 애초에 함수 내에서 변수를 선언해서
그 함수를 호출하기 전에는 선언조차 되지 않도록
변수를 비공개하는 방법도 있다.

다음과 같은 코드에서

let another = function () {
  let x = 'local';
  function y() {
    alert(x);
  }
  return { y: y };
}
let newScope = another();

newScope는 선언과 동시의 another의 리턴 값으로 할당 된다.
여기서 return 되는 값은 { y: function() { alert('local') } }으로
newScope라는 네임스페이스(변수이름)을 통해
변수 y에 접근할 수 있지만 변수 x에는 접근할 수 없다.

여기서 y를 공개변수 x를 비공개 변수라 볼 수있다.
다른 언어와는 달리 자바스크립트에는 자바의
private, protected과 같이 함수를 비공개하는 별도의 문법이 없기 때문에
위와 같은 방법으로 비공개 변수 기능을 만들어 사용할 수 있다.
이러한 패턴을 모듈 패턴이라고도 한다.


다음과 같은 코드에서

function aaa() {
	let apple = "이건 사과에요"
    
    return function bbb() {
    	let banana = "이건 바나나에요"
        console.log("안녕하세요")
      	console.log(apple)
      	console.log(banana)
    }
}

aaa()함수를 호출하면 bbb()함수를 리턴하는데
여기서 aaa()()으로 bbb()함수까지 한방에 리턴할 수 있다.

console.log(apple)에 주목하자.
여기서 변수applebbb()함수의 내부에서 생성한 변수도 아니고,
aaa()함수의 매개변수도 아니다.
이런 apple과 같은 변수가 바로 위에서 말한 비공개 변수이다.

그리고 위와 같은 문이 바로 클로저이다.
내부 함수 bbb()가 외부 함수 aaa() 환경에 접근해 이건 사과에요라는 콘솔을 출력하는 것을 볼 수있다.

클로저비공개 변수를 만들어서 활용하기 때문에
사용자의 접근을 막아 사용자가 해킹이나 프로그램에 버그를 만드는 것과 같은
예상을 뒤엎는 행동을 하는 것을 막을 수있다.

때문에 클로저는 자바스크립트에서 사용자를 통제하기 위한 기본적인 방법으로 활용된다.


참조 1

참조 2

profile
Developer

0개의 댓글