HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
🤎
프론트엔드 데브코스 5기 교육생
/
소인성팀
소인성팀
/
팀프로젝트-모모
팀프로젝트-모모
/
💻
공부
/
이벤트 핸들러의 종속성

이벤트 핸들러의 종속성

태그
날짜
Jan 12, 2024
사람
const [isDragging, setIsDragging] = useState(false); const handleMouseUp = (event: MouseEvent) => { if (isDragging) { setIsDragging(false); onMouseUp(event); } }; useEffect(() => { window.addEventListener('mouseup', handleMouseUp); return () => window.removeEventListener('mouseup', handleMouseUp); }, []);
 
handleMouseUp 이벤트 핸들러를 window 전역 객체에 등록하는 간단한 코드이지만 정상적으로 동작하지 않습니다.
isDragging 이 변경되어 리랜더링 되면 handleMouseUp 은 참조가 바뀌게되고 useEffect 안에서 window 전역 객체가 변경되기 전 handleMouseUp 을 이벤트 핸들러로 등록하고 있기 때문에 발생하는 문제입니다.
 
useEffect(() => { window.addEventListener('mouseup', handleMouseUp); return () => window.removeEventListener('mouseup', handleMouseUp); }, [isDragging]);
 
간단하게 isDragging 을 useEffect 종속성 배열에 넣으면 isDragging이 변경될 때마다 이벤트 핸들러도 같이 재등록시키는 방법이 있습니다.
 
그렇다면 이벤트 핸들러를 useCallback 으로 감쌌을때는 어떻게 동작할까요?
 
const handleMouseUp = useCallback((event: MouseEvent) => { if (isDragging) { setIsDragging(false); onMouseUp(event); } }, []); useEffect(() => { window.addEventListener('mouseup', handleMouseUp); return () => window.removeEventListener('mouseup', handleMouseUp); }, [isDragging]);
 
이 코드도 정상적으로 동작하지 않습니다.
useEffect 안에서 isDragging의 값이 변하여 이벤트 핸들러를 재등록 하더라도 이벤트 핸들러 자체가 변하지 않기 때문입니다.
이 말인즉슨, handleMouseUp 안의 isDragging은 밖에서 무슨 일이 일어나든 초기값을 가진다는 의미입니다.
 
이 문제를 해결하는 방법도 간단합니다.
 
const handleMouseUp = useCallback((event: MouseEvent) => { if (isDragging) { setIsDragging(false); onMouseUp(event); } }, [isDragging]); useEffect(() => { window.addEventListener('mouseup', handleMouseUp); return () => window.removeEventListener('mouseup', handleMouseUp); }, [handleMouseUp]);
 
위와 같이 handleMouseUp 이벤트 핸들러는 useCallback의 종속성 배열에 isDragging 을 넣고,
useEffect의 종속성 배열에는 isDragging의 변경으로 바뀐 handleMouseUp을 넣어주면 깔끔쓰하게 해결됩니다.
 
 

정리

  1. JSX에 직접 넣는 이벤트 핸들러(onClick 등) 말곤 전부 종속성 관리를 해줘야한다.
  1. useCallback으로 감싸진 이벤트 핸들러는 자체적으로 종속성 관리를 하되 만일 useEffect에서 dom 이벤트 리스너에 등록한다면 useCallback 함수를 useEffect의 종속성으로 넣어야한다.