훅(Hook)의 규칙 — 왜 조건문 안에서 쓰면 안 될까?
Article
이전 글에서 useState와 useEffect를 배웠습니다. 이런 use로 시작하는 함수들을 **훅(Hook)**이라고 부릅니다.
훅은 정말 편리하지만, 반드시 지켜야 하는 규칙이 있습니다. 이 규칙을 모르면 에러가 나거나, 더 무서운 건 에러 없이 이상하게 동작하는 버그가 생깁니다.
훅이란
훅은 React가 제공하는 특별한 함수입니다. use로 시작하는 게 특징입니다.
useState— 상태를 관리합니다.useEffect— 부수 효과를 처리합니다.useRef,useMemo,useCallback— 이것들도 전부 훅입니다.
공통점은 하나입니다. 전부 컴포넌트에 특별한 기능을 연결(hook into)해주는 함수입니다.
규칙 1: 최상위에서만 호출하세요
훅은 컴포넌트 함수의 맨 위에서 호출해야 합니다. 조건문, 반복문, 중첩 함수 안에서 호출하면 안 됩니다.
// 잘못된 예시
function MyComponent() {
const [name, setName] = useState("민초리");
if (name === "민초리") {
const [age, setAge] = useState(20); // 조건문 안에서 호출 — 안 됩니다!
}
return <p>{name}</p>;
}
// 올바른 예시
function MyComponent() {
const [name, setName] = useState("민초리");
const [age, setAge] = useState(20); // 항상 최상위에서 호출
return <p>{name}</p>;
}
왜 이런 규칙이 있을까요
React는 훅을 호출 순서로 관리합니다.
컴포넌트가 렌더링될 때마다 React는 내부적으로 이렇게 기억합니다.
1번째 훅 → useState("민초리") → name
2번째 훅 → useState(20) → age
3번째 훅 → useEffect(...)
매번 렌더링할 때 같은 순서로 훅이 호출된다는 것을 전제로 동작합니다.
그런데 조건문 안에 훅을 넣으면 어떻게 될까요? 조건이 false가 되는 순간 그 훅이 호출되지 않습니다. 그러면 순서가 뒤틀립니다.
첫 번째 렌더링: 1번 → 2번 → 3번 (정상)
두 번째 렌더링: 1번 → 3번 (2번이 사라짐!)
React는 "2번째 훅은 age다"라고 기억하고 있는데, 갑자기 2번 자리에 다른 훅이 오면 데이터가 뒤섞입니다. 비유하자면, 출석부에서 2번 학생이 빠졌는데 3번 학생을 2번으로 부르는 것과 같습니다.
규칙 2: React 함수 컴포넌트 안에서만 호출하세요
훅은 React 함수 컴포넌트 또는 커스텀 훅 안에서만 사용할 수 있습니다.
일반 JavaScript 함수에서 호출하면 동작하지 않습니다.
// 잘못된 예시 — 일반 함수에서 호출
function calculateTotal() {
const [total, setTotal] = useState(0); // 에러!
return total;
}
// 올바른 예시 — React 컴포넌트 안에서 호출
function PriceDisplay() {
const [total, setTotal] = useState(0); // 정상
return <p>합계: {total}</p>;
}
React가 컴포넌트를 렌더링하는 과정에서 훅을 추적하기 때문에, 그 과정 바깥에서 호출하면 React가 훅을 관리할 수 없습니다.
규칙을 어기면 어떤 에러가 나나요
다행히 React는 이 규칙을 어기면 명확한 에러 메시지를 보여줍니다.
React Hook "useState" is called conditionally.
React Hooks must be called in the exact same order in every component render.
"훅이 조건부로 호출되었다", "매번 같은 순서로 호출되어야 한다"는 내용입니다. 이 에러가 보이면 훅이 조건문이나 반복문 안에 들어가 있는지 확인하면 됩니다.
정리
- 훅은
use로 시작하는 React의 특별한 함수입니다. - 규칙 1: 컴포넌트의 최상위에서만 호출합니다. 조건문, 반복문 안에서 호출하면 안 됩니다.
- 규칙 2: React 함수 컴포넌트 또는 커스텀 훅 안에서만 호출합니다.
- React가 호출 순서로 훅을 관리하기 때문에 이 규칙이 존재합니다.
- 규칙을 어기면 에러가 나거나 데이터가 꼬일 수 있습니다.
다음 글에서는 React가 화면을 효율적으로 업데이트하는 핵심 전략, 가상DOM에 대해 알아보겠습니다.