노트

React의 규칙과 렌더 순수성

Rules of React

프런트엔드#react · 연결된 개념 10개

쉽게 말하면

React의 규칙은 계산기처럼 같은 입력이면 늘 같은 답을 내라는 약속이에요. React는 같은 컴포넌트를 여러 번 부르거나 렌더를 중간에 버리기도 해서, 렌더가 순수해야 몇 번을 실행해도 화면이 같아요.

비유가 깨지는 곳 훅에는 규칙이 하나 더 있어요. React는 이름이 아니라 호출 순서로 각 훅의 state를 찾아서, 조건문 안에서 하나를 건너뛰면 뒤의 훅이 한 칸씩 밀려요. 그래서 훅은 최상위에서만 불러요.

Rules of React는 React가 올바르게 동작하고 최적화하기 위해 코드가 지켜야 하는 규칙으로, 공식 문서가 세 가지로 정리한다. 핵심은 렌더가 순수한 계산이어야 한다는 것이다.

  1. 컴포넌트와 훅은 순수해야 한다. 같은 입력(props·state·context)이면 같은 JSX(JavaScript XML)를 낸다. 부수 효과는 렌더 밖(이벤트 핸들러, Effect)에서 실행한다. props·state, 훅의 인자와 반환값, JSX에 넘긴 값은 불변 스냅샷으로 다루고 고치지 않는다
  2. 컴포넌트와 훅은 React가 호출한다. Profile()처럼 직접 부르지 말고 JSX로 쓴다. 훅을 값처럼 넘기지 않는다. React가 호출해야 트리 위치에 state를 묶고 재조정에 참여시킬 수 있다
  3. 훅은 최상위(Top Level)에서만 호출한다. 조건문·반복문·중첩 함수 안에서 부르지 않는다. React는 호출 순서로 각 훅의 state를 찾기 때문에, 하나를 건너뛰면 뒤의 훅이 한 칸씩 밀린다. 훅은 컴포넌트나 use로 시작하는 커스텀 훅 안에서만 부른다. use()만은 조건문·반복문 안에서도 부를 수 있다

왜 이렇게 엄격한가

React는 같은 컴포넌트를 여러 번 부를 수 있다(엄격 모드(Strict Mode)는 개발 중 일부러 두 번 렌더한다). 동시성 모드에서는 렌더를 멈췄다 다시 하거나 통째로 버리기도 하고(동시성 렌더링), 다 그린 트리를 커밋 때 바꿔 끼운다(Fiber 아키텍처). 렌더가 순수해야 몇 번을 실행하든 결과가 같다. 렌더 중 Math.random()·Date.now()는 하이드레이션 불일치(Hydration Mismatch)와 잘못된 메모이제이션을 만든다.

  • 같은 입력에 같은 결과라는 성질은 서버 쪽 멱등성(Idempotency)과 닮았다
  • React Compiler는 이 규칙을 전제로 최적화하고, 어기면 그 컴포넌트를 건너뛴다
  • eslint-plugin-react-hooks가 대부분을 자동으로 잡아 준다
  • 부수 효과의 정의는 부수 효과와 Effect

출처: React - Rules of React · Rules of Hooks

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • Effect가 필요 없는 경우

    Effect는 외부 시스템과 동기화할 때 쓰는 탈출구(Escape Hatch)다. 렌더 중에 계산할 수 있는 값이나 사용자 이벤트 처리에 Effect를 쓰면 렌더가 한 번 더 일어나고 흐름이 꼬인다. React 공식 문서가 이런 경우를 따로 정리해 두었다.

  • React로 보는 SOLID

    SOLID는 원래 객체 지향 설계 원칙이지만 React 컴포넌트·props·훅에도 그대로 옮겨 볼 수 있다. 원칙 자체보다 "어떤 코드 모양이 되는가"를 짧게 정리한다.

  • 재조정(Reconciliation)

    재조정(Reconciliation)은 React가 이전 렌더의 엘리먼트 트리와 새 트리를 비교(Diffing)해, 실제 DOM(Document Object Model)에 필요한 최소한의 변경만 반영하는 과정이다. 두 트리를 완벽하게 비교하면 O(n³)이라, React는 두 가지 가정을 두어 O(n)으로 줄인다.

  • React 서버 컴포넌트(RSC)

    React 서버 컴포넌트(React Server Components, RSC)는 서버에서만 실행되고, 컴포넌트 코드가 아니라 실행 결과(직렬화된 엘리먼트 트리)만 클라이언트로 보내는 컴포넌트다. Next.js App Router에서는 'use client'를 붙이지 않은 컴포넌트가 기본으로 서버 컴포넌트다.

  • useEffectEvent

    useEffectEvent는 Effect 안에서 부르되 의존성 배열(Dependency Array)에는 넣지 않는 이벤트 함수를 만드는 훅이다. 항상 최신 props·state를 읽지만, 그 값이 바뀐다고 Effect가 다시 실행되지는 않는다. React 19.2에서 정식이 됐다(2026 기준).

보기 옵션