React Hooks와 Hooks 규칙 – 나에게 드디어 와닿은 이해

발행: (2026년 1월 4일 오전 03:37 GMT+9)
8 분 소요
원문: Dev.to

Source: Dev.to

Cover image for React Hooks and the Rules of Hooks – The Understanding That Finally Clicked for Me

오늘, 무언가가 깨달아졌습니다.

오랫동안 React Hooks를 사용해 왔지만, 솔직히 말하면 그것이 무엇인지, 왜 React가 그 규칙에 그렇게 엄격한지, 그리고 동작하는 것처럼 보이는 일부 패턴이 왜 여전히 나쁜 관행으로 간주되는지 진정으로 이해하지 못했습니다.

이 블로그는 제가 개인적으로 이해한 내용을 적어보려는 시도이며, 이를 통해:

  • 일주일이나 이주일 후에 다시 읽을 때
  • 혹은 앞으로 혼란스러워질 때

이 글이 저를 완전한 명확성으로 되돌아오게 해 주고, 단순히 겉핥기식 지식에 머무르지 않게 해 주길 바랍니다.

실제 React Hooks가 무엇인가

첫 번째 오해가 바로 이것이었습니다:

Hooks는 단순한 헬퍼 함수가 아니다.

Hooks는 React가 제공하는 특수한 빌딩 함수이며, React의 Fiber 아키텍처와 직접적으로 상호 작용합니다.

Hooks는 다음을 위해 사용됩니다:

  • React에 상태를 등록하기
  • 부수 효과(side effects)를 등록하기
  • 컴포넌트 로직을 React 내부 업데이트 시스템에 연결하기

그래서 다음과 같은 특징이 있습니다:

  • 모든 Hook은 use로 시작합니다 (useState, useEffect, useRef 등)
  • React는 Hook을 일반 JavaScript 함수처럼 취급하지 않습니다 – Hook은 React가 컴포넌트를 렌더링하고 업데이트하는 방식과 밀접하게 결합되어 있습니다.

Hooks와 React Fiber – 놓친 정신 모델

내부적으로 React는 Fiber Tree를 유지합니다. 각 컴포넌트 렌더링마다 React는 훅을 연결 리스트에 저장합니다:

  • 첫 번째 훅 호출은 첫 번째 노드가 됩니다
  • 두 번째 훅 호출은 두 번째 노드가 됩니다
  • …이와 같이 계속됩니다

React는 훅을 이름으로 식별하지 않고 순서로 식별합니다. 이 한 가지 사실이 모든 Hooks 규칙을 설명합니다.

React Hooks 개요

React는 많은 훅을 제공하지만, 실제로 가장 흔히 쓰이는 그룹은 다음과 같습니다:

가장 많이 사용되는 훅

  • useState
  • useEffect
  • useReducer
  • useContext

성능 / 최적화 훅

  • useRef
  • useCallback
  • useMemo
  • useTransition
  • useDeferredValue

저수준 또는 고급 훅

  • useSyncExternalStore
  • useInsertionEffect

각 훅은 목적이 다르지만 모든 훅에 동일한 규칙이 적용됩니다.

훅 규칙 (마침내 이해된 부분)

✅ 규칙 1: 훅은 최상위에서만 호출한다

  • if 문 안에 훅을 두지 않는다
  • 루프 안에 훅을 두지 않는다
  • return 뒤에 훅을 두지 않는다

훅은 절대 조건부로 실행되어서는 안 된다.

잘못된 패턴 예시

if (imdbRating > 8) {
  const [isTop, setIsTop] = useState(true);
}

왜 위험한가: 훅이 일부 렌더에서는 실행되고 다른 렌더에서는 실행되지 않을 수 있어, 훅 순서가 깨지고 React가 상태를 올바르게 매칭하지 못한다.

✅ 규칙 2: 훅은 React 함수에서만 호출한다

훅은 다음 내부에서만 허용된다:

  • 함수형 컴포넌트
  • 커스텀 훅

일반 JavaScript 함수에서는 호출해서는 안 된다. React는 렌더링 단계에서만 훅을 추적하기 때문이다.

“이 코드는 동작하지만… 왜 여전히 잘못된 걸까?”

파생 상태 함정

예전에는 이렇게 해도 괜찮다고 생각했습니다:

const [isTop, setIsTop] = useState(imdbRating > 8);
useEffect(() => {
  setIsTop(imdbRating > 8);
}, [imdbRating]);

코드는 오류 없이 실행되지만, 개념적으로 불필요한 상태를 만들고 설계가 나빠집니다.

올바른 사고 방식: 저장하지 말고 파생하라

값을 props나 다른 상태에서 완전히 파생할 수 있다면, 별도의 상태로 저장하지 말아야 합니다.

const isTop = imdbRating > 8;

추가 상태도, 효과도, 추가 렌더링도 없으므로 로직이 더 깔끔해지고 버그가 줄어듭니다.

평균 평점에 대한 상태 업데이트 이해

새로운 상태가 이전 상태에 의존할 때는 함수형 업데이트를 사용합니다:

// Direct update
setAvgRating(Number(imdbRating));

// Functional update (depends on previous value)
setAvgRating(prev => (prev + userRating) / 2);

React는 직접 업데이트와 함수형 업데이트를 모두 지원합니다. 함수형 업데이트를 사용하면 다음과 같은 문제를 피할 수 있습니다:

  • 오래된 값 사용
  • 배치 처리로 인한 예기치 않은 동작

이제 나는 훅을 이렇게 시각화한다

  • Hooks = 연결 리스트의 노드
  • React = 그 리스트를 관리하는 매니저
  • 순서를 바꾸면 = ❌ 시스템이 깨짐

따라서, 훅은 렌더링마다 같은 순서로 호출되어야 하며, 조건문 안에 넣어서는 안 된다.

최종 깨달음

The Rules of Hooks are:

  • 임의적이지 않음
  • “React가 이유 없이 엄격한 것”이 아님

They are a direct result of React’s internal design. Once I understood Fiber and hook ordering, I didn’t need to memorize the rules—they started making logical sense.

최종 생각

React Hooks에 어려움을 겪고 있다면:

  • 사용법만 배우지 말고 존재하는지 배우세요.

“왜”가 명확해지면:

  • 코드가 더 깔끔해집니다
  • 버그가 줄어듭니다
  • 자신감이 높아집니다

이 블로그는 미래의 나를 위해서도 씁니다 — 이 혼란이 다시는 돌아오지 않도록.

Back to Blog

관련 글

더 보기 »