Maximum update depth, useEffect, 무한 루프 | 이펙트가 서로를 부르면?
Maximum update depth exceeded는 훅이 고장난 게 아니라 그린 뒤 이펙트가 상태를 바꾸고 그 상태가 다시 이펙트를 불러 한도를 넘긴 줄입니다. Too many re-renders와 구분하고, 객체 의존, 파생 값, 함수형 업데이트를 봅니다. React, Next.js, 한국 1인 개발자 기준. 2026년 9월 React useEffect·에러 185 문서.
Maximum update depth exceeded는 훅이 고장난 게 아니라, 그린 뒤 이펙트가 상태를 바꾸고 그 상태가 다시 이펙트를 불러 한도를 넘긴 줄입니다. 렌더 도중에 setState를 부르는 줄과 자리가 다릅니다.
화면이 멈추고 콘솔에 빨간 경고가 반복되는 일, 객체를 의존 배열에 넣거나 이펙트 안에서 같은 값을 새로 만들 때 한 번은 만납니다. 버튼을 고치기 전에 이펙트 의존부터 보세요.
컴포넌트를 통째로 갈아엎기 전에 의존 배열만 값으로 쪼개 보세요. 파생 값은 이펙트가 아니라 그리는 중에 계산합니다. 근거는 리액트 useEffect와 에러 185에 있습니다.
렌더 중 setState와 이펙트 루프는 다른 줄
리액트는 중첩 갱신이 한도를 넘으면 이 에러를 던집니다. 개발 빌드 메시지는 이펙트가 상태를 바꾸는데, 그 상태에 이펙트가 다시 기대면 루프가 된다고 안내합니다.
Too many re-renders는 그리는 도중에 setState를 호출한 줄입니다. onClick={fn()}처럼 렌더 몸통에서 바로 실행되면 그쪽입니다. 이 글은 그린 다음 이펙트가 서로를 부르는 칸입니다. 렌더 중 호출은 Too many re-renders 글을 보세요.
하이드레이션 미스매치는 서버 HTML과 첫 클라이언트 그림이 다른 줄이라 여기 루프와 무관합니다. 콘솔에 두 줄이 같이 있으면 원인을 나누세요. 미스매치는 하이드레이션 글입니다.
메시지
언제 도나
먼저 볼 코드
Maximum update depth exceeded
이펙트 또는 업데이트 훅이 루프
useEffect 의존 배열
Too many re-renders
렌더 함수 안에서 setState
onClick={fn()}, 렌더 몸통
Hydration failed
서버와 첫 그림이 다름
Date, window, 잘못된 태그
의존 배열에 객체가 있으면 의심하세요 | 렌더마다 새 객체, 새 배열, 새 함수가 만들어지면 이펙트는 매번 바뀌었다고 봅니다. 그 이펙트가 setState를 하면 루프입니다.
이펙트가 바꾼 상태가 다시 그 이펙트의 의존이면 한도를 넘긴다
의존에 객체를 넣으면 매번 다른 값이다
리액트는 의존을 Object.is로 비교합니다. 내용이 같아도 렌더마다 새로 만든 객체는 다른 값입니다. useEffect(() => { setUser({ ...user, ok: true }) }, [user])처럼 새 객체를 넣으면 이펙트가 끝없이 돕니다.
공식 문서는 이펙트가 외부 시스템과 동기화할 때만 쓰라고 합니다. 화면용 값을 맞추려고 이펙트에서 setState를 반복하면 루프가 납니다. 부모에서 인라인 객체 props를 넘긴 뒤 자식이 그걸 의존에 넣어도 같습니다.
함수도 렌더마다 새로 생깁니다. 의존에 넣은 핸들러가 이펙트에서 상태를 바꾸면 같은 줄입니다. 그 함수를 이펙트 안으로 옮기거나, 정말 필요할 때만 useCallback으로 고정하세요.
객체를 의존에 넣어 루프가 나는 코드
// 매 렌더 user가 새 객체가 되어 이펙트가 다시 돈다
function Panel({ id }) {
const [user, setUser] = useState({ id, flag: false })
useEffect(() => {
setUser({ ...user, flag: true })
}, [user])
return <div>{user.id}</div>
}
파생 값은 이펙트가 아니라 렌더에서 계산한다
리액트는 이펙트로 상태를 복제하지 말라고 합니다. 이미 있는 props나 state에서 만들 수 있는 값은 그리는 중에 계산합니다. 이펙트에서 setFiltered를 부르면 의존이 바뀔 때마다 한 바퀴 더 돕니다.
이전 값에 1을 더하는 이펙트도 그 숫자를 의존에 넣으면 루프입니다. 정말 마운트 한 번만 필요하면 배열을 비우고, 이전 값이 필요하면 함수형 업데이트 setN(n => n + 1)로 의존에서 빼세요.
서버 컴포넌트 파일에 훅을 넣은 줄은 여기 루프가 아닙니다. 지시자가 빠진 경우는 use client 글입니다. 이 글은 이미 클라이언트에서 이펙트가 돈 다음의 한도입니다.