프레임워크와 라이브러리/React

[Advanced React Hooks] useReducer부터 useImperativeHandle까지

Dachaes 2025. 4. 11. 23:47
728x90
반응형

Advanced React Hooks

React를 어느 정도 사용해본 개발자라면 useState, useEffect 같은 기본 훅은 익숙할 것입니다. 하지만 복잡한 상태 관리나 라이프사이클 제어, 퍼포먼스 개선 등 더 세밀한 제어가 필요할 땐 고급 훅(Advanced Hooks)이 큰 도움이 됩니다.

 


1.  useReducer  (복잡한 상태 관리를 위한 훅)

언제 사용하나요?

  • useState로는 관리하기 힘든 복합 상태
  • 상태 전이 로직을 명확하게 정의하고 싶을 때

기본 구조

const [state, dispatch] = useReducer(reducer, initialState);
예제
const initialState = { count: 0 };

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      return state;
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
    </>
  );
}
  • useReducer는 특히 Redux 스타일 로직 분리를 선호하는 경우 유용합니다.

 


2. useImperativeHandle (부모가 자식 컴포넌트의 메서드 직접 호출 가능)

언제 사용하나요?

  • 부모 컴포넌트가 자식 컴포넌트의 내부 메서드를 호출하고 싶을 때
  • forwardRef와 함께 사용

예제

const initialState = { count: 0 };

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      return state;
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
    </>
  );
}

 

  • 이 훅은 일반적으로 DOM을 직접 제어해야 하는 라이브러리 컴포넌트 제작 시 사용됩니다.

 


3.  useLayoutEffect (DOM 변경 직후 동기 실행)

useEffect와의 차이점?


항목 useEffect useLayoutEffect
실행 시점 화면 그린 후 화면 그리기 전
실행 방식 비동기 동기
용도 API 호출, 로깅 등 레이아웃 계산, 스크롤 제어 등

예제

useLayoutEffect(() => {
  const width = ref.current.getBoundingClientRect().width;
  console.log('요소 너비:', width);
}, []);
  • useLayoutEffect는 레이아웃이 중요한 컴포넌트의 초기 세팅에 적합하지만, 불필요하게 사용하면 성능에 악영향을 줄 수 있습니다

 


4. useDebugValue (커스텀 훅 디버깅 지원)

언제 사용하나요?

  • 커스텀 훅의 내부 상태를 React DevTools에서 보기 좋게 표현하고 싶을 때

예제

function useOnlineStatus() {
  const [online, setOnline] = useState(navigator.onLine);

  useEffect(() => {
    const handleOnline = () => setOnline(true);
    const handleOffline = () => setOnline(false);
    window.addEventListener('online', handleOnline);
    window.addEventListener('offline', handleOffline);
    return () => {
      window.removeEventListener('online', handleOnline);
      window.removeEventListener('offline', handleOffline);
    };
  }, []);

  useDebugValue(online ? '온라인' : '오프라인');

  return online;
}
  • 디버깅용으로만 사용되며 실제 앱 성능에는 영향이 없습니다.
 

5.  마무리

기본 훅만으로도 많은 기능을 구현할 수 있지만, 고급 훅은 다음과 같은 상황에서 강력한 도구가 됩니다.

  • 상태가 복잡하거나 조건이 많을 때 (useReducer)
  • DOM 조작과 레이아웃이 중요한 컴포넌트일 때 (useLayoutEffect, useImperativeHandle)
  • 커스텀 훅의 디버깅과 가시성이 필요할 때 (useDebugValue)

리액트를 한 단계 더 깊이 이해하고 싶다면, 고급 훅을 익혀 더 유연하고 성능 좋은 컴포넌트 설계에 도전해보세요.

함께 보면 좋은 자료

블로그 글 :

 

[React Hooks] useState부터 커스텀 훅까지

React HooksReact 16.8부터 등장한 Hooks(훅)은 함수형 컴포넌트에서도 상태 관리와 사이드 이펙트를 다룰 수 있게 해주며, 컴포넌트 구조를 더욱 직관적으로 바꿨습니다. 이 글에서는 자주 사용되는 기

dachaes-devlogs.tistory.com

 

[React Custom Hooks] 로직을 재사용하는 가장 React스러운 방법

React Custom Hooks리액트 훅을 사용하다 보면, useState, useEffect, useRef 등 반복되는 로직이 여러 컴포넌트에 등장하는 경우가 많습니다. 이때 공통 로직을 재사용하고, 컴포넌트는 UI에만 집중할 수 있

dachaes-devlogs.tistory.com

 


728x90
반응형