노트

useEffectEvent

useEffectEvent

프론트엔드#react · 연결된 개념 3개

쉽게 말하면

useEffectEvent는 Effect 안에서 최신 값을 읽기만 하고, 그 값이 바뀌었다고 Effect를 다시 돌리지는 않게 하는 함수를 만들어요. 통화 중에 상대 연락처 메모가 바뀌었다고 전화를 끊고 다시 걸 필요는 없는 것처럼요.

비유의 한계 의존성 경고를 숨기는 도구가 아니에요. url처럼 바뀌면 다시 연결해야 하는 값은 의존성에 그대로 두고, 최신 값을 읽기만 하는 부분만 빼야 해요. 렌더 중에 부르거나 자식에게 넘기면 안 돼요.

useEffectEvent는 Effect 안에서 부르되 의존성 배열(Dependency Array)에는 넣지 않는 이벤트 함수를 만드는 훅이다. 항상 최신 props·state를 읽지만, 그 값이 바뀐다고 Effect가 다시 실행되지는 않는다. React 19.2에서 정식이 됐다(2026 기준).

// 전: onConnect가 바뀔 때마다 연결을 끊었다 다시 맺는다
useEffect(() => {
  const conn = createConnection(url)
  conn.on('connected', () => onConnect(conn))
  conn.connect()
  return () => conn.disconnect()
}, [url, onConnect])
 
// 후: url이 바뀔 때만 재연결, onConnect는 항상 최신
const onConnected = useEffectEvent(onConnect)
useEffect(() => {
  const conn = createConnection(url)
  conn.on('connected', () => onConnected(conn))
  conn.connect()
  return () => conn.disconnect()
}, [url])
  • 핵심은 Effect 안의 로직을 둘로 나누는 것이다. 바뀌면 다시 동기화해야 하는 값은 의존성에 두고, 최신 값을 읽기만 하면 되는 부분만 Effect Event로 뺀다
  • 의존성 경고를 숨기는 용도로 쓰면 안 된다. 페이지 방문 로그를 pageUrl 없이 []로 돌리면 URL(Uniform Resource Locator)이 바뀌어도 로그가 안 남는다. 다시 실행돼야 할 값이면 의존성에 둔다
  • 제약
    • Effect 안이나 다른 Effect Event 안에서만 호출한다. 렌더 중에 부르거나 다른 컴포넌트·훅에 넘기지 않는다
    • 반환된 함수를 의존성 배열에 넣지 않는다
    • 이벤트 핸들러나 자식에게 넘길 콜백이 필요하면 일반 함수(또는 useCallback)를 쓴다

Effect를 아예 안 쓰는 방법이 먼저다(Effect가 필요 없는 경우). 배경은 부수 효과와 Effect.

출처: React - useEffectEvent

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • useEffect와 useLayoutEffect

    useLayoutEffect는 useEffect와 같은 일을 하지만, 브라우저가 화면을 그리기(Paint) 전에 동기적으로 실행된다. useEffect는 그린 뒤에 실행된다.

  • 서버 렌더에서 훅이 하는 일

    서버 렌더(Server-Side Rendering, SSR)에서도 컴포넌트 함수는 실제로 호출되고, 그 안의 훅도 호출은 된다. 다만 서버에는 커밋(DOM 반영)이 없어서, 렌더 중 동기적으로 값을 계산하는 훅만 일하고 커밋 뒤에 도는 훅은 아무것도 하지 않는다. "이 훅은 클라이언트에서만 동작한다"는 말은 대개 "Effect 안의 일은 클라이언트에서만 일어난다"는 뜻이다.

  • React의 규칙과 렌더 순수성

    Rules of React는 React가 올바르게 동작하고 최적화하기 위해 코드가 지켜야 하는 규칙으로, 공식 문서가 세 가지로 정리한다. 핵심은 렌더가 순수한 계산이어야 한다는 것이다.

  • useSyncExternalStore

    useSyncExternalStore는 React 밖에 있는 상태(외부 스토어(External Store), 브라우저 API(Application Programming Interface))를 구독해 컴포넌트와 동기화하는 훅이다. 동시성 렌더링(Concurrent Rendering)에서도 모든 컴포넌트가 같은 스냅샷을 보게 보장해 tearing을 막는다(React 18+).

  • 이벤트 버블링·캡처링과 위임

    DOM 이벤트는 대상 요소에서만 끝나지 않고 트리를 따라 전파된다. 루트에서 대상까지 내려가는 캡처링(Capturing Phase), 대상에서 처리되는 타깃 단계(Target Phase), 대상에서 루트로 올라가는 버블링(Bubbling Phase) 순서다.

보기 옵션