TIL - 20251023

juni·2025년 10월 23일

TIL

목록 보기
161/316

1023 React 기초 복습 (3/3): Side Effects, 최적화, 라우팅


✅ 1. Side Effects와 useEffect Hook

  • Side Effect (부수 효과)란 React 컴포넌트의 주된 역할인 UI 렌더링 외에, 외부 세계와 상호작용하는 모든 작업을 의미합니다.

  • 주요 Side Effects 예시:

    • HTTP 요청 (데이터 fetching)
    • 타이머 설정 (setTimeout, setInterval)
    • DOM 직접 조작
    • 브라우저 API(e.g., localStorage) 사용
  • useEffect Hook: 함수형 컴포넌트에서 이러한 Side Effects를 처리하기 위해 사용하는 Hook입니다. useEffect에 전달된 함수는 컴포넌트가 렌더링된 후(DOM에 반영된 후)에 실행됩니다.

➕ 의존성 배열 (Dependency Array)

  • useEffect의 두 번째 인자로 전달되는 배열입니다. 이 배열의 역할은 useEffect언제 다시 실행될지를 결정하는 것입니다.
    • [] (빈 배열): 컴포넌트가 처음 마운트될 때 한 번만 실행됩니다. (초기 데이터 로딩에 주로 사용)
    • [state, props]: 배열 안의 값이 변경될 때마다 useEffect가 다시 실행됩니다.
    • 생략: 컴포넌트가 리렌더링될 때마다 useEffect가 실행됩니다. (의도치 않은 무한 루프를 유발할 수 있어 주의 필요)

➕ Cleanup 함수 (정리 함수)

  • useEffect가 반환(return)하는 함수를 Cleanup 함수라고 합니다. 이 함수는 컴포넌트가 DOM에서 제거되기 직전(unmount), 또는 useEffect가 다시 실행되기 직전에 호출되어, 이전에 실행했던 Side Effect를 "정리"하는 역할을 합니다. 메모리 누수(Memory Leak)를 방지하기 위해 필수적입니다.

    useEffect(() => {
      // Side Effect: 1초마다 콘솔에 로그 출력
      const timerId = setInterval(() => {
        console.log('Timer running...');
      }, 1000);
    
      // Cleanup 함수: 컴포넌트가 사라질 때 타이머를 제거
      return () => {
        clearInterval(timerId);
      };
    }, []); // 처음 마운트될 때만 실행

✅ 2. React 렌더링 최적화

  • React는 부모 컴포넌트가 리렌더링되면 기본적으로 모든 자식 컴포넌트도 리렌더링합니다. 이는 props가 변경되지 않은 자식에게는 불필요한 연산이므로, 성능 저하의 원인이 될 수 있습니다.

➕ 주요 최적화 도구

  1. React.memo:

    • 컴포넌트를 감싸는 고차 컴포넌트(HOC)로, props가 변경되었을 때만 해당 컴포넌트를 리렌더링하도록 만듭니다.
    • props가 자주 변경되지 않는 무거운 UI 컴포넌트에 적용하면 효과적입니다.
  2. useCallback:

    • 문제: 컴포넌트가 리렌더링될 때마다 내부에 선언된 함수는 새로운 함수로 다시 생성됩니다. 이 함수를 memo로 감싼 자식에게 prop으로 전달하면, prop이 변경된 것으로 간주되어 memo가 무력화됩니다.
    • 해결: useCallback은 함수 자체를 메모이제이션(memoization)하여, 의존성 배열의 값이 변경되지 않는 한 함수를 재생성하지 않고 재사용하게 해주는 Hook입니다.
  3. useMemo:

    • 함수가 아닌, 값(value)을 메모이제이션합니다.
    • 복잡하고 비용이 큰 계산(e.g., 배열 필터링, 정렬)의 결과를 저장해두고, 의존성 배열의 값이 변경될 때만 해당 계산을 다시 수행합니다.

✅ 3. React Router: 클라이언트 사이드 라우팅

  • 싱글 페이지 애플리케이션(SPA)에서 사용자가 URL을 통해 여러 페이지를 이동하는 것처럼 느끼게 해주는 라이브러리입니다. 실제로는 페이지를 새로고침하지 않고, URL에 맞는 컴포넌트만 동적으로 렌더링합니다.

➕ 주요 컴포넌트 및 Hooks

  1. createBrowserRouter & <RouterProvider>:

    • 최신 React Router(v6.4+)에서는 createBrowserRouter를 사용하여 라우트 설정을 객체 형태로 정의하고, <RouterProvider>를 통해 앱에 라우터를 제공합니다.
  2. <Link>:

    • 페이지를 새로고침하지 않고, 지정된 경로(to)로 URL만 변경하여 클라이언트 사이드에서 페이지를 전환합니다. (<a> 태그 대신 사용)
  3. <Outlet />:

    • 중첩 라우팅(Nested Routes)에서 사용되며, 부모 라우트 컴포넌트 내에서 자식 라우트 컴포넌트가 렌더링될 위치를 지정합니다. (e.g., 공통 레이아웃)
  4. useParams:

    • URL의 동적 파라미터(e.g., /products/:productId) 값을 객체로 가져오는 Hook입니다.
  5. useNavigate:

    • 로그인 성공 후 특정 페이지로 이동시키는 등, 코드 내에서 프로그래매틱하게 페이지를 이동시켜야 할 때 사용하는 Hook입니다.
    // App.js - 라우터 설정 예시
    import { createBrowserRouter, RouterProvider, Outlet } from 'react-router-dom';
    import HomePage from './pages/Home';
    import ProductsPage from './pages/Products';
    import RootLayout from './layouts/RootLayout';
    
    const router = createBrowserRouter([
      {
        path: '/',
        element: <RootLayout />, // 공통 레이아웃
        children: [
          { path: '/', element: <HomePage /> },
          { path: '/products', element: <ProductsPage /> },
        ],
      },
    ]);
    
    function App() {
      return <RouterProvider router={router} />;
    }
    
    // layouts/RootLayout.js
    function RootLayout() {
      return (
        <>
          <MainNavigation />
          <main>
            <Outlet /> {/* 자식 컴포넌트가 여기에 렌더링됨 */}
          </main>
        </>
      );
    }

📌 요약

  • useEffect는 데이터 fetching과 같은 Side Effects를 처리하는 Hook이며, 의존성 배열로 실행 시점을 제어하고 Cleanup 함수로 메모리 누수를 방지해야 합니다.
  • 불필요한 리렌더링을 방지하여 성능을 최적화하기 위해, React.memo로 컴포넌트를, useCallback으로 함수를, useMemo로 값을 메모이제이션할 수 있습니다.
  • React Router는 SPA에서 페이지 이동을 구현하는 표준 라이브러리이며, <Link>로 페이지를 전환하고 <Outlet />으로 중첩 레이아웃을 구성하며, useParams와 같은 Hook을 통해 라우팅 정보에 접근합니다.

0개의 댓글