모던 리액트 Deep Dive 10-1. Event Bubbling, Event Capture and Event Delegation

React v16 에서 v17 로 변경되면서 이벤트 위임 방식의 변경에 대해 자세히 알아봅니다.

cover-image

📖 서론

위키북스의 모던 리액트 Deep Dive 10장을 학습하게 되었습니다.

회사에서는 React 17 버전을 사용하고 있으며, 개인 블로그 프로젝트 등에서는 React 18 버전을 사용하고 있는데 이 둘의 차이를 피상적으로만 알고 있기 때문에 이번 기회에 좀 더 구체적으로 알고 싶어졌기 때문입니다.

먼저 리액트 16 버전에서 리액트 17 버전으로 변경되면서 이벤트 위임 방식의 변경에 대해 좀 더 자세히 공부해 보게 되었습니다.

🌌 리액트에서 이벤트를 등록하는 두 가지 방식

1. 리액트 방식

  • 리액트에서 DOM 에 이벤트를 추가하는 방식 (이벤트 핸들러 연결)

2. 직접 DOM 을 참조(reference) 하는 방식

  • 직접 DOM 을 참조해서 가져온 다음 DOM 에 직접 접근해 함수를 추가하는 고전적 방식

    import React, { useRef } from 'react'; function Field() { const inputRef = useRef(null); function handleFocus() { inputRef.current.disabled = false; inputRef.current.focus(); } return ( <> <input disabled type="text" ref={inputRef} /> <button onClick={handleFocus}>활성화</button> </> ); }

🌍 브라우저가 이벤트를 감지하는 방식

1. 이벤트 버블링 (Event Bubbling)

특정 화면 요소에서 이벤트가 발생했을 때 해당 이벤트가 더 상위의 화면 요소들로 전달되어 가는 특성을 의미

  • 특정 요소에서 최상위 화면 요소까지 이벤트가 전파됨
  • 하위에서 상위 요소로의 이벤트 전파 방식

2. 이벤트 캡쳐 (Event Capturing)

이벤트 버블링과 반대 방향으로 진행되는 이벤트 전파 방식을 의미

  • 특정 요소에서 클릭 이벤트가 발생했다면, 해당 이벤트가 발생한 지점을 찾으러 가는 것
  • 즉, 자식 요소에서 발생한 이벤트가 부모 요소부터 시작하여 안쪽 자식 요소까지 도달하는 것

🛁 브라우저에서 이벤트가 일어나는 단계 (이벤트 전파 흐름)

1. 이벤트 캡쳐링 (Event Capturing)

어디서 클릭 이벤트가 발생했지? 트리 최상단 부모 요소에서 부터 찾으러 가는 단계

2. 타깃(Target)

이벤트가 타깃 요소에 도착해 리스너를 실행합니다.

3. 버블링 (Bubbling)

다시 상위 요소로 이벤트를 전파한다. 즉 이벤트가 발생한 요소에서부터 시작해 최상위 요소까지 다시 올라갑니다.

⚙️ 이벤트 전파를 제어하기

  • 브라우저는 기본적으로 캡쳐링 ↔️ 버블링으로 동작하기 때문에 이벤트 동작 자체를 바꿀 수 없습니다.
  • 하지만 부모와 자식 요소 모두에 각기 다른 이벤트가 등록되어 있고 자식 요소를 클릭했을 때만 이벤트를 발생시키고 부모 요소의 이벤트는 발생시키고 싶지 않을 때는?
  • 혹은 기본으로 정의된 이벤트를 작동하지 못하게 하고 싶을 때는?

event.stopPropagation()

  • 이벤트 버블링을 방지
  • 상위 요소로 해당 이벤트를 전달하지 않고 이벤트를 발생시킨 요소만 이벤트를 감지하도록 사용하는 것
  • 클릭한 요소의 이벤트만 발생시킴

event.preventDefault()

  • 기본으로 정의된 이벤트를 작동하지 못하게 하는 메서드
  • 이벤트에 대한 구현체의 기본 동작을 실행하지 않음
  • e.g) a 태그에 연결된 href 경로 → a에 onclick 이벤트 핸들러 연결 시, 기본으로 정의된 이벤트를 실행하지 않고 alert 를 띄우는 등 다른 동작을 수행하고자 할 때.

🎭 이벤트 위임 (Event Delegation) 이란?

  • 이벤트 캡처링과 버블링을 이용한 것
  • 여러 엘리먼트마다 각각 이벤트 핸들러를 할당하지 않고, 공통되는 부모 요소에 이벤트 핸들러를 할당하여 이벤트를 관리하는 방식
  • 특정 노드에 일일이 이벤트 리스너를 추가하는 대신, 이벤트 리스너를 특정 노드들을 포함하는 상위 노드에 연결하여 이벤트를 전파하는 것
  • 위임된 이벤트는 포함된 하부 노드에 전파됨

🐞 리액트 버전 16에서의 이벤트 위임

  • 이벤트 핸들러를 해당 이벤트 핸들러를 추가한 각각의 DOM 요소에 부탁하는 것이 아니라
  • 모든 이벤트는 document 에 부착합니다.
  • 서로 다른 리액트 버전 (16.14, 16.16) 을 하나의 프로젝트에서 사용할 때 발생할 수 있는 문제를 해결해야 함

🥯 리액트 버전 17에서의 이벤트 위임

  • 이벤트 핸들러를 해당 이벤트 핸들러를 추가한 각각의 DOM 요소에 부탁하는 것이 아니라
  • 이벤트 타입(click, change) 당 하나의 핸들러를 컴포넌트의 최상위 루트 (root) 에 부착합니다.
  • 위에서 알게된 이벤트 단계의 원리를 활용해 이벤트를 상위 컴포넌트에만 붙이는 것을 의미합니다.

👻 리액트의 이벤트는 어떻게 동작하는가? (SyntheticEvent)

  • React Element 의 on{Event} Props 에 넣어주는 이벤트 리스너는 React 에서 제공하는 합성 이벤트(SyntheticEvent)를 받습니다. 이 합성 이벤트는 크로스 브라우징 문제를 다루기 위해 React 제공하는, 브라우저 이벤트를 한번 래핑한 객체인데요. React 는 이렇게 자체적으로 이벤트를 다루기 위해 이벤트 리스너를 React 루트 요소에 붙이고 있습니다.

[클릭!] 도서 구매 링크 🧚🏻

이전 블로그로
다음 블로그로