훅(Hook)

안전하게 붙이고 자동 정리하는 useEventListener 훅

window·document·엘리먼트에 이벤트를 선언적으로 붙이고, 언마운트 시 자동으로 정리하는 훅. ref 패턴으로 stale closure까지 막습니다.

ReactTypeScriptuseRefuseEffectaddEventListener
라이브 데모
새 탭에서 열기
데모 불러오는 중…

제작 과정

한 줄 요약

addEventListener/removeEventListener를 매번 짝 맞춰 쓰는 대신, 한 줄로 붙이고 자동으로 정리하는 훅입니다.

이럴 때 필요해요

스크롤키보드리사이즈 같은 전역 이벤트를 다룰 때 useEffect 안에서 add/remove를 직접 쓰다 보면 cleanup을 빠뜨리거나, 핸들러 안의 state가 옛 값을 가리키는(stale closure) 버그가 잘 생깁니다. 이 훅은 그 두 함정을 구조적으로 막아줍니다.

어떻게 동작하나

  1. 핸들러를 ref에 저장하고 매 렌더 갱신 구독은 그대로 둔 채 항상 최신 핸들러를 호출합니다.

  2. effect는 eventNametargetenabled가 바뀔 때만 재구독하고, 정리 함수에서 removeEventListener를 호출합니다.

  3. target은 window(기본)document엘리먼트ref를 모두 받고, enabled=false면 아예 구독하지 않습니다.

놓치기 쉬운 것

  • 핸들러를 deps에 넣으면 매 렌더 재구독됩니다 ref 패턴으로 피합니다.

  • options에 인라인 객체를 넘기면 매번 새 참조라 재구독되니 상수로 두세요.

  • SSR에서 window가 없으므로 접근 전에 가드가 필요합니다.

이런 곳에 써요

  • 전역 단축키, 스크롤/리사이즈 추적

  • 바깥 클릭 감지, 온라인/오프라인 상태

소스 코드

· 데모 페이지에서 자동 추출
import type { Metadata } from "next";
import { UseEventListenerDemo } from "./-components/UseEventListenerDemo";

export const metadata: Metadata = {
  title: "useEventListener — 선언적 이벤트 구독 훅 (데모)",
  description:
    "window·document·엘리먼트·ref에 이벤트를 안전하게 붙이고 자동 cleanup하는 useEventListener 훅. ref로 stale closure 방지, enabled로 on/off.",
  robots: { index: false, follow: false },
};

export default function Page() {
  return (
    <main className="flex min-h-[100dvh] items-center justify-center bg-white">
      <UseEventListenerDemo />
    </main>
  );
}
16조회수

댓글