React에서의 이벤트위임(feat 이벤트 동작방식, 디버깅, 코드활용..)

이수빈·2023년 11월 2일
0

React

목록 보기
12/20
post-thumbnail
  • React에서 이벤트는 어떻게 동작할까? 이벤트 버블링, 캡처링 개념과 React에서의 이벤트 처리과정, 디버깅방법들에 대해 글을 작성한다.

이벤트 버블링, 캡처링, 위임

이벤트 버블링

  • 한 요소에 이벤트가 발생하면, 이 요소에 할당된 핸들러가 동작하고, 이어서 부모 요소의 핸들러가 동작한다.

  • 가장 최상단의 조상 요소를 만날 때까지 이 과정이 반복되면서 요소 각각에 할당된 핸들러가 동작하는게 이벤트 버블링

  • 즉 방울처럼 => 하나의 요소에 이벤트가 발생하면 최상단의 요소를 만날때까지 상위로 이벤트가 전달되는 현상.

  • 다음과 같은 코드에서 가장 안쪽의 p태그를 클릭한다면? => p → div → form 순서로 3개의 얼럿 창이 생성됨

  1. p에 할당된 onclick 핸들러가 동작합니다.
  2. 바깥의 div에 할당된 핸들러가 동작합니다.
  3. 그 바깥의 form에 할당된 핸들러가 동작합니다.
  4. document 객체를 만날 때까지, 각 요소에 할당된 onclick 핸들러가 동작합니다.

이벤트 캡처링

  • 자식 요소에서 발생한 이벤트가 부모 요소부터 시작하여 이벤트를 발생시킨 자식 요소까지 도달하는 것을 캡처링이라 한다. 즉 이벤트가 하위요소로 전파되는 단계임.

  • 이벤트 버블링과 캡쳐링은 둘 중에 하나만 발생하는 것이 아니라, 캡쳐링으로부터 시작해서 버블링으로 종료됨.

  • td를 클릭하면 이벤트가 최상위 조상에서 시작해 아래로 전파되고(캡처링 단계), 이벤트가 타깃 요소에 도착해 실행된 후(타깃 단계), 다시 위로 전파됩니다(버블링 단계). 이런 과정을 통해 요소에 할당된 이벤트 핸들러가 호출됩니다.

  • addEventListener 메소드의 세번째 매개변수에 true를 설정하면 캡처링으로 전파되는 이벤트를 캐치하고 false 또는 미설정하면 버블링으로 전파되는 이벤트를 캐치한다. (캡처링시 동작여부 결정)

이벤트 위임

  • li태그에 이벤트를 등록하려고 할 때 만일 이벤트 전파 개념이 없다면, li 요소 마다 일일히 이벤트를 등록해야 할 것이다.

  • 버블링의 특성을 통해 우리는 그 부모 요소인 ul 요소에만 이벤트를 등록하면, 어떤 몇번째의 li 요소를 클릭하든 부모 요소로 이벤트가 전파되기 때문에 불필요한 코드작성을 줄일 수 있다.

  • 이 기법을 이벤트 위임이라 부른다.

React에서의 이벤트 처리방식

  • 아래의 코드에서 item이 1억개라면? React는 1억개에 아이템에 대한 이벤트 리스너를 모두 등록하는걸까?

  • 결론부터 말하지면 아니다. React에서는 이벤트를 내부적으로 이벤트 위임 방식으로 처리한다.

  • React 17버전부터는 이벤트핸들러를 Document Level이 아닌 React 트리가 렌더되는 root Dom container에 부착함 (아래는 next.js라서 "__next"가 root Container이다)

  • React에서는 크로스브라우징 문제를 해결하기 위해 브라우저에서 발생하는 native Event를 그대로 사용하는 것이 아니라 SyntheticEvent 객체를 이용해 Native Event를 감싸는 방식을 사용함. => 가상돔생성시점에 발생

  • 실제 코드레벨에서 onClick와 같은 이벤트 핸들러에서 바로 이벤트가 처리되는게 아님. => dispatchEvent라는 함수를 통해 Root Node로 전달됨. => Root node에서 target Dom node를 찾아 이벤트가 실행됨.

  • Root Node에서는 React Dom Tree가 생성될 때 Native Event와 SyntheticEvent를 매핑하는 과정이 존재함.

내부적인 처리과정

  • 자세한 과정은 아래 두 블로그를 참고하자 (대략적인 흐름만 작성한다)

React 이벤트 핸들링과정 : https://handhand.tistory.com/287
React Deep Dive – 이벤트를 핸들링하는 법 : https://inpa.tistory.com/entry/JS-%F0%9F%93%9A-%EB%B2%84%EB%B8%94%EB%A7%81-%EC%BA%A1%EC%B3%90%EB%A7%81

  • 총 3가지 단계로 실행된다.
  1. Synthetic Event, Native Event에 대한 매핑
  2. Synthetic Event에 해단 이벤트 listener 등록
  3. Synthetic Event에 대한 감지 후 해당 listener 실행

Synthetic Event, Native Event에 대한 매핑

createRoot함수 => listenToAllSupportedEvents 호출 => Native Event와 Synthetic 이벤트를 매핑함.


Synthetic Event에 해단 이벤트 listener 등록

  • listenToNativeEvent 함수사용 => addTrappedEventListner 함수 호출 =>
    createEventListenerWrapperWithPriority 를 통해 listener 를 생성하여 할당 (Listener 할당과정

Synthetic Event에 대한 감지 후 해당 listener 실행

  • Button을 클릭하면 리액트에서 ‘click’ 이벤트를 감지하고, attach한 이벤트 리스너가 트리거됩니다. 이때, 이 이벤트 리스너는 리액트에서 정의한 dispatchEvent 함수를 호출하게 됩니다.

  • 이 함수는 최종적으로 dispatchEventsForPlugins 를 호출합니다.

  • 이후 getEventTarget 이라는 함수로 target을 얻고, extractEvents라는 함수를 통해 해당 listener를 찾은 뒤, dispatchQueue에 해당 이벤트와 리스너를 넣어 순차적으로 실행함.

디버깅 방법 및 꿀팁

  • 네트워크탭에서 Elements Tab에 Event Listner라는 항목이 존재한다.

  • 이런식으로 Framework listeners 항목을 체크했을때, 프레임워크에 등록된 이벤트 리스너들만을 모아서 볼 수 있다.

ref)
✔ PoimeaWeb Event : https://poiemaweb.com/js-event
✔ 한눈에 이해하는 이벤트 흐름제어(blog) : https://inpa.tistory.com/entry/JS-%F0%9F%93%9A-%EB%B2%84%EB%B8%94%EB%A7%81-%EC%BA%A1%EC%B3%90%EB%A7%81
✔ JavaScript Info 버블링과 캡쳐링 : https://ko.javascript.info/bubbling-and-capturing
✔ React SyntheticEvent(공식문서) : https://ko.legacy.reactjs.org/docs/events.html#gatsby-focus-wrapper

profile
응애 나 애기 개발자

0개의 댓글