React의 Cannot update a component while rendering 에러란?
🔗 관련 에러 해결 가이드
React 개발 중 Cannot update a component while rendering 에러를 마주친 적이 있나요? 이 에러는 React 16.13 버전 이후 도입된 경고 메시지로, 컴포넌트가 렌더링되는 동안 다른 컴포넌트의 상태를 업데이트하려고 할 때 발생합니다. 정확한 에러 메시지는 ‘Warning: Cannot update a component (`ComponentB`) while rendering a different component (`ComponentA`)’와 같은 형태로 나타나며, React의 단방향 데이터 흐름 원칙을 위반했음을 알려줍니다. 이 에러를 방치하면 무한 루프, 예측 불가능한 렌더링, 성능 저하 등의 심각한 문제로 이어질 수 있어 반드시 해결해야 합니다.
🤖 AI 에러 분석 도우미
이 에러는 다음과 같은 상황에서 주로 발생합니다:
- 코드 문법 오류가 있을 때
- 라이브러리나 의존성 문제
- 환경 설정이 잘못된 경우
- 타입 불일치 문제
💡 위 해결법을 순서대로 시도해보세요. 90% 이상 해결됩니다!
에러 상세 분석
이 에러는 React의 렌더링 사이클과 밀접한 관련이 있습니다. React는 컴포넌트를 렌더링할 때 순수 함수처럼 동작해야 한다고 가정합니다. 즉, 렌더링 과정에서는 외부 상태를 변경하지 않아야 합니다. Cannot update a component while rendering 에러는 이 원칙이 깨졌을 때 발생합니다.
구체적으로는 컴포넌트 A가 렌더링되는 중에 컴포넌트 B의 setState나 상태 업데이트 함수를 호출하면 React는 이를 감지하고 경고를 발생시킵니다. 이는 렌더링 순서가 예측 불가능해지고, 동일한 props와 state에 대해 항상 같은 결과를 반환해야 한다는 React의 핵심 원칙을 위반하기 때문입니다. 특히 이런 패턴은 컴포넌트 간 순환 의존성을 만들어 무한 렌더링 루프를 초래할 수 있습니다.
발생 원인 5가지
1. 렌더링 중 직접 상태 업데이트
가장 흔한 원인은 컴포넌트의 return 문이나 렌더링 로직 내에서 직접 setState를 호출하는 것입니다. 예를 들어 조건부 렌더링 과정에서 상태를 변경하려는 시도가 여기에 해당합니다.
2. 부모 컴포넌트 상태를 변경하는 자식 컴포넌트
자식 컴포넌트가 렌더링되면서 props로 받은 setState 함수를 즉시 호출하는 경우입니다. 이는 부모가 렌더링 중일 때 부모의 상태를 변경하려는 시도로 이어집니다.
3. useEffect 의존성 배열 누락
useEffect 없이 렌더링 본문에서 상태 업데이트를 수행하거나, useEffect의 의존성 배열을 잘못 설정하여 매 렌더링마다 상태가 업데이트되는 경우입니다.
4. Ref 콜백에서의 상태 업데이트
ref 콜백 함수 내에서 상태를 업데이트하면 렌더링 중에 상태 변경이 발생할 수 있습니다. ref는 렌더링 과정에서 할당되기 때문입니다.
5. Context Provider에서의 즉시 업데이트
Context Provider를 렌더링하면서 동시에 Context 값을 업데이트하려는 시도도 이 에러를 유발합니다. 특히 Provider 내부에서 useState를 초기화하면서 즉시 업데이트하는 패턴에서 자주 발생합니다.
해결방법 7가지 (코드 포함)
해결법 1: useEffect 사용하기
가장 기본적이고 권장되는 방법은 상태 업데이트를 useEffect로 감싸는 것입니다.
// 잘못된 예
function Component({ data }) {
const [state, setState] = useState();
if (data) {
setState(data); // 에러 발생!
}
return {state};
}
// 올바른 예
function Component({ data }) {
const [state, setState] = useState();
useEffect(() => {
if (data) {
setState(data);
}
}, [data]);
return {state};
}
해결법 2: 이벤트 핸들러로 이동
상태 업데이트를 사용자 이벤트에 반응하도록 변경합니다.
// 잘못된 예
function Parent() {
const [count, setCount] = useState(0);
return ;
}
function Child({ setCount }) {
setCount(prev => prev + 1); // 에러!
return Child;
}
// 올바른 예
function Child({ setCount }) {
return (
);
}
해결법 3: 파생 상태 제거
상태를 따로 저장하지 않고 props나 기존 상태로부터 직접 계산합니다.
// 잘못된 예
function Component({ items }) {
const [filteredItems, setFilteredItems] = useState([]);
if (items.length > 0) {
setFilteredItems(items.filter(item => item.active)); // 에러!
}
return
;
}
// 올바른 예
function Component({ items }) {
const filteredItems = items.filter(item => item.active);
return
;
}
해결법 4: useMemo로 메모이제이션
계산 비용이 큰 파생 값은 useMemo를 사용합니다.
function Component({ items }) {
const filteredItems = useMemo(() => {
return items.filter(item => item.active);
}, [items]);
return
;
}
해결법 5: useLayoutEffect 활용
DOM 측정 후 상태를 업데이트해야 할 때 사용합니다.
function Component() {
const [height, setHeight] = useState(0);
const ref = useRef();
useLayoutEffect(() => {
if (ref.current) {
setHeight(ref.current.offsetHeight);
}
}, []);
return Height: {height};
}
해결법 6: Ref 콜백 수정
ref 콜백에서는 상태 업데이트를 피하거나 useEffect로 이동합니다.
// 잘못된 예
function Component() {
const [width, setWidth] = useState(0);
return (
{
if (node) setWidth(node.offsetWidth); // 에러 가능!
}}>
Width: {width}
);
}
// 올바른 예
function Component() {
const [width, setWidth] = useState(0);
const ref = useRef();
useEffect(() => {
if (ref.current) {
setWidth(ref.current.offsetWidth);
}
}, []);
return Width: {width};
}
해결법 7: Key를 사용한 컴포넌트 리셋
props 변경 시 컴포넌트를 완전히 리셋해야 한다면 key를 사용합니다.
function Parent() {
const [userId, setUserId] = useState(1);
return ;
}
function UserProfile({ userId }) {
const [data, setData] = useState(null);
useEffect(() => {
fetchUser(userId).then(setData);
}, [userId]);
return {data?.name};
}
예방법과 베스트 프랙티스
이 에러를 예방하려면 몇 가지 원칙을 따라야 합니다. 첫째, 렌더링 로직을 순수하게 유지하세요. 컴포넌트 함수 본문에서는 계산만 수행하고 부수 효과는 피합니다. 둘째, 모든 부수 효과는 useEffect, useLayoutEffect, 또는 이벤트 핸들러 안에 배치합니다. 셋째, 가능하면 상태를 최소화하고 파생 값은 렌더링 중 직접 계산합니다.
또한 ESLint의 react-hooks 플러그인을 활성화하여 잠재적 문제를 사전에 감지하고, React DevTools를 사용해 불필요한 렌더링을 모니터링하세요. 컴포넌트 설계 시 단방향 데이터 흐름을 항상 염두에 두고, 자식이 부모의 상태를 직접 변경하는 패턴은 피해야 합니다.
마무리
Cannot update a component while rendering 에러는 React의 렌더링 원칙을 이해하면 충분히 예방하고 해결할 수 있습니다. 핵심은 렌더링 중에는 상태를 변경하지 않고, 모든 부수 효과를 적절한 생명주기나 이벤트 핸들러로 이동시키는 것입니다. 이 가이드에서 제시한 해결법들을 프로젝트에 적용하면 더 안정적이고 예측 가능한 React 애플리케이션을 만들 수 있을 것입니다. 에러가 발생했을 때는 에러 메시지를 주의 깊게 읽고 어떤 컴포넌트가 어떤 컴포넌트를 업데이트하려 했는지 파악하는 것이 첫 번째 단계입니다.
📚 함께 읽으면 좋은 글
Cannot update a component while rendering 완벽 해결법 – 원인부터 예방까지
📅 2025. 9. 29.
🎯 Cannot update a component while rendering
Cannot update a component while rendering 에러 해결법 – 원인 분석부터 완벽 해결까지
📅 2025. 8. 30.
🎯 Cannot update a component while rendering
Warning: Each child in a list should have a unique “key” prop 에러 해결법 – 원인 분석부터 완벽 해결까지
📅 2025. 9. 11.
🎯 Warning: Each child in a list should have a unique “key” prop
Hook “useState” is called conditionally 에러 해결법 – 원인 분석부터 완벽 해결까지
📅 2025. 9. 11.
🎯 Hook “useState” is called conditionally
Cannot read property ‘length’ of undefined 에러 해결법 – 원인 분석부터 완벽 해결까지
📅 2025. 9. 10.
🎯 Cannot read property ‘length’ of undefined
💡 위 글들을 통해 더 깊이 있는 정보를 얻어보세요!
📢 이 글이 도움되셨나요? 공유해주세요!
여러분의 공유 한 번이 더 많은 사람들에게 도움이 됩니다 ✨
🔥 공유할 때마다 블로그 성장에 큰 힘이 됩니다! 감사합니다 🙏
💬 여러분의 소중한 의견을 들려주세요!
이 글을 읽고 새롭게 알게 된 정보가 있다면 공유해주세요!
⭐ 모든 댓글은 24시간 내에 답변드리며, 여러분의 의견이 다른 독자들에게 큰 도움이 됩니다!
🎯 건설적인 의견과 경험 공유를 환영합니다 ✨
🔔 블로그 구독하고 최신 글을 받아보세요!
🌟 React 에러부터 다양한 실생활 정보까지!
매일 새로운 유용한 콘텐츠를 만나보세요 ✨
📧 RSS 구독 | 🔖 북마크 추가 | 📱 모바일 앱 알림 설정
지금 구독하고 놓치는 정보 없이 업데이트 받아보세요!