클로저(closure)는 직역만으론 작동원리를 이해하기 어렵다. 필자 또한 한 번에 이해하기 어려웠다. 크롬 개발자도구에서 지원하는 디버깅 툴을 통해 하나씩 살펴보고 이해했다. (크롬 개발자 도구는 참 많은 걸 지원한다.) 결론부터 말하자면, 클로저는 반환 된 내부 함수가 자신이 선언 되었을 때 환경을 기억하는 함수다.
클로저를 이해해야 하는 이유는 상태 유지, 고차컴포넌트, 매개변수 함수 등을 위해서다. 물론 클로저에 대한 이해가 없이도 어느정도 알 수 있으나, 접근이나 코드가 복잡해지면 길을 잃기 딱 좋아 보인다. 따라서 미리 이해하고 있고자 정리한다.
<!DOCTYPE html>
<html lang="ko">
<head>
<title>Closure</title>
<script>
function aaa() {
const apple = 10;
function bbb() {
const banana = 20;
console.log(banana);
console.log(apple);
console.log(qqq);
}
const qqq = 3;
return bbb();
}
aaa();
</script>
</head>
<body></body>
</html>
위 코드를 실행시키고 개발자도구 소스로 가서 해당 코드 진행 사항을 차근차근히 살펴볼 수 있다. 무엇보다 오른쪽 스코프탭을 통해 클로저 상태도 알 수 있다.
클로저는 스코프 글에서 정리한 렉시컬 스코프의 특징 중 하나로, 함수와 함수 속 변수가 선언된 환경이 어떤 상황인가를 뜻한다. 즉, 함수 안에서 선언된 변수 유효범위다.
위 코드를 순차로 따라가보자. 처음 페이지를 로드하며 script파일을 읽는다. aaa()를 만나 함수 실행. const apple = 10; 실행, const qqq = 3; 실행. bbb()를 만나 함수 실행. bbb() 안에 들어가서 const bababa = 20;을 실행. 여기까지가 위 스크린샷 상태다. 오른쪽에서 보면 스코프 탭 안에 closure가 있음을 볼 수 있다. closure로 aaa를 가지고 있다. 측 bbb는 aaa를 상위 스코프로 인정하고 있는 상태를 말한다. 클로저 탭 안에 있는 변수를 살펴보자. bbb()함수는 aaa() 상위 함수에 있는 apple과 qqq를 모두 참조할 수 있다고 뜬다. 따라서 그 다음 콘솔들으 모두 실행하면 20, 10, 3이 모두 찍힌다.
여기까진 그냥 스코프와 뭐가 다른가 싶을 수 있다. 이제부터가 진짜다.
function aaa() {
const apple = 10;
function bbb() {
const banana = 20;
console.log(banana);
console.log(apple);
console.log(qqq);
}
const qqq = 3;
return bbb();
}
const innerbbb=aaa()
innerbbb()
스크립트 부분만 잘라온 후 aaa() bbb() 실행을 aaa() 리턴값로 바꾸었다. aaa 함수를 innerbbb에 넣은 후 이를 실행시켰다. 위 코드를 잘 살펴보자. aaa() 함수는 bbb() 반환하고 라이프사이클이 종료되어 실행콘텍스트 스택에서도 제거됐다. 그러나 위 코드를 실행하면 아무 문제 없이 20, 10, 3이 찍힌다. 어찌된 일일까? 상위 함수보다 하위 함수가 도 오래 살아있다. 바로 이부분이 클로저다. 외부 함수 밖에서 내부 함수가 호출 되더라도 외부 함수 지역 변수에 접근하는 걸 클로저라 부른다. 즉, 자기 자신을 포함한 외부 함수보다 하위 함수가 더 오래 유지되는 경우다.
마무리
외부 함수보다 내부 함수가 더 오래 살아있는 것. 이해는 했다. 다만 클로저도 언제 어떻게 써먹을 수 있을 지 딱 떠오를 때까진 시간이 걸릴 듯하다. 예제를 봐야만 ‘이렇게 쓸 수 있구나’를 아는 정도기 때문이다. 실무에서 실제로 얼마나 쓰는진 모르지만, 실제 활용 코드를 더 자주 접해봐야 익숙해질 듯한 개념이다.
※ 잘못된 내용이 있을 경우 댓글로 알려주세요. 배우고 익히고 수정하겠습니다:)
'FE > Javascript' 카테고리의 다른 글
Flatten & Unflatten (0) | 2022.10.26 |
---|---|
Recursive Functions (0) | 2022.10.22 |
Scope (0) | 2022.10.17 |
정규 표현식 (0) | 2022.10.10 |
Throttling & Debouncing at Search (1) | 2022.10.04 |