[TIL-0515] onMouseEnter, onMouseLeave

jiny·2025년 5월 29일

캡스톤2

목록 보기
15/22

onMouseEnteronMouseLeave는 React(또는 순수 HTML/JavaScript의 DOM 이벤트 시스템)에서 마우스 포인터가 특정 요소에 진입하거나 벗어날 때 실행되는 이벤트 핸들러이다.
두 이벤트는 주로 UI에 호버(hover) 효과를 주거나, 툴팁 표시, 애니메이션 시작/종료, 상태 변화 등을 제어할 때 사용된다.

🌟 onMouseEnter : 마우스가 요소 안으로 들어갈 때

  • 동작 조건

    • 마우스 커서가 요소 영역 안으로 들어가는 순간 이벤트가 발생함
    • 자식 요소로 이동하더라도 다시 발생하지 않음 (onMouseOver과의 차이점)
  • 주요 특징

    • 버블링 없음 (onMouseOver과의 차이점)

      🫧 버블링

      • 의미: 이벤트가 하위 요소(자식)에서 발생했을 때, 상위 요소(부모)로 전달되는 현상
      • 예시: 자식 <div>에서 마우스 이벤트 발생 → 부모 <div>의 이벤트 핸들러도 실행됨
        <div onMouseOver={() => console.log("부모")}>
          <div onMouseOver={() => console.log("자식")}>자식 요소</div>
        </div>
        • 자식 요소에 마우스를 올리면
          1) "자식" 로그 출력
          2) 버블링되어 "부모" 로그도 출력
    • React에서는 onMouseEnter를 사용하면 내부적으로 mouseenter가 아닌 mouseover를 사용하지만, 자식 요소 이동 시 중복 실행 안 되도록 자동 처리

      🤔 mouseenter vs. mouseover (실제 DOM 이벤트 기준)

      이벤트 이름버블링 여부자식 요소 이동 시 재호출언제 발생?
      mouseenter❌ (버블링 안 함)요소에 처음 진입할 때만 한 번 발생
      mouseover✅ (버블링 함)요소 위에 올라갈 때마다 발생 (자식 포함)

      💡 React의 이벤트 시스템은 mouseenter를 직접 사용하지 않음

      • React에서는 onMouseEnter라고 쓰지만, 내부적으로는 실제로 mouseover 이벤트를 사용
      • 하지만, 동작은 mouseenter처럼 구현되어 있음

      ➡️ React는 mouseover 이벤트를 써서 onMouseEnter를 구현하지만, 자식 요소로 마우스를 옮겨도 다시 실행되지 않게 자동으로 걸러줌

      🤔 React의 onMouseOver는 어떻게 작동하나?

      React의 onMouseOver그대로 브라우저의 mouseover 이벤트를 사용
      즉, 다음 특징을 그대로 가짐

      특징설명
      버블링 O자식 요소에서 발생해도 부모로 이벤트 전달됨
      자식 요소 이동 시 재호출 O마우스가 부모 요소 위에 있는 동안 자식 요소 위로 이동해도 계속 발생함

🌟 onMouseLeave : 마우스가 요소 밖으로 나갈 때

  • 동작 조건

    • 마우스 커서가 요소 전체를 벗어나는 순간 이벤트가 발생함
    • 자식 요소로 이동하는 경우에는 발생하지 않음 (onMouseOut과의 차이점)
  • 주요 특징

    • mouseleave 이벤트는 마우스가 요소 전체를 떠날 때 한 번만 발생
    • React에서는 onMouseLeave를 사용하면 내부적으로 mouseleave가 아닌 mouseout을 사용하지만, 자식 요소 이동 시 중복 실행 안 되도록 자동 처리

      🤔 mouseleave vs. mouseout (실제 DOM 이벤트 기준)

      이벤트 이름버블링 여부자식 요소 이동 시 재호출언제 발생?
      mouseleave❌ (버블링 안 함)요소를 벗어났을 때만 한 번 발생
      mouseout✅ (버블링 함)요소에서 마우스가 빠질 때마다 발생 (자식 포함)

      💡 React의 이벤트 시스템은 mouseleave를 직접 사용하지 않음

      • React에서는 onMouseLeave라고 쓰지만, 내부적으로는 실제로 mouseout 이벤트를 사용
      • 하지만, 동작은 mouseleave처럼 구현되어 있음

      ➡️ React는 mouseout 이벤트를 써서 onMouseLeave를 구현하지만, 자식 요소로 마우스를 옮겨도 다시 실행되지 않게 자동으로 걸러줌


🌟 onMouseEnter vs. onMouseOver

구분onMouseEnteronMouseOver
이벤트 발생 시점요소 진입 시 한 번요소 또는 자식 요소 진입 시마다
버블링❌ (실제 DOM 기준)
자식 요소 이동 시❌ 재호출 안 됨✅ 계속 호출됨

🌟 onMouseLeave vs. onMouseOut

구분onMouseLeaveonMouseOut
이벤트 발생 시점요소를 벗어날 때 한 번자식 포함 요소 벗어날 때마다
버블링❌ (실제 DOM 기준)
자식 요소 이동 시❌ 재호출 안 됨✅ 계속 호출됨

🌟 주의사항

  • onMouseEnter/onMouseLeave모바일 환경에서는 동작하지 않음 (터치 이벤트와 다름)
  • onMouseOveronMouseOut은 자식 요소에 마우스가 들어가거나 나갈 때도 이벤트가 발생하므로, 불필요한 재렌더링/상태 업데이트가 발생할 수 있음

🌟 사용 예시

  1. 호버 효과(Hover Effect) 제어

    <div
      onMouseEnter={() => setHovered(true)}
      onMouseLeave={() => setHovered(false)}
    >
      {hovered ? "😄 Hovered!" : "🙂 Hover me!"}
    </div>
    • 사용 목적
      버튼/아이콘/카드 등에 마우스를 올렸을 때 배경색, 그림자 등 스타일을 바꾸고 싶을 때
    • 왜 필요한가?
      CSS :hover로 충분하지 않을 때, 동적인 동작(상태 변경, 애니메이션)과 연동하려면 JS 이벤트 핸들러가 필요함
  2. 툴팁(Tooltip)이나 설명 박스 표시

    <div
      onMouseEnter={() => setShowTooltip(true)}
      onMouseLeave={() => setShowTooltip(false)}
    >
      ℹ️ 정보
      {showTooltip && <div className="tooltip">여기에 상세 정보</div>}
    </div>
    • 사용 목적
      마우스를 아이콘이나 텍스트에 올렸을 때 부가 설명을 보여줌
    • 왜 필요한가?
      title 속성보다 더 예쁜 커스텀 툴팁을 만들 때 유용함
  3. 애니메이션 트리거

    <div
      onMouseEnter={() => startAnimation()}
      onMouseLeave={() => stopAnimation()}
    >
      애니메이션 요소
    </div>
    • 사용 목적
      마우스를 올렸을 때 회전, 확대, 흐림 등 애니메이션 실행
    • 왜 필요한가?
      마우스 움직임에 따라 JS 기반 애니메이션을 제어해야 할 때
  4. 메뉴/서브메뉴 열기

    <div
      onMouseEnter={() => setMenuOpen(true)}
      onMouseLeave={() => setMenuOpen(false)}
    >
      메뉴
      {menuOpen && <ul className="submenu">서브 메뉴</ul>}
    </div>
    • 사용 목적
      드롭다운 메뉴를 마우스 올림으로 열고 벗어나면 닫음
    • 왜 필요한가?
      클릭보다 더 직관적인 마우스 인터렉션을 제공함
  5. 상태 변경을 통한 조건부 렌더링

    <div
      onMouseEnter={() => setActive(true)}
      onMouseLeave={() => setActive(false)}
    >
      {active ? <ComponentA /> : <ComponentB />}
    </div>
    • 사용 목적
      상태 값에 따라 다른 컴포넌트를 보여줄 때
    • 왜 필요한가?
      마우스 진입/이탈을 사용자 행동 감지로 활용
  6. 마우스 좌표 추적

    const handleMouseEnter = (e: React.MouseEvent) => {
      console.log("X: ", e.clientX, "Y: ", e.clientY);
    };
    
    <div onMouseEnter={handleMouseEnter}>커서 좌표 보기</div>
    • 사용 목적
      커서 위치 기반으로 어떤 효과(팝업 위치, 애니메이션 등)를 주고 싶을 때

✍️ 구현 예시

  • AI 설문지 툴팁 : AIButton 위에 마우스를 올렸을 때 AITooltip이 보이게 구현

    • AIButton.tsx

      import { useState } from "react";
      import AITooltip from "./AITooltip";
      import AISurvey from "./AISurvey";
      
      const AIButton = () => {
        const [isHovered, setIsHovered] = useState<boolean>(false);
        const [showQuestionnaire, setShowQuestionnaire] = useState<boolean>(false);
        
        return (
          <div>
            {!showQuestionnaire && isHovered && <AITooltip />}
            {showQuestionnaire && <AISurvey />}
            <button
              onMouseEnter={() => setIsHovered(true)}
              onMouseLeave={() => setIsHovered(false)}
              className="fixed bottom-[10px] right-[10px]"
              onClick={() => setShowQuestionnaire(!showQuestionnaire)}
            >
              <img
                src="/images/ai-button.svg"
                alt="ai"
                className="h-[70px] aspect-square hover:cursor-pointer"
              />
            </button>
          </div>
        );
      };
      
      export default AIButton;
    • AITooltip.tsx

      const AITooltip = () => {
        return (
          <div className="rounded-[8px] bg-[#5A5858] p-[10px] text-white w-fit fixed bottom-[85px] right-[15px] [box-shadow:5px_5px_10px_rgba(0,0,0,0.25)]">
            <h3 className="font-bold mb-[3px]">AI 맞춤 여행지 찾기</h3>
            <p className="text-[13px]">AI를 이용하여</p>
            <p className="text-[13px]">나만의 맞춤 여행지를 찾아보세요!</p>
          </div>
        );
      };
      
      export default AITooltip;
      • AI 버튼 위에 마우스를 올리면 isHovered 상태가 true가 되면서 AI 툴팁이 뜸
        (단, AI 설문지가 떠 있을 때는 AI 버튼 위에 마우스를 올려도 툴팁이 뜨지 않도록 함)
      • AI 버튼 밖으로 마우스를 옮기면 isHovered 상태가 false가 되면서 AI 툴팁이 사라짐
      • AI 버튼을 클릭하면 showQuestionnaire 상태가 원래의 반대가 됨
        • 설문지가 보이는 상태였다면 → 설문지가 사라짐
        • 설문지가 안보이는 상태였다면 → 설문지가 뜸

0개의 댓글