React 17 업그레이드 후 이벤트 위임 변경 사항 정리

문제 상황

회사 프로젝트를 React 17로 업그레이드한 후, 모달 컴포넌트에서 외부 클릭 감지가 제대로 작동하지 않는 버그가 발생했다. react-modal 라이브러리를 사용 중이었는데, 모달 외부를 클릭해도 닫히지 않는 현상이었다.

원인 분석

React 17부터 이벤트 위임 방식이 변경되었다. 기존에는 모든 이벤트를 document에 붙였지만, 이제는 React 트리가 렌더링되는 root DOM 노드에 붙인다.

// React 16 이하
const rootNode = document.getElementById('root');
ReactDOM.render(<App />, rootNode);
// 이벤트는 document에 위임됨

// React 17
const rootNode = document.getElementById('root');
ReactDOM.render(<App />, rootNode);
// 이벤트는 rootNode에 위임됨

이 변경으로 인해 document에 직접 이벤트 리스너를 등록한 코드와 React 이벤트 시스템 간의 실행 순서가 달라졌다.

해결 방법

외부 클릭 감지 로직을 수정했다. e.stopPropagation()에 의존하던 코드를 제거하고, 클릭된 요소가 모달 내부인지 직접 확인하는 방식으로 변경했다.

useEffect(() => {
  const handleClickOutside = (e) => {
    if (modalRef.current && !modalRef.current.contains(e.target)) {
      closeModal();
    }
  };

  document.addEventListener('mousedown', handleClickOutside);
  return () => {
    document.removeEventListener('mousedown', handleClickOutside);
  };
}, []);

참고 사항

React 17은 breaking change가 거의 없다고 알려져 있지만, 이벤트 시스템 변경은 예상치 못한 부작용을 일으킬 수 있다. 특히 jQuery나 Vanilla JS로 작성된 레거시 코드와 혼용하는 경우 주의가 필요하다.

마이크로 프론트엔드 아키텍처를 사용한다면, 이번 변경이 오히려 도움이 된다. 여러 React 버전을 한 페이지에서 사용할 때 이벤트 충돌 위험이 줄어들기 때문이다.

React 17 업그레이드 후 이벤트 위임 변경 사항 정리