웹 개발

[Javascript] 이벤트의 실행순서 파악하기 (onMouseDown은 onClick보다 먼저 실행된다 👻)

citron031 2024. 12. 21. 00:02

프론트엔드 개발을 할 때 많이 사용되는 이벤트들이 있다.

 

그중에 onClick 이벤트가 있는데, onClick은 사용자가 마우스로 무언가를 클릭했을 때 이벤트가 발생하도록 하는 것이다.

 

다만, onClick 이외에도 또 다른 마우스 클릭 관련 이벤트들이 있고, 때로는 더 섬세한 동작을 위해서 onMouseDown, onMouseUp과 같은 이벤트들을 사용할 수 있다.

 

여기서, 더 생각해볼만한 점은 이 셋이 모두 한번에 사용되었을 때이다.

 

세 개의 이벤트는 어떤 순서로 동작할까?

 

 

사용자가 UI 요소와 상호작용할 때 마우스 이벤트가 실행되는 일반적인 순서는 다음과 같다.

  1. onMouseDown
    사용자가 마우스 버튼을 누를 때 발생한다.
  2. onMouseUp
    사용자가 마우스 버튼을 놓을 때 발생한다.
  3. onClick
    마우스 버튼이 이동하거나 너무 오래 눌리지 않은 경우 onMouseDownonMouseUp이 완료된 후 발생한다.

실제로 순서대로 작동하는지, React를 사용한 예제를 통해서 확인해보자 🙌

 

"use client";

const MouseEventTest = () => {
  const logEvent = (eventName: string) => {
    console.log(eventName);
  };

  return (
    <div>
      <h1>MouseEventTest</h1>
      <button
        onMouseDown={() => logEvent("MouseDown")}
        onMouseUp={() => logEvent("MouseUp")}
        onClick={() => logEvent("Click")}
      >
        Click Me
      </button>
    </div>
  );
};

export default MouseEventTest;

 

위의 예제를 실행해보면 !

위와 같이 로그가 남는것을 확인할 수 있다.

 

이벤트가 순서대로 실행되는 것을 알 수 있다.

(mouse up이 click보다 먼저 실행된다.)

 

이런 마우스의 이벤트를 활용해서 동기적으로 실행되는 로직들을 설정할 수 있다.

 

다음과 같은 React 예제를 살펴보자.

 

"use client";

import { useState } from "react";

const MouseEventOrderTest = () => {
  const [allowClick, setAllowClick] = useState(false);

  const handleMouseDown = () => {
    console.log("MouseDown");
    setAllowClick(true); // 마우스를 눌렀을 때 클릭 허용
  };

  const handleMouseUp = () => {
    console.log("MouseUp");
    setTimeout(() => setAllowClick(false), 100); // 짧은 지연 후 상태 초기화
  };

  const handleClick = () => {
    if (allowClick) {
      console.log("Click");
    } else {
      console.log("Click blocked");
    }
  };

  return (
    <button
      onMouseDown={handleMouseDown}
      onMouseUp={handleMouseUp}
      onClick={handleClick}
    >
      Controlled Click
    </button>
  );
};

export default MouseEventOrderTest;

위의 예제는 handleClick 내부의 로직을 보호할 수 있도록 작성해봤다.

 

실제로는 더 꼼꼼한 로직이 필요하겠지만, 마우스 버튼을 누른 순간 handleClick 이벤트가 활성화되고, 누른 상태에서 마우스를 뗀 순간 아주 잠깐의 100ms 동안만 클릭을 활성화함으로써, 클릭을 마구 눌렀을 때 handleClick 이벤트가 너무 많이 호출되는 것을 막는 코드이다.

 

💧 생각해보면 더 많은 쓸모가 있을 수 있겠지만, 간단한 예제를 통해 이런 이벤트를 알아보았다.

만약, 타인이 만든 Button 컴포넌트를 사용할 때, 이벤트를 컨트롤하기 어려울 경우도 있는데 이런 경우에는 다양한 마우스 이벤트들을 사용하여 적절하게 로직의 서순을 조정할 수 있다. 

 

+ 마우스를 주로 예시를 들었지만, 키보드도 마우스처럼 유사하게 서순을 가지고 있다.

 

키보드 이벤트 실행 순서

  1. onKeyDown
    키가 눌릴 때 발생한다.
  2. onKeyPress (Deprecated)
    (더 이상 권장되지 않음) 키가 문자 값을 생성하는 경우 onKeyDown 후 발생한다.
  3. onKeyUp
    키를 놓을 때 발생한다.