
예전에 자바스크립트를 공부할 때 작성했던 코드라, 부족한 점이 많고
예시 또한 적절치 않을 수 있습니다. 또한 클로저 설명에 대해 잘못된 점이 있다면 지적해주시면 감사하겠습니다.
쇼핑리스트 토이 프로젝트 진행중에, 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에 기재되어 있는 글을 읽고 이해해보려 했다.
클로저를 이해하기 위해서는 먼저 어휘적 범위 지정이라는 개념에 대해 알아야 하는데,
다음의 예시가 이를 잘 설명해준다. 이 예시는 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 지식 == 개발자의 코어 근육