onMouseEnter와 onMouseLeave는 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를 사용하지만, 자식 요소 이동 시 중복 실행 안 되도록 자동 처리됨
🤔
mouseentervs.mouseover(실제 DOM 이벤트 기준)
이벤트 이름 버블링 여부 자식 요소 이동 시 재호출 언제 발생? mouseenter❌ (버블링 안 함) ❌ 요소에 처음 진입할 때만 한 번 발생 mouseover✅ (버블링 함) ✅ 요소 위에 올라갈 때마다 발생 (자식 포함)
💡 React의 이벤트 시스템은
mouseenter를 직접 사용하지 않음
- React에서는
onMouseEnter라고 쓰지만, 내부적으로는 실제로mouseover이벤트를 사용함- 하지만, 동작은
mouseenter처럼 구현되어 있음➡️ React는
mouseover이벤트를 써서onMouseEnter를 구현하지만, 자식 요소로 마우스를 옮겨도 다시 실행되지 않게 자동으로 걸러줌
🤔 React의
onMouseOver는 어떻게 작동하나?React의
onMouseOver는 그대로 브라우저의mouseover이벤트를 사용함
즉, 다음 특징을 그대로 가짐
특징 설명 버블링 O 자식 요소에서 발생해도 부모로 이벤트 전달됨 자식 요소 이동 시 재호출 O 마우스가 부모 요소 위에 있는 동안 자식 요소 위로 이동해도 계속 발생함
onMouseLeave : 마우스가 요소 밖으로 나갈 때동작 조건
onMouseOut과의 차이점)주요 특징
mouseleave 이벤트는 마우스가 요소 전체를 떠날 때 한 번만 발생함onMouseLeave를 사용하면 내부적으로 mouseleave가 아닌 mouseout을 사용하지만, 자식 요소 이동 시 중복 실행 안 되도록 자동 처리됨🤔
mouseleavevs.mouseout(실제 DOM 이벤트 기준)
이벤트 이름 버블링 여부 자식 요소 이동 시 재호출 언제 발생? mouseleave❌ (버블링 안 함) ❌ 요소를 벗어났을 때만 한 번 발생 mouseout✅ (버블링 함) ✅ 요소에서 마우스가 빠질 때마다 발생 (자식 포함)
💡 React의 이벤트 시스템은
mouseleave를 직접 사용하지 않음
- React에서는
onMouseLeave라고 쓰지만, 내부적으로는 실제로mouseout이벤트를 사용함- 하지만, 동작은
mouseleave처럼 구현되어 있음➡️ React는
mouseout이벤트를 써서onMouseLeave를 구현하지만, 자식 요소로 마우스를 옮겨도 다시 실행되지 않게 자동으로 걸러줌
onMouseEnter vs. onMouseOver| 구분 | onMouseEnter | onMouseOver |
|---|---|---|
| 이벤트 발생 시점 | 요소 진입 시 한 번 | 요소 또는 자식 요소 진입 시마다 |
| 버블링 | ❌ (실제 DOM 기준) | ✅ |
| 자식 요소 이동 시 | ❌ 재호출 안 됨 | ✅ 계속 호출됨 |
onMouseLeave vs. onMouseOut| 구분 | onMouseLeave | onMouseOut |
|---|---|---|
| 이벤트 발생 시점 | 요소를 벗어날 때 한 번 | 자식 포함 요소 벗어날 때마다 |
| 버블링 | ❌ (실제 DOM 기준) | ✅ |
| 자식 요소 이동 시 | ❌ 재호출 안 됨 | ✅ 계속 호출됨 |
onMouseEnter/onMouseLeave는 모바일 환경에서는 동작하지 않음 (터치 이벤트와 다름)onMouseOver과 onMouseOut은 자식 요소에 마우스가 들어가거나 나갈 때도 이벤트가 발생하므로, 불필요한 재렌더링/상태 업데이트가 발생할 수 있음호버 효과(Hover Effect) 제어
<div
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
>
{hovered ? "😄 Hovered!" : "🙂 Hover me!"}
</div>
:hover로 충분하지 않을 때, 동적인 동작(상태 변경, 애니메이션)과 연동하려면 JS 이벤트 핸들러가 필요함툴팁(Tooltip)이나 설명 박스 표시
<div
onMouseEnter={() => setShowTooltip(true)}
onMouseLeave={() => setShowTooltip(false)}
>
ℹ️ 정보
{showTooltip && <div className="tooltip">여기에 상세 정보</div>}
</div>
title 속성보다 더 예쁜 커스텀 툴팁을 만들 때 유용함애니메이션 트리거
<div
onMouseEnter={() => startAnimation()}
onMouseLeave={() => stopAnimation()}
>
애니메이션 요소
</div>
메뉴/서브메뉴 열기
<div
onMouseEnter={() => setMenuOpen(true)}
onMouseLeave={() => setMenuOpen(false)}
>
메뉴
{menuOpen && <ul className="submenu">서브 메뉴</ul>}
</div>
상태 변경을 통한 조건부 렌더링
<div
onMouseEnter={() => setActive(true)}
onMouseLeave={() => setActive(false)}
>
{active ? <ComponentA /> : <ComponentB />}
</div>
마우스 좌표 추적
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;
isHovered 상태가 true가 되면서 AI 툴팁이 뜸isHovered 상태가 false가 되면서 AI 툴팁이 사라짐showQuestionnaire 상태가 원래의 반대가 됨