[데브코스] 15, 16일차 TIL (이벤트 위임, 커스텀 이벤트, 낙관적 업데이트, 디바운스)
공부
자바스크립트
javascript
데브코스
TIL
이벤트
낙관적업데이트
디바운스
2022-04-11

들어가며

평소에 관심을 가지고 한번쯤은 구현해 봤던 기능들을 강의를 통해 다시 구현했던 시간이었다. 혼자 구현할 때는 '과연 이 방법이 맞는걸까?' 하는 의구심이 있었는데, 강의를 통해 어느정도 궁금했던 점이 해결된 것 같다.

이벤트 위임 (Event Delegation)

자바스크립트에서 이벤트를 핸들링하는 가장 쉬운 방법은 이벤트가 발생할 요소에 addEventListener 를 사용해 이벤트 리스너를 등록하는 것이다. 만약 리스트가 있고 리스트 내부의 리스트 아이템에 click 이벤트를 설정해야하는 상황을 생각해보자. 아이템의 개수가 적다면 상관 없겠지만 개수가 많아질수록 모든 아이템에 이벤트를 등록해야하기 때문에 비효율적이다. 이런 상황에서 사용하는 게 이벤트 위임이다.

1 <ul>
2 <li>1</li>
3 <li>2</li>
4 <li>3</li>
5 ...
6 <li>999</li>
7 <li>1000</li>
8 </ul>

이벤트 위임을 이해하기 위해서 먼저 자바스크립트 이벤트의 이벤트 버블링에 대해 이해해야한다.

1 <div class="first">
2 <div class="second">
3 <div class="third"></div>
4 </div>
5 </div>

위와 같은 html 이 있을 때 class="third"div 를 클릭하면 해당 요소에 클릭 이벤트가 발생하고, 이 이벤트는 해당 요소의 상위 요소로 전달되고 최종적으로 최상위 요소까지 이벤트가 전달된다. 이렇게 하위 요소에서 상위 요소를 이벤트가 전파되는 것을 이벤트 버블링 (Event Bubbling) 이라고 한다.

위에서 설명했던 리스트의 경우를 다시 생각해보자. li 요소를 클릭하면 이벤트 버블링으로 인해 클릭 이벤트가 상위 요소인 ul 에 전파된다. 그렇기 때문에 각각의 li 요소에 이벤트 리스너를 등록하지 않고 ul 에 이벤트 리스너를 등록하면 하위의 li 요소에서 발생한 클릭 이벤트를 감지할 수 있다. li 에서 처리해야 할 이벤트를 상위 요소에게 위임해서 처리하기 때문에 이벤트 위임 (Event Delegation) 이라고 한다.

주의할 점

이벤트 버블링은 모든 이벤트에서 발생하지 않는다. 클릭 이벤트의 경우 이벤트 버블링이 발생해 이벤트 위임을 통해 처리할 수 있지만, 그렇지 않은 이벤트도 있기 때문에 사용할 때 조심해야 한다.

커스텀 이벤트

자바스크립트에는 다양한 이벤트가 있다. 이벤트는 기본적으로 정의되어 있다. 요소를 클릭했을 때는 click 이벤트가 발생하고, 키를 입력한 후 뗐을 때는 keyup 이벤트가 발생한다. 이처럼 기본적인 이벤트는 정해져 있다.
그런데 만약 내가 원하는 이벤트를 만들고 싶다면 어떻게 할까? 내가 원하는 상황에 원하는 이벤트를 발생시키고 싶을 수 있다. 이 때 원하는 이벤트를 직접 만들 수 있다. 만약 특정 요소를 클릭 했을 때 catch-element 라는 이벤트를 발생시킨다고 하자. 이벤트를 발생시키기 위해 CustomEvent 라는 객체를 사용해 커스텀 이벤트를 생성한다.

1 window.dispatchEvent(
2 new CustomEvent("catch-element", {
3 detail: {
4 test: "Custom Event!",
5 },
6 })
7 );

CustomEvent의 첫 번째 인자로 발생 시킬 이벤트의 이름을 입력한다. 두 번째 인자로는 객체를 전달할 수 있는데 이 객체에 detail 이라는 프로퍼티를 추가해 커스텀 이벤트 관련 정보를 명시하고, 해당 정보를 이벤트에 전달할 수 있다.

커스텀 이벤트를 처리하기 위해서 다른 이벤트와 같이 addEventListener 를 사용하면 된다.

1 window.addEventListener('catch-element', e => {
2 console.log(e.detail); // { test: 'Custom Event!' }
3 }

낙관적 업데이트

서버에 데이터를 저장할 때 서버로 요청을 보내고, 저장이 완료되면 응답을 받고, 저장된 데이터를 다시 서버로부터 받아와서 화면을 업데이트 해야 사용자는 데이터를 저장하고, 제대로 저장되었는지 확인할 수 있다. 서버에 요청을 보내고 응답을 받는 과정이 짧다면 문제가 되지 않지만, 서버로부터 응답을 받을 때 까지 시간이 오래 걸리게 되면 사용자는 화면이 업데이트 될 때까지 오랫동안 기다려야 하는 상황이 생긴다.

이런 문제를 해결하기 위해 서버에서 응답이 도착하기 전에 미리 요청이 성공했을 때의 화면으로 업데이트하고, 서버로부터 응답을 받으면 응답에 맞게 화면을 다시 그려주는 방법을 사용하는데 이를 낙관적 업데이트 라고 한다.

낙관적 업데이트는 비교적 가벼운 요청을 처리할 때 사용한다. 예를 들어 페이스북이나 인스타그램에서 좋아요를 누르면, 요청이 성공했다고 가정하고 좋아요를 누른 상태로 화면을 그려준다. 좋아요 기능은 여러 명의 사용자가 동시에 요청을 보내도 문제가 없고, 미리 화면을 업데이트 했을 때 생기는 부작용이 없기 때문에 낙관적 업데이트를 할 수 있다. 그런데 결제 기능을 생각해보자. 사용자가 결제 요청을 보내면 서버에서 요청을 처리하고 처리 결과에 대한 응답을 받고 화면을 업데이트 한다. 이 과정에서 낙관적 업데이트를 사용하면 결제가 완료되지 않았는데 사용자는 결제가 완료되었다는 화면을 보게 되고, 이 때 요청이 실패하면 부작용이 발생할 수 있다.

디바운스 (Debounce)

블로그에 글을 쓰는 상황을 생각해보자. 글을 쓰는 도중 갑자기 브라우저가 종료되면 열심히 작성하는 글이 다 날아가게 된다. 이런 상황을 해결하기 위해 로컬 스토리지에 현재까지 작성한 글을 저장하고 만약 브라우저가 갑자기 종료 되었을 때 로컬 스토리지에 저장된 데이터를 불러와서 이어서 글을 작성할 수 있다. 이를 구현하기 위해 textarea 에 변경이 있을때마다 로컬 스토리지에 저장한다고 하면 계속해서 이벤트가 발생하기 때문에 성능 상의 문제가 생길 수 있다. 이벤트 호출 횟수를 줄이기 위해 계속 글을 작성하고 있다면 저장하는 로직을 실행시키지 않는 방법을 사용할 수 있다. 일정 시간 내에 같은 이벤트가 계속해서 발생하면 가장 마지막에 발생한 이벤트에 대한 동작을 하는 것을 디바운스 (Debounce) 라고 한다.

정리

15일차 강의 내용을 정리하지 못해서 오늘 같이 정리를 했다. 정리하는 걸 한 번 밀리니까 계속 밀리게 되는 것 같다. 주말에 벚꽃놀이도 갔다 오고, 헤어진 친구 위로해준다고 술약속도 갔다 오니까 공부할 시간이 너무 부족한 것 같다. 데브코스 기간 중에는 최대한 공부할 수 있는 시간을 확보하는 게 중요한 것 같다.

아직 블로그에 사진을 올리는 방법이 익숙하지 않다. 토요일에 마광휘님 특강을 들으면서 블로그의 중요성도 알게 되고, 광휘님 블로그도 살펴 봤는데 Gatsby.js 로 만드셔서 참고할 만한 코드가 많을 것 같다. 코드 참고해서 깔끔하게 이미지 업로드 할 수 있도록 해야겠다.

참고자료

이벤트 위임 https://ko.javascript.info/event-delegation
이벤트 버블링 https://joshua1988.github.io/web-development/javascript/event-propagation-delegation/
커스텀 이벤트 https://ko.javascript.info/dispatch-events
디바운스 https://velog.io/@yujuck/Javascript-%EB%94%94%EB%B0%94%EC%9A%B4%EC%8A%A4%EC%99%80-%EC%93%B0%EB%A1%9C%ED%8B%80%EB%A7%81

Loading script...