mouseOver 이벤트를 상위 엘리먼트에 줬는데, 하위 엘리멘트에서도 발생해서 엄청난 지진 현상이 발생했다. 정지 버튼 위에 마우스를 가져가면 깜빡이는 현상이 문제이다.
| 문제의 화면 | 해결 된 화면 |
|---|---|
![]() | ![]() |
처음에는 z-index로 해결할 수 있을까? 했지만 근본적인 해결 방법이 아니었다.
이벤트에는 이벤트 버블링과 캡처링이라는 현상이 존재한다.
이벤트 버블링 : 요소에서 발생한 이벤트가 해당 요소의 부모 요소로 전파
이벤트 캡처링 : 이벤트가 계층 구조의 최상위 요소에서 시작하여 하위 요소로 전파
자세한 설명은 참고 : 한눈에 이해하는 이벤트 흐름 제어 (버블링 & 캡처링)
내 요소들의 배치는 대략 이렇게 되어있다.
<div css={VideoStyle}>
<div
css={ClickZone}
onClick={playingHandler}
onMouseOver={hoverHandler} // 이벤트 발생
onMouseOut={unhoverHandler}
/>
</div>;
{
isHover && (
<div css={PlayBtnStyle}> // 이벤트 없는데 발생
<PauseBtn />
</div>
);
}
같은 div 태그에 쌓인 요소도 아닌데 영향을 받는다고? 라는 생각이 들어서 콘솔로 확인을 해봤다.

// 확인 코드
const hoverHandler = () => {
setIsHover(() => true);
console.log('onHover', isHover);
};
const unhoverHandler = () => {
setIsHover(() => false);
console.log('outHover', isHover);
};
마우스를 일시정지 버튼에 가져가자마자 엄청나게 많은 이벤트가 발생하면서 hover 상태가 변화되는 모습을 볼 수 있었다.
이벤트 버블링은 하위 요소에 e.stopPropagation()을 추가하면, 상위 요소로 이벤트가 전파되는 것을 막을 수 있다.
const onMouseOver = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
e.stopPropagation();
console.log('버블링 확인 : ', e.nativeEvent.bubbles);
}
<div css={PlayBtnStyle} onMouseOver={(e) => checkBubble(e)}>
<PauseBtn />
</div>
| 수정 버전 | ![]() |
|---|---|
| 원본 | ![]() |
비교가 잘 보이는지 모르겠지만, 정지 버튼을 보면 확실히 적은 오류가 보이는 것을 확인할 수 있다. div에만 e.stopPropagation()을 적용해서 그런지, 원 위에서는 오류가 발생하지 않고 svg에 접근했을 때 발생하는 모습을 볼 수 있다.
하지만 이렇게 일일이 처리해주려면 번거로울 것이다.
여기 아주 간단한 방법이 있다!
css 에 pointer-events라는 속성이 있다. 이 속성은 특정 요소의 트리거 역할을 설정한다. 만약 z-index가 높은 요소 아래에 있는 이벤트를 작동시키고 싶다면, pointer-events : none; 을 적용하면 된다.
const PlayBtnStyle = css`
pointer-events: none;
`;

비로소 오류 없이 마우스 이벤트가 작동하는 모습을 볼 수 있게 되었다.
이런 상황을 만나면 이벤트 버블링이 왜 필요할까? 라는 생각이 들 수 있지만, 비슷한 요소들 (예를들어 li 태그같은) 에게 한 번에 이벤트를 부여할 수 없다면 굉장히 번거로워질 것이다.
이번 트러블 슈팅 과정을 통해 이벤트 버블링과 캡처링이라는 이벤트 전파 과정을 공부할 수 있었다.