o-ohi-code 님의 블로그

React 렌더링 과정 본문

프로젝트/React

React 렌더링 과정

o-ohi-code 2025. 4. 15. 12:31

React 렌더링

React 프로젝트를 진행하던 중, 
예상치 못한 로그인 오류가 계속 발생해서 원인을 추적하게 되었다.

그러다 보니 자연스럽게 react 의 렌더링 과정에 대해 알 게 되었고, 
결국 그 렌더링 방식이 로그인 오류의 핵심 원인이었다는 것을 깨닫게 되어 정리를 해보았다.

 

React의 렌더링 과정에는 크게 2단계로 나뉜다.

Render Phase (렌더 준비 단계)

  • 컴포넌트 함수 호출됨
  • JSX 평가 → 가상 DOM 트리 구성
  • useState, useEffect, useRef 등 Hook들이 등록만 됨 (실행 X)
  • 렌더링은 순수해야 함 (랜덤값, API 호출, 상태 업데이트 등 ❌)

Commit Phase (렌더 반영 단계)

  • 실제 DOM 업데이트가 여기서 발생
  • useLayoutEffect → useEffect 순서로 실행됨
  • 이 때 effect는 하위 → 상위 순서로 깊이 우선(DFS) 실행됨
  • 리액트는 이 때 Fiber를 통해 변경된 DOM만 최소 반영

ex) 간단한 예시를 들어 설명하자면

import { Routes, Route, Navigate,  } from 'react-router-dom';
import React, { useState, useEffect } from 'react'; // ✅ useEffect 추가
import BoardPage from './pages/BoardPage';
import WritePage from './pages/WritePage';
import LoginPage from './pages/loginPage';
import BoardDetailPage from './pages/BoardDetailPage'; 


function PrivateRoute({ isLoggedIn, children }) {
  return isLoggedIn ? children : <Navigate to="/login" />
}

function App() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const [checkedLogin, setCheckedLogin] = useState(false);

  useEffect(() => {
    const token = localStorage.getItem("accessToken");
    if (token) {
      setIsLoggedIn(true);
    }
    setCheckedLogin(true); // ✅ 복구 완료 표시
  }, []);

  if (!checkedLogin) return <div>로딩 중...</div>;


  return (
    <Routes>
      <Route path="/" element={<Navigate to="/login" />} />
      <Route path="/login" element={<LoginPage setIsLoggedIn={setIsLoggedIn} />} />
      <Route
        path="/board"
        element={
          <PrivateRoute isLoggedIn={isLoggedIn}>
            <BoardPage />
          </PrivateRoute>
        }
      />
      <Route
        path="/write"
        element={
          <PrivateRoute isLoggedIn={isLoggedIn}>
            <WritePage />
          </PrivateRoute>
        }
      />
      <Route
        path="/board/:boardId"
        element={
          <PrivateRoute isLoggedIn={isLoggedIn}>
            <BoardDetailPage />
          </PrivateRoute>
        }
      />
    </Routes>
    
  );
}

export default App;

1단계: 브라우저 새로고침(F5)

  • 브라우저가 index.html, bundle.js를 다시 불러옴
  • React 앱이 새로 시작됨
  • App() 컴포넌트가 다시 호출됨

 

2단계: App 컴포넌트 최초 실행 (Render Phase 시작)

  • useState 두 개가 실행됨
    • isLoggedIn = false
    • checkedLogin = false
  • 이제 JSX return 부분이 실행됨

 

3단계: 조건부 렌더링 평가

if (!checkedLogin) return <div>로딩 중...</div>;
  • 현재 checkedLogin === false 이므로
  • <Routes> 부분은 아예 실행되지 않음
  • BoardPage, WritePage, PrivateRoute, useEffect, saga 등 모두 실행 ❌

👉 이게 바로 "렌더 차단"이 작동한 순간!

4단계: Commit Phase - useEffect 실행

useEffect(() => {
  const token = localStorage.getItem("accessToken");
  if (token) setIsLoggedIn(true);
  setCheckedLogin(true);
}, []);
  • 이 코드는 브라우저에 렌더된 후 비동기적으로 실행됨
  • localStorage에서 토큰을 꺼내서 로그인 여부 복구
  • setIsLoggedIn(true), setCheckedLogin(true) → 상태 업데이트 발생

5단계: 상태 업데이트로 인해 App이 다시 렌더링

  • 이번엔 checkedLogin === true
  • 조건문 통과!

6단계: <Routes> 렌더링됨

<Routes>
  <Route path="/board" element={
    <PrivateRoute isLoggedIn={isLoggedIn}>
      <BoardPage />
    </PrivateRoute>
  } />
</Routes>
  • 이제 진짜로 BoardPage, PrivateRoute, LoginPage 등 필요한 컴포넌트들이 렌더링됨
  • 그 안의 useEffect, redux dispatch, saga들도 이제 실행됨!

7단계: PrivateRoute 동작

function PrivateRoute({ isLoggedIn, children }) {
  return isLoggedIn ? children : <Navigate to="/login" />;
}
  • isLoggedIn === true → children(=BoardPage 등) 렌더 통과
  • 로그인 상태에 따라 정상 페이지 or 로그인 페이지 분기

8단계: 최종 페이지 렌더링 완료

  • 로그인 상태 복구 완료
  • 페이지 컴포넌트 정상 렌더
  • 내부 API 호출, saga, 데이터 로딩 등 이제야 실행

정리하면

📦 App() 호출
  └ useState 초기화: isLoggedIn=false, checkedLogin=false
  └ useEffect 등록
  └ return <로딩 중...> (조건부 렌더링 차단)

🔁 Commit Phase
  └ useEffect 실행 → 토큰 복구 → 상태 업데이트

🔁 상태 변경 → App() 재렌더
  └ checkedLogin = true
  └ <Routes> 평가됨
    └ <PrivateRoute> 실행
      └ isLoggedIn = true → children 통과
      └ <BoardPage> 렌더됨
        └ 내부 useEffect, saga, dispatch 동작 시작

 

이 구조의 장점

 하위 컴포넌트 초기 실행 방지,

 렌더링이 끝난 후 토큰만 복원 가능,

 최종적인 로그인 상태 기반 라우팅/페이지 전환 가능 

 

 

 

 

 

'프로젝트 > React' 카테고리의 다른 글

React 프로젝트 생성 방법  (1) 2025.04.09