클로저 알아가기

Donghyun Hwang·2023년 11월 4일
post-thumbnail

❗ 유의

예전에 자바스크립트를 공부할 때 작성했던 코드라, 부족한 점이 많고
예시 또한 적절치 않을 수 있습니다. 또한 클로저 설명에 대해 잘못된 점이 있다면 지적해주시면 감사하겠습니다.


⭐ 클로저가 궁금해진 계기

쇼핑리스트 토이 프로젝트 진행중에, input을 입력받아 내가 정의한 createItemBox() 함수를 통해 ShoppingList에 itemBox(살 것)를 추가하는 코드를 작성했다.
input에 텍스트를 입력받아 생성되는 최종 HTML 코드와 모습은 다음과 같다.

<section id="content">
       <li class="itemBox">
            <h2 class="item_title">살 것 이름</h2>
            <li class="btns">
                <!-- 체크 버튼 -->
                <button class="fa fa-check" id="check_btn"></button> 
			    <!-- 삭제 버튼 -->
                <button class="fa fa-trash" id="trash_btn"></button>
            </li>
        </li>
</section>

이 때 휴지통 버튼을 누르면 해당 아이템이 사라지게 하도록 이벤트리스너를 달았는데,

처음에는 다음과 같이 parentNode를 사용하여 아이템을 없앴다.

trash_btn.parentNode.parentNode.remove();

parentNode를 통한 삭제는 어떤 자식이 클릭이 되었느냐에 따라,
HTML 구조가 조금만 바뀌어도 바로 에러가 발생할 수 있기 때문에,
명확한 id나 클래스명 등을 통해 삭제를 처리하는 것이 좋다.
이렇게 적지 않도록 하자...아무튼

function createItemBox() {
 // 이전 코드 생략
  trash_btn.addEventListener('click',( e => {        
    content.removeChild(itemBox);
    });
  );
}

createItemBox 함수의 일부분이다.
createItemBox() 함수 안에서 trash_btn 생성과 함께 위와 같은 코드를 넣은 후에, 잘 작동하는 것을 보고서 의구심이 들었다.

content 내부에는 여러 itemBox들이 있는데, 자바스크립트는 여러 버튼들 중 내가 누른 휴지통 버튼이 정확히 어떤 itemBox의 버튼인지 알고 삭제가 되는 걸까?

자바스크립트에는 '클로저'라는 개념이 있었다.

📚클로져란

아직은 클로저에 대해 잘 모르지만, mdn에 기재되어 있는 글을 읽고 이해해보려 했다.

MDN 클로저


클로저를 이해하기 위해서는 먼저 어휘적 범위 지정이라는 개념에 대해 알아야 하는데,

다음의 예시가 이를 잘 설명해준다. 이 예시는 ES6 이전의 자바스크립트에 대한 설명이다.

if (Math.random() > 0.5) {
      var x = 1;
    } else {
      var x = 2;
    }
    console.log(x);

평소에 사용하는 C와 JAVA에서 다음과 같은 코드는 에러를 발생한다.

if 블록 내에서 선언된 x라는 변수를 console.log(x) 줄에서는 알 길이 없기 때문이다.

그러나 ES6 이전 자바스크립트에서는, var x 선언 및 명령문에서 x가 전역 변수로 생성되었다.

블록 안에서 생성되었는데 왜 스코프를 가지지 않지?

이러한 혼란 때문에 ES6에서 부터는 블록도 스코프로 취급되게 되었다.

단, 이는 let과 const를 사용하여 변수를 선언했을 때만 유효하다.

클로저는, 전역 스코프와 함수 스코프 블록 스코프 등 모든 스코프를 캡처할 수 있다.

이 부분 이후의 더 자세한 클로저의 내용에 대해 이해해보려고 했는데....

굉장히 어려웠다. 정확히는 무엇이다! 라고 내 머릿속에 개념이 제대로 잡히질 않았다.
😡


클로저와 관련한 예시들을 보면서 감은 어느정도 잡혔지만, 명확히 정의를 내려서 설명하기가 힘들었다. 다른 많은 사이트의 글들을 참고한 결과, 그래도 클로저의 느낌은 잡아갈 수 있었다.

우선 내가 직면한 궁금증에서의 '클로저'의 정체는

자신이 선언될 당시의 환경을 기억하는 함수

라고 정의 내릴 수 있었다.

내가 선언한 createItem() 함수 안에는, eventListener 콜백 함수가 정의되어 있다. 쉽게 말해서 중첩함수라는 것이다.

이 때 내부 함수인 이벤트리스너 함수가 수행될 때, 외부 환경에 있는 데이터 또한 함께 기억하고 있었기 때문에, itemBox를 제거할 시에 내가 만든 itemBox 중 어떤 itemBox를 가리키고 있는지 기억한다...라고 이해했다.

“클로저는 내부함수가 외부함수의 맥락(context)에 접근할 수 있는 것을 가리킨다" 라는 클로저의 여러 정의 중 하나가 이제는 어느정도 이해가 되었다.

클로저가 아직 명확히 내 개념으로 자리 잡지는 않은 것 같아서, 후에 더욱 공부가 필요할 것 같다.

도움을 받은 글들의 링크를 아래에 같이 첨부하겠습니다!

특히 첫 번째 링크의 예제 문제들이 클로저의 개념을 이해하는 데 많은 도움이 되었습니다.


✅시간이 지나고..

지난 학기 학교에서 프로그래밍 언어 과목을 수강했다.
언어마다의 스코프 단위, 특성들을 배우고 나서 다시 클로저를 보니 더 쉽게 이해되는 것 같다.
CS 절대 소홀히 하지 말자...^_^

CS 지식 == 개발자의 코어 근육

💎레퍼런스

변수의 유효 범위와 클로저
클로저란 무엇일까?

profile
앞만 보고 가

0개의 댓글