문법 - 클로저

bery·2021년 10월 3일
0
post-thumbnail

어떤 함수를 호출할 때마다 1씩 증가하는 숫자를 리턴하는 함수를 만든다고 해보자.

어떻게 만들면 될까?

일단 1씩 증가하는 숫자라고 하는 건 만약에 한 번 호출하면 1이 나오고, 그다음 호출하면 2가 나오고, 그다음 호출하면 3이 나오면 된다. 그렇다면 바로 이전에 돌려줬던 값을 그 함수가 기억하고 있어야 할 것이다. 호출했을 때 4를 준다는 건 4를 주기 전에는 3이었다는 이야기이다. 그러니까 그 이전에 돌려줬던 값을 저장할 변수가 필요할 것이다.

변수를 한 번 만들어보자.

호출하면 증가된 값을 돌려주고, 1씩 증가시키게 된다.

잘 작동하는지 console.log를 이용하여 확인해보자

1, 2, 3 3번 호출했으니까 1, 2, 3 호출이 잘 되었다.

그런데 이 코드의 문제점이 뭘까??

여기서 두 번째 호출하고 나서, 어딘가에서 saveNumber에 200을 넣었다.

그리고 다시 한번 실행해 보면 1, 2, 200 이 나온다.

이 saveNumber를 보호하고 있지 못하는 것이다. increment 함수 입장에서는 마지막에 분명히 2까지 증가시키고 3이었을 텐데, saveNumber를 강제로 다른 곳에서 200으로 바꿔 버린 것이다.

그렇다면 이것을 못 하게 보호해 줘야 될 텐데 increment 함수는 그런 역할이 불가능하다.

왜 이런 문제가 생기는 것일까?

이 saveNumber가 모두에게 알려져 있기 때문에, 어디에서나 접근 가능한 상태이기 때문에 그렇다.

언제나 실수는 의도치 않게 일어난다. 이것을 원천적으로 바깥쪽에서는 접근하지 못하도록 만들어 주는 방법이 필요하다.

saveNumber를 함수 안쪽으로 옮기면 함수 바깥쪽에서는 접근할 수가 없게 된다. 일단 함수 안쪽으로 넣어 보자.

이렇게 넣으면 어떤 문제가 생길까?
값이 증가하지 않는다.
이럴 때 사용하는 자바스크립트 특유의 방법이 있다.

지금은 값 자체를 반환하고 있는데, 값을 반환하는 게 아니라 함수를 리턴해 주는 것이다.
지금은 값 자체를 반환하고 있지만, 이 값을 함수로 감싸서 반환을 시키는 것이다.

이렇게 됐으면 increment를 호출하면 함수가 반환된다. 함수는 값이 아니니까 호출해야 값이 나올 수 있다.
그래서 반환된 함수를 변수에 한번 저장을 해 보자. 나중에 호출을 연속해서 할 수 있도록!

inc라는 변수를 하나 만들고 여기에 increment 함수를 호출한다.

그래서 inc를 호출하여 실행하면 1, 2, 3이 잘 작동되는 걸 확인할 수 있다.

그런데 어떻게 작동이 되는 걸까?

분명히 increment를 호출하면 saveNumber 1을 세팅하고 나서 함수를 리턴했다.
리턴을 하면 함수 안에 들어가 있는 지역 변수는 사라지기 때문에 위의 변수 saveNumber는 사라진다.
그래서 다시 inc 함수를 호출하면 사라진 saveNumber가 어떻게 되살아나서 1, 2, 3 이런 식의 값을 반환하게 되는 걸까?

이것이 클로저라고 하는 것의 핵심이다.

클로저라고 하는 것은 함수 안쪽에서 함수가 만들어질 때,
increment가 호출되면 increment 안에 들어와서 함수가 반환하기 위해서 새로 만들어지는데, 이렇게 만들어지는 상황에서 함수 안쪽에 있는 코드 중에 바깥 함수에 있는 변수에 접근을 하게 되면, 이 접근한 변수를 클로저라고 하는 특별한 공간에 저장을 해 둔다.

그러고 나서 이 함수가 반환을 하면 이 saveNumber가 있던 increment 함수의 지역 공간은 사라져서 이 안쪽 함수가 만들어지면서 옮겨졌던 클로저라는 공간에는 여전히 saveNumber가 유지되고 있는 것이다.

그래서 이 increment 함수가 호출될 때 saveNumber는 위쪽에 사라진 increment의 로컬 공간에서 찾는 것이 아니라 클로저 공간에서 찾아서 저장된 값을 유지하면서 반환할 수 있게 되는 것이다.

특수한 공간 안에 바깥쪽에 있던 변수를 마치 가둬놓듯이 가둬놓을 수 있는 것이 바로 클로저라고 하는 공간이다.

이 코드를 다시 한번 살펴보자.

이 코드에서 클로저를 썼을 때 장점이 뭐가 있을까?
지금 함수가 리턴돼도 특정 값을 보호하면서 그 값을 계속 사용할 수 있다는 장점이 생겼다.

그렇기 때문에 saveNumber가 1, 2, 3 이렇게 증가하는 것이다.

또한 그 변수를 보호했기 때문에 바깥쪽에선 어떤 방법으로든 saveNumber에 접근할 수 없다.
클로저 공간은 코드 상에서 접근을 할 수가 없다. 바깥 공간에서는!
클로저 공간 안에 있는 변수를 접근할 수 있는 유일한 길은 바로 클로저를 만든 함수 안의 코드이다.

이 코드는 실행하는 순간, 런타임 상황에서는 바꿀 수가 없기 때문에 클로저는 완벽하게 보호되는 공간이다.

그래서 보호되어야 하는 값이 필요하다면 클로저 공간에 넣는 것들을 많이 사용하게 된다.

타입스크립트라면 아주 간단하다. 객체의 어떤 속성을 보호하고 싶다면 앞에 private라고 써주면 된다.

자바스크립트같은 경우는 저런 스펙이 없기 때문에 클로저라는 특별한 기능을 이용해서 값을 보호할 수 있게 되는 것이다.

0개의 댓글