티스토리 뷰
1. 클로저란?
1.1 클로저 정의
- 클로저 : 함수와 그 함수가 선언될 당시(outer Environment reference)의 lexical environment의 상호관계에 따른 현상(MDN) 즉, inner function에서 outer function의 lexical에 접근하는 경우에 대한 현상이다.
- 사전적 의미: 닫혀있음, 폐쇄, 완결 등의 의미이다.
- 함수형 프로그래밍에서 보편적으로 나타난다. 그래서 ecma 명세에도 클로저를 따로 다루지 않는다.
- 컨텍스트 A에서 선언한 내부함수 B의 실행컨텍스트가 활성화될 때, A는 B의 lexical에 접근할 수 없지만, B는 A의 lexical에 접근 가능하다.
- 선언시 만들어지는 유효범위가 사라진 후에도 호출을 할 수 있는 함수.
1.2 inner함수 자체를 반환하면서 외부 참조에 대한 그 당시의 상황 그대로를 가져간다.
1.3 동작원리
- 가비지 컬렉터는 어떤 값을 참조하는 변수가 하나라도 있으면 수집 대상에 포함시키지 않는다. 그런데, inner는 외부를 참조하고 있으니 inner가 남아있는 한, outer의 lexical을 지우지 않는 것이다.
1.4 명확한 정의
- 클로저: 어떤 함수 A에서 선언한 변수 a를 참조하는 내부함수 B를 외부로 전달할 경우 A의 실행 컨텍스트가 종료된 이후에도 변수 a가 사라지지 않는 현상.
** 외부 전달이 return만 있는 것은 아니다.
- setInterval이나 addEventListener를 할 때, 콜백함수가 외부의 변수를 참조하는 경우가 많다. 이럴 때, closure가 일어나는 것이다.
2. 클로저와 메모리
2.1 클로저는 메모리 누수를 일으킬 수도 있다. 그러나 안 쓸 수는 없기에, 주의해서 설계해야 한다.
2.2 클로저의 관리 방법: 식별자에 참조형이 아닌 기본형 데이터를 할당하면, 메모리 해제를 할 수 있다..??
- 외부 변수를 inner에서 return을 하고 outer를 null로 만드는 방법 (함수 자체 return으로 구현하는 경우)
- inner를 inner내부에서 null로 만드는 방법으로 해제 가능하다.
3. 클로저 활용 사례
3.1 콜백함수 내부에서 외부데이터를 사용
- 콜백함수를 외부에 따로 두는 경우 this가 addEventListener가 된다. 그래서 bind를 해줘야되는데, bind는 이벤트 리스너를 잘 동작하지 못하게 할 수 있다. 그래서 고차함수를 사용해야한다. 고차함수는 함수를 인자로 받거나 함수를 리턴하는 함수이다. 즉, 인자로 받은 다음에 그 내부에 함수를 정의하고 그 내부함수 자체를 리턴하는 방식으로 해야한다는 것이다.(alertFruitBuilder 예제)
3.2 접근권한 제어
- 객체지향 언어에는 보통 접근제어자가 있는데, 자바스크립트에는 없다. 그래서, private+getter setter의 역할을 하게끔 closure로 구현할 수 있다.
- outer변수를 inner가 return을 해주고 outer가 inner를 리턴해주면? 원래는 outer의 내부선언 변수들은 외부에서 사용 못한다. 그런데, 이렇게 하면 외부에서 사용 가능하다.(like getter) 즉, outer의 실행당시에 내부에서 정의했던 변수들을 return해주는 함수를 따로 지정하여, 그 변수들을 재활용할 수 있게하는것이다.
- 자바스크립트의 class를 사용하지말고, 함수의 outer.a 이런식으로 원래 사용못하는 원리를 활용해서, private(함수 내부의 변수 직접 참조 불가능한 원리)+getter setter를 지정하는 방식으로 사용을 하자는 것이다.
3.3 부분적용 함수(partially applied function)
- 부분적용 함수: n개(n>m)의 인자를 받는 함수에 미리 m개의 인자만 넘겨서 기억 시켰다가 나중에 나머지를 로 보내는 함수
- bind와 arguments활용의 방법이 있다.(3.1의 bind 예제처럼 this에 관여하는 측면에서 좋지 않음)
- partial 함수를 add를 인자로 받게 적용하는경우.
- 이렇게 복잡하게 사용하나? 싶었는데, debounce에서 활용한다.
- Debounce: 짧은 시간동안 동일한 이벤트가 많이 발생하는 경우, 이를 전부 처리하지 않고, 앞또는 뒤 이벤트에 대해 나눠서 처리하는 것이다. 프론트 엔드 성능 최적화의 중요한 개념이다.
- 키보드 입력마다 필터링하는 예제의 경우 debounce를 활용하여 최초 이벤트 발생시(다시 발생하면 reset) 일정 시간동안 이벤트를 리슨하지 않고(setTimeout) 시간이 지나고 나서 마지막 입력값에 대해서만 listen하게 만들 수 있다. 실시간 검색에 활용될 수 있다.(네이버 이메일 참고)
3.4 커링 함수(currying function)
- 커링함수: 여러개의 인자를 받는 함수를 하나의 인자만 받는 함수로 나눠서 순차적으로 호출될 수 있게 chain 형태로 구현하는 것. 부분 적용함수와 가장 큰 차이점은 한번에 하나만 전달하는 것을 원칙으로 한다. 또한, 중간 과정의 결과는 활용되지 않고 최종결과만 활용된다. 중간 결과는 최종결과를 위해 존재할 뿐이다. 함수가 내부의 함수를 리턴하고 그 내부가 리턴하는 방식으로 구현되기 때문에, currying(func)(a)(b)이런 식으로 호출된다.
- 화살표 함수에서 const currying = func => a => b => c=> d 이런 식으로 함수 선언을 한다.
- 이것도 복잡해서 어디에 쓰나? 싶었는데, lazy excution에서 활용한다.
- const getInformation = baseUrl => path => id => fetch(baseUrl+path+'/'+id);
const getUser = getInformation("bomsbro.com");
const getId = getPath("/user");
const id = getId(bomsbro);
- 이런 식으로 어떤 값을 구하기 위해 값들이 많이 필요한데, 구현 중간과정에서 잘 바뀌지 않는 것들을 앞에 배치하고 그 뒤에 자주 변하는 것들을 배치해서 사용하는 방법이다.
정리: 클로저는 내부함수를 외부로 전달하는 경우 외부의 컨텍스트가 종료되어도 변수가 남아있는 현상을 말한다. return과 callback의 형태가 있다. 메모리를 계속 차지하니까 관리를 잘해줘라. 여러 중요한 곳에서 활용된다.
'FE > JavaScript 팔아요' 카테고리의 다른 글
[Note_코어자바스크립트] 7장 클래스 [완] (0) | 2022.01.13 |
---|---|
[Note_코어자바스크립트] 6장 프로토타입 (0) | 2022.01.11 |
[Note_코어자바스크립트] 4장 콜백 함수 (0) | 2021.12.28 |
[Note_코어자바스크립트] 3장 this (0) | 2021.12.21 |
[Note_코어 자바스크립트] 2장 실행 컨텍스트 (0) | 2021.12.13 |