Post

[GitPulse #1] 프로젝트 뼈대 구축: React Query, Router, throttle

[GitPulse #1] 프로젝트 뼈대 구축: React Query, Router, throttle

✅ 오늘의 목표

  • React Query 전역 설정 및 Devtools 연결
  • throttle 유틸 함수 작성
  • React Router 구성 (라우터 트리, 레이아웃 적용)
  • 사이드바 구현

🧩 문제 상황 / 배경

프로젝트 초기 세팅 중, 다음과 같은 상황이 있었습니다:

  • 서버 상태를 효율적으로 관리하기 위해 React Query 도입이 필요했습니다.
  • 빠르게 발생하는 resize 이벤트에 throttle을 적용해 성능을 최적화해야 했습니다.
  • 전체 페이지 구조를 라우터 트리로 명확히 구성할 필요가 있었습니다.
  • 사이드바가 반응형으로 동작하도록 구현해야 했습니다.

🛠️ 해결 과정 / 코드 정리

🔸 React Query 전역 설정

1
npm i @tanstack/react-query @tanstack/react-query-devtools
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { RouterProvider } from "react-router-dom";
import { router } from "./router/index";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";

// 전역에서 Query를 관리할 QueryClient 생성
const queryClient = new QueryClient();

createRoot(document.getElementById("root")).render(
  <StrictMode>
    <QueryClientProvider client={queryClient}>
      <RouterProvider router={router} />
      {/* 개발 중에는 ReactQueryDevtools로 상태 확인 가능 */}
      {import.meta.env.DEV && <ReactQueryDevtools initialIsOpen={false} />}
    </QueryClientProvider>
  </StrictMode>
);
  • React Query란? 비동기 상태를 쉽게 다루도록 도와주는 라이브러리
  • QueryClient는 React Query의 핵심 객체로, 데이터를 fetch하고 cache를 관리
  • QueryClientProvider를 통해 전역으로 상태 관리가 가능하며, 컴포넌트 어디서든 데이터를 선언적으로 가져옴

TanStack Query(React Query) 더 자세히 알아보기


🔸 throttle 유틸 함수

src/utils/feature.js

1
2
3
4
5
6
7
8
9
10
11
// 쓰로틀 : 일정 시간 동안 한 번만 실행. 함수(함수, 대시시간)
export const throttle = (func, limit = 300) => {
  let inThrottle;
  return function (...args) {
    if (!inThrottle) {
      func.apply(this, args);
      inThrottle = true;
      setTimeout(() => (inThrottle = false), limit);
    }
  };
};
  • 지정한 시간 동안 한 번만 함수가 실행되도록 제어
  • resize, scroll 등에 주로 사용

debounce와의 차이점

구분throttledebounce
동작 방식일정 시간 간격으로 주기적으로 실행마지막 이벤트 발생 후 일정 시간 지나면 실행
사용 예시scroll, resize, mousemoveinput, search, autosave
실행 타이밍주기적으로 실행됨사용자가 멈춘 후 실행됨

🔸 React Router 구성

src/router/index.jsx

1
2
3
4
5
6
7
8
9
10
11
export const router = createBrowserRouter([
  {
    path: "/",
    element: <DefaultLayout />,
    errorElement: <div>에러</div>,
    children: [
      { index: true, element: <LoginPage /> },
      { path: "/organization", element: <OrganizationPage /> },
    ],
  },
]);
  • DefaultLayout을 공통 레이아웃으로 설정하고, 그 하위에 페이지들을 children으로 구성
  • index: true/ 경로에서 로그인 페이지가 보이도록 설정
1
2
3
4
5
6
7
8
9
const CustomNavLink = ({ to, label, icon }) => (
  <NavLink
    className={({ isActive }) => (isActive ? `${css.active}` : "")}
    to={to}
  >
    <i className={`bi ${icon}`}></i>
    <p>{label}</p>
  </NavLink>
);
  • CustomNavLink로 컴포넌트를 분리하여 코드 중복 제거
  • props로 to, label, icon만 넘겨주면 되므로 재사용성과 가독성 향상

🔸 반응형 사이드바 구현

src/common/SideBar.jsx

1
2
3
4
5
6
7
8
9
10
11
12
const handleResize = throttle(() => {
  if (window.innerWidth > 1100) {
    setIsOn(false);
  }
}, 1000);

useEffect(() => {
  window.addEventListener("resize", handleResize);
  return () => {
    window.removeEventListener("resize", handleResize);
  };
}, [handleResize]);
  • 화면 너비가 1100px 초과 시 사이드바 자동 닫힘
  • throttle로 resize 이벤트 최적화
  • NavLink를 사용해 각 페이지로 이동할 수 있도록 구성

작업 결과물

💡 핵심 개념 요약

개념설명
React Query서버 상태를 캐싱하고 쉽게 관리할 수 있는 라이브러리
QueryClientReact Query 전역 상태 관리 객체
throttle(func, ms)지정 시간마다 한 번만 함수 실행
createBrowserRouterReact Router v6의 라우터 생성 함수
RouterProvider라우터 트리를 렌더링하는 Provider 컴포넌트

결과

  • 프로젝트 초기 구조를 세팅하면서 React Query, Router, 사이드바를 한 번에 정리할 수 있었습니다.
  • throttle 개념을 실습을 통해 명확히 이해할 수 있었고, resize 최적화에 바로 적용해 보았습니다.
  • 반복적인 UI 코드는 CustomNavLink로 분리하여 가독성을 높이고 재사용성을 확보했습니다.

Reference

이 포스트는 아래 게시글의 정보 및 이미지가 사용되었습니다.

  1. TanStack Query 공식 문서
  2. React Router v6 공식 문서

END

This post is licensed under CC BY 4.0 by the author.