무엇에 반응해야 하는지 나누기

chat room 연결 Effect에서 roomIdtheme을 모두 읽습니다. room이 바뀌면 연결을 다시 만들어야 하지만 theme 변경은 다음 알림 색만 바꾸면 됩니다. 둘을 같은 dependency로 두면 theme을 바꿀 때마다 불필요한 재연결이 생깁니다.

useEffectEvent는 Effect 안에서 호출하는 비반응 로직이 최신 props와 state를 읽게 하지만, 반응해야 하는 dependency를 숨기는 용도로 사용하면 안 됩니다.

Effect Event의 적용 경계

Effect Event는 Effect 또는 다른 Effect Event 안에서만 호출합니다. 최신 committed props와 state를 읽지만 일반 click handler나 child component에 전달하는 callback 대용이 아닙니다. 연결 identity를 결정하는 roomId는 계속 dependency로 남겨야 합니다.

import { useEffect, useEffectEvent } from 'react';

function ChatRoom({ roomId, theme }) {
  const onConnected = useEffectEvent(() => {
    showNotification('연결되었습니다', theme);
  });

  useEffect(() => {
    const connection = createConnection(roomId);
    connection.on('connected', onConnected);
    connection.connect();
    return () => connection.disconnect();
  }, [roomId]);
}

의존성을 숨기지 않았는지 확인

값이 바뀔 때 외부 system을 다시 동기화해야 한다면 그 값은 Effect dependency입니다. useEffectEvent로 옮겨 linter를 조용하게 만들면 오래된 subscription이나 누락된 analytics 같은 오류를 숨길 수 있습니다. test에서는 theme 변경 시 connect count가 늘지 않으면서 다음 알림은 새 theme을 쓰는지, roomId 변경 시에는 cleanup 뒤 새 연결이 정확히 한 번 생기는지 확인합니다. React 19.2와 현재 eslint-plugin-react-hooks 규칙도 함께 맞춥니다.

공식 문서

현재 React와 hooks linter version에서 호출 위치와 dependency 규칙을 확인합니다.