개발 노트
frontend
2025
3
React Hooks 고급 패턴과 최적화 전략

React Hooks 고급 패턴과 최적화 전략

React Hooks는 함수형 컴포넌트에서 상태 관리와 생명주기 기능을 구현할 수 있게 해주는 강력한 도구입니다. 이 글에서는 React Hooks의 고급 사용 패턴과 성능 최적화 전략을 깊이 있게 탐구해보겠습니다.

1. 커스텀 Hooks로 로직 추상화

커스텀 Hooks는 컴포넌트 로직을 재사용 가능한 함수로 추출할 수 있게 해줍니다.

// 데이터 페치를 위한 커스텀 Hook
function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
 
  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(url);
        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err);
      } finally {
        setLoading(false);
      }
    };
 
    fetchData();
  }, [url]);
 
  return { data, loading, error };
}

2. useCallback과 useMemo로 불필요한 렌더링 방지

function ExpensiveComponent({ data }) {
  // 복잡한 계산을 메모이제이션
  const processedData = useMemo(() => {
    return data.map(item => {
      // 무거운 계산 로직
      return complexCalculation(item);
    });
  }, [data]);
 
  // 콜백 함수 메모이제이션
  const handleClick = useCallback(() => {
    // 클릭 핸들러 로직
  }, []);
 
  return (
    <div>
      {processedData.map(item => (
        <div key={item.id}>{item.processedValue}</div>
      ))}
    </div>
  );
}

3. useReducer로 복잡한 상태 관리

function todoReducer(state, action) {
  switch (action.type) {
    case 'ADD_TODO':
      return [...state, { 
        id: Date.now(), 
        text: action.payload, 
        completed: false 
      }];
    case 'TOGGLE_TODO':
      return state.map(todo => 
        todo.id === action.payload 
          ? { ...todo, completed: !todo.completed }
          : todo
      );
    default:
      return state;
  }
}
 
function TodoList() {
  const [todos, dispatch] = useReducer(todoReducer, []);
 
  const addTodo = (text) => {
    dispatch({ type: 'ADD_TODO', payload: text });
  };
 
  const toggleTodo = (id) => {
    dispatch({ type: 'TOGGLE_TODO', payload: id });
  };
 
  return (
    // Todo 렌더링 로직
  );
}

4. useContext와 성능 최적화

const ThemeContext = React.createContext();
 
function ThemeProvider({ children }) {
  const [theme, setTheme] = useState('light');
 
  // useMemo로 컨텍스트 값 최적화
  const value = useMemo(() => ({
    theme,
    toggleTheme: () => setTheme(prev => prev === 'light' ? 'dark' : 'light')
  }), [theme]);
 
  return (
    <ThemeContext.Provider value={value}>
      {children}
    </ThemeContext.Provider>
  );
}

5. 성능 모니터링과 최적화 팁

  • React.memo()로 컴포넌트 렌더링 최적화
  • 큰 목록의 경우 react-windowreact-virtualized 고려
  • 불필요한 의존성 배열 최소화
  • 복잡한 상태 로직은 useReducer로 관리

결론

React Hooks는 강력하지만, 현명하게 사용해야 합니다. 성능과 가독성 사이의 균형을 찾는 것이 중요합니다. 과도한 최적화는 오히려 코드를 복잡하게 만들 수 있으니 주의해야 합니다.