카테고리 없음

React 'Rendered fewer hooks than expected' 에러 원인과 해결법

트티 2025. 4. 21. 08:00

React 'Rendered fewer hooks than expected' 에러 원인과 해결법

React로 프로젝트를 진행하다 보면 예상치 못한 에러 메시지에 멈춰 서게 되는 경우가 많죠. 그 중에서도 많은 개발자들을 당황하게 만드는 에러 중 하나가 바로 "Rendered fewer hooks than expected"입니다. 처음에는 무슨 말인지도 모르겠고, 어디서부터 봐야 할지 난감할 수 있어요.

이 에러는 주로 useState, useEffect 같은 Hook을 사용할 때 특정 조건에 따라 실행 흐름이 달라지며 발생하게 되는데요. 원리를 이해하지 못하면 작은 코드 수정 하나에도 반복적으로 같은 문제를 겪게 될 수 있어요.

이 글에서는 실제 사례를 바탕으로 왜 이 에러가 발생하는지, 그리고 어떻게 해결할 수 있는지에 대해 자세히 설명드릴게요. 글을 끝까지 읽으시면 Hook 사용에 대한 감을 잡고, 앞으로 더 자신 있게 코드를 작성하실 수 있을 거예요!

목차

📌 에러 발생 원인

"Rendered fewer hooks than expected" 에러는 React가 내부적으로 useState, useEffect 등의 Hook 호출 순서를 기준으로 컴포넌트의 상태를 추적하는데, 이 순서가 조건에 따라 달라지는 경우 발생합니다. React는 "컴포넌트가 매번 동일한 순서로 Hook을 호출해야 한다"는 규칙을 가지고 있어요.

예를 들어 다음과 같은 코드가 있다고 가정해 볼게요:

{`function MyComponent({ isAdmin }) {
  if (isAdmin) {
    const [adminData, setAdminData] = useState(null);
    // ...
  }
  const [userData, setUserData] = useState(null);
  // ...
}`}
    

위 코드에서는 isAdmin이 true일 때만 useState를 호출하게 되죠. 이 말은 어떤 렌더에서는 Hook이 2개 호출되고, 어떤 렌더에서는 1개만 호출된다는 뜻입니다. React 입장에서는 "아니, 이 컴포넌트 지난번에는 2개 Hook 썼잖아?" 하면서 에러를 뿜게 되는 거예요.

📌 실전 사례 분석

실제로 제가 경험했던 사례를 공유해볼게요. 어떤 관리자 페이지를 개발하던 중, 관리자만 볼 수 있는 섹션에서 데이터를 받아오기 위해 다음과 같은 코드를 작성했어요:

{`function Dashboard({ isAdmin }) {
  if (isAdmin) {
    const [adminStats, setAdminStats] = useState([]);
    useEffect(() => {
      fetch('/api/admin-stats')
        .then(res => res.json())
        .then(data => setAdminStats(data));
    }, []);
  }

  const [userInfo, setUserInfo] = useState(null);
  useEffect(() => {
    fetch('/api/user-info')
      .then(res => res.json())
      .then(data => setUserInfo(data));
  }, []);

  return (
{userInfo &&

환영합니다, {userInfo.name}님

} {isAdmin && adminStats && }
  );
}`}
    

이 코드를 실행하면 "Rendered fewer hooks than expected" 에러가 콘솔에 딱! 뜹니다. 문제는 useStateuseEffectif (isAdmin) 조건문 안에서 사용했다는 거예요.

이 코드를 해결하기 위해선 조건부 Hook 호출을 제거하고, 항상 동일한 순서로 Hook을 호출하도록 리팩터링해야 해요:

{`function Dashboard({ isAdmin }) {
  const [adminStats, setAdminStats] = useState([]);
  const [userInfo, setUserInfo] = useState(null);

  useEffect(() => {
    fetch('/api/user-info')
      .then(res => res.json())
      .then(data => setUserInfo(data));
  }, []);

  useEffect(() => {
    if (isAdmin) {
      fetch('/api/admin-stats')
        .then(res => res.json())
        .then(data => setAdminStats(data));
    }
  }, [isAdmin]);

  return (
{userInfo &&

환영합니다, {userInfo.name}님

} {isAdmin && adminStats && }
  );
}`}
    

이처럼 Hook은 항상 컴포넌트 최상단에서 호출되어야 하며, Hook 내부에서 조건 처리를 하는 방식으로 문제를 해결해야 해요. 조건부로 Hook 자체를 호출하면 절대 안 된다는 것, 꼭 기억하세요!

📌 실무에서 자주 겪는 실수와 팁

개발 현장에서 이 에러는 특히 리팩토링하거나 새로운 조건을 추가할 때 많이 발생합니다. 나도 모르게 조건문 안에 Hook을 넣는 순간, 다음 렌더링 때 순서가 꼬이면서 에러가 터지죠. 그래서 아래 몇 가지 체크리스트를 기억해두시면 실수를 줄일 수 있어요.

✔️ 조건문, 반복문 안에서 Hook 쓰지 않기

if, for, while 등 흐름 제어 문 안에서 useState, useEffect 등 Hook을 사용하면 절대 안 됩니다. 반복문에서 여러 개의 Hook을 생성하려는 유혹이 들더라도 참아야 해요! 필요하다면 map 안에서 컴포넌트로 분리해서 처리하세요.

✔️ Hook 호출 위치는 항상 컴포넌트 최상단

Hook은 컴포넌트 함수가 실행되자마자 바로 호출되어야 React가 상태를 예측할 수 있어요. 이를 지키지 않으면 렌더링 간에 Hook의 순서가 달라져서 React의 내부 메커니즘이 무너져버립니다.

✔️ 커스텀 Hook도 마찬가지

useMyCustomHook() 같은 커스텀 Hook도 마찬가지예요. 이 역시 내부에 useStateuseEffect를 포함하고 있기 때문에, 조건적으로 호출하면 안 됩니다. 항상 무조건 호출되게 하고, 그 안에서 로직 분기를 처리하세요.

✔️ ESLint로 예방하기

리액트 프로젝트에서는 eslint-plugin-react-hooks 플러그인을 꼭 설정해두는 걸 추천드려요. 이 플러그인은 Hook 사용 규칙을 위반할 경우 경고 또는 오류로 알려줍니다. 실수로 조건문 안에 Hook을 넣었을 때 즉시 감지할 수 있어서 큰 도움이 돼요.

개발자의 경험담: 저는 한 번은 복잡한 조건을 가지는 UI를 만들면서 Hook을 중첩 조건 안에 넣어버렸어요. 당연히 로컬에선 잘 되다가, 특정 조건에서만 에러가 발생했죠. 결국 2시간을 날린 후에야 "Hook 순서" 문제라는 걸 깨달았습니다. 그 이후부터는 Hook은 무조건 최상단, 조건은 내부에서 분기! 이 원칙을 철칙처럼 지키고 있어요.

✔️ 공통된 패턴은 커스텀 Hook으로 정리

비슷한 패턴이 반복된다면 커스텀 Hook으로 추출해보세요. 예를 들어, 로그인 유저 정보 불러오기, 로딩 상태 관리 등은 반복적으로 쓰이니까 useUserInfo() 같은 형태로 만들면 재사용성과 가독성이 높아집니다.

📌 결론

React에서 발생하는 "Rendered fewer hooks than expected" 에러는 초보자부터 숙련자까지 누구나 한 번쯤은 마주하는 흔한 문제입니다. 하지만 이 에러의 근본 원인은 단순합니다 — Hook의 호출 순서가 일관되지 않기 때문이죠.

우리는 Hook을 사용할 때 항상 컴포넌트 함수의 최상단에서, 조건문 없이 일관되게 호출해야 한다는 React의 규칙을 따라야 합니다. 그리고 조건에 따라 다른 동작을 하려면, Hook 내부에서 조건 분기를 처리하는 방식으로 코드를 구성해야 합니다.

실제 사례에서도 알 수 있듯이, 처음엔 실수로 조건문 안에 Hook을 넣어도 콘솔 경고 외에는 눈에 띄지 않다가, 특정 조건에서 에러가 발생하고 말죠. 이럴 때는 당황하지 말고 Hook 호출 위치부터 꼼꼼히 다시 확인해보세요.

React의 Hook 시스템은 매우 강력하지만, 그만큼 규칙도 명확합니다. 이 규칙을 잘 이해하고 습관처럼 지키는 것이, 앞으로 더 안정적이고 유지보수하기 쉬운 코드를 작성하는 첫걸음이 될 거예요.

기억하세요: "Hook은 항상 같은 순서로 호출되어야 한다"는 단 하나의 원칙만 지켜도, 이 에러는 사라집니다. 작은 규칙이 큰 품질을 만든다는 점, 잊지 마세요!