React Hook useEffect has a missing dependency 완벽 해결법
도입: React Hook useEffect has a missing dependency 에러란?
🔗 관련 에러 해결 가이드
React 개발을 하다 보면 React Hook useEffect has a missing dependency 경고 메시지를 자주 마주치게 됩니다. 이 경고는 ESLint의 react-hooks/exhaustive-deps 규칙에 의해 발생하며, useEffect 훅 내부에서 사용하는 변수나 함수가 의존성 배열에 포함되지 않았을 때 나타납니다. 많은 개발자들이 이 경고를 무시하거나 임시방편으로 해결하려 하지만, 이는 예상치 못한 버그와 성능 문제를 야기할 수 있습니다. 이 글에서는 에러의 근본 원인부터 체계적인 해결 방법, 그리고 예방법까지 완벽하게 알아보겠습니다.
🤖 AI 에러 분석 도우미
이 에러는 다음과 같은 상황에서 주로 발생합니다:
- 코드 문법 오류가 있을 때
- 라이브러리나 의존성 문제
- 환경 설정이 잘못된 경우
- 타입 불일치 문제
💡 위 해결법을 순서대로 시도해보세요. 90% 이상 해결됩니다!
에러 상세 분석
이 경고 메시지는 React의 Hooks 규칙을 준수하지 않았을 때 발생합니다. useEffect는 의존성 배열에 명시된 값이 변경될 때마다 실행되는데, 만약 useEffect 내부에서 사용하는 state, props, 함수 등이 의존성 배열에 포함되지 않으면 최신 값이 아닌 이전 값을 참조하는 클로저 문제가 발생합니다.
예를 들어, 다음과 같은 코드에서 경고가 발생합니다:
const [count, setCount] = useState(0);
useEffect(() => {
console.log(count);
}, []); // 경고: 'count'가 의존성 배열에 없음
이 경고를 무시하면 count가 업데이트되어도 useEffect는 처음 렌더링 시의 값(0)만 계속 참조하게 됩니다. 이는 데이터 불일치와 예상치 못한 동작을 초래할 수 있습니다.
발생 원인 5가지
1. State나 Props를 의존성 배열에 누락
가장 흔한 원인으로, useEffect 내부에서 사용하는 state나 props를 의존성 배열에 포함시키지 않은 경우입니다. React는 이러한 값들이 변경될 때 effect를 다시 실행해야 하는지 판단할 수 없습니다.
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
fetchUser(userId).then(setUser);
}, []); // userId가 누락됨
}
2. 컴포넌트 내부에서 정의된 함수 누락
컴포넌트 내부에서 정의한 함수를 useEffect에서 사용하면, 해당 함수도 의존성 배열에 포함되어야 합니다. 함수는 매 렌더링마다 새로 생성되기 때문입니다.
function Component() {
const handleClick = () => {
// 로직
};
useEffect(() => {
document.addEventListener('click', handleClick);
return () => document.removeEventListener('click', handleClick);
}, []); // handleClick이 누락됨
}
3. 객체나 배열을 의존성으로 사용
객체나 배열은 매 렌더링마다 새로운 참조를 생성하므로, 의존성 배열에 직접 넣으면 무한 루프가 발생할 수 있습니다.
4. useCallback이나 useMemo로 감싸지 않은 함수
최적화를 위해 함수를 메모이제이션하지 않으면, 불필요한 effect 재실행이 발생할 수 있습니다.
5. Context 값 사용 시 누락
useContext로 가져온 값을 useEffect에서 사용할 때도 의존성 배열에 포함시켜야 합니다.
const theme = useContext(ThemeContext);
useEffect(() => {
applyTheme(theme);
}, []); // theme이 누락됨
해결방법 7가지 (코드 포함)
방법 1: 의존성 배열에 모든 변수 추가
가장 기본적이고 권장되는 방법입니다. React Hook useEffect has a missing dependency 경고가 제안하는 대로 모든 의존성을 추가하세요.
const [count, setCount] = useState(0);
const [name, setName] = useState('');
useEffect(() => {
console.log(`${name}의 카운트: ${count}`);
}, [count, name]); // 모든 의존성 추가
방법 2: useCallback으로 함수 메모이제이션
함수를 useCallback으로 감싸서 불필요한 재생성을 방지합니다.
function Component({ userId }) {
const [data, setData] = useState(null);
const fetchData = useCallback(async () => {
const result = await api.fetch(userId);
setData(result);
}, [userId]);
useEffect(() => {
fetchData();
}, [fetchData]);
}
방법 3: 함수를 useEffect 내부로 이동
함수가 useEffect 내부에서만 사용된다면, 내부로 이동시켜 의존성 문제를 해결할 수 있습니다.
useEffect(() => {
const fetchData = async () => {
const result = await api.fetch(userId);
setData(result);
};
fetchData();
}, [userId]); // 함수가 내부에 있으므로 의존성에 포함 불필요
방법 4: 함수형 업데이트 사용
setState에서 이전 값을 참조할 때는 함수형 업데이트를 사용하면 의존성을 줄일 수 있습니다.
useEffect(() => {
const timer = setInterval(() => {
setCount(prevCount => prevCount + 1); // 함수형 업데이트
}, 1000);
return () => clearInterval(timer);
}, []); // count를 의존성에 포함하지 않아도 됨
방법 5: useRef로 최신 값 참조
effect를 재실행하지 않고 최신 값을 참조하고 싶을 때 useRef를 사용합니다.
const countRef = useRef(count);
useEffect(() => {
countRef.current = count;
}, [count]);
useEffect(() => {
const timer = setInterval(() => {
console.log(countRef.current); // 항상 최신 값
}, 1000);
return () => clearInterval(timer);
}, []);
방법 6: 객체/배열은 useMemo로 메모이제이션
객체나 배열을 의존성으로 사용할 때는 useMemo로 감싸서 불필요한 재생성을 방지합니다.
const options = useMemo(() => ({
method: 'POST',
headers: { 'Content-Type': 'application/json' }
}), []);
useEffect(() => {
fetch(url, options);
}, [url, options]);
방법 7: ESLint 규칙을 특정 라인에서만 비활성화 (최후의 수단)
정말 필요한 경우에만 사용하세요. 의도적으로 의존성을 제외해야 하는 명확한 이유가 있을 때만 사용합니다.
useEffect(() => {
// 마운트 시에만 실행되어야 하는 로직
initializeApp();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
예방법과 베스트 프랙티스
1. ESLint 설정 활성화: react-hooks/exhaustive-deps 규칙을 ‘error’ 레벨로 설정하여 경고를 강제하세요.
2. 함수는 가능한 useEffect 내부에 정의: 외부에 정의해야 할 이유가 명확하지 않다면 내부에 작성하세요.
3. 필요한 경우에만 메모이제이션: useCallback과 useMemo를 남용하지 말고, 실제로 성능 이슈가 있을 때만 사용하세요.
4. 의존성 배열을 비우지 마세요: 빈 배열([])은 마운트 시에만 실행된다는 의미이므로, 정말 그것이 의도인지 확인하세요.
5. 커스텀 훅으로 로직 분리: 복잡한 useEffect 로직은 커스텀 훅으로 추출하여 관리하기 쉽게 만드세요.
마무리
React Hook useEffect has a missing dependency 에러는 단순한 경고가 아닌, 코드 품질과 안정성을 위한 중요한 신호입니다. 이 글에서 소개한 7가지 해결 방법을 적절히 활용하면 대부분의 상황을 해결할 수 있습니다. 가장 중요한 것은 경고를 무시하거나 임시방편으로 해결하지 않고, 근본 원인을 이해하고 올바른 방법으로 접근하는 것입니다. 의존성 배열을 정확히 관리하면 예측 가능하고 버그 없는 React 애플리케이션을 만들 수 있습니다. 지금 바로 프로젝트의 useEffect 코드를 점검하고 개선해보세요!
📚 함께 읽으면 좋은 글
Error: Element type is invalid 완벽 해결법 – 원인부터 예방까지
📅 2025. 10. 24.
🎯 Error: Element type is invalid
React Hook useEffect has a missing dependency 완벽 해결법 – 원인부터 예방까지
📅 2025. 10. 24.
🎯 React Hook useEffect has a missing dependency
Cannot update a component while rendering 완벽 해결법 – 원인부터 예방까지
📅 2025. 10. 23.
🎯 Cannot update a component while rendering
Cannot update a component while rendering 완벽 해결법 – 원인부터 예방까지
📅 2025. 10. 23.
🎯 Cannot update a component while rendering
Error: Element type is invalid 완벽 해결법 – 원인부터 예방까지
📅 2025. 10. 23.
🎯 Error: Element type is invalid
💡 위 글들을 통해 더 깊이 있는 정보를 얻어보세요!
📢 이 글이 도움되셨나요? 공유해주세요!
여러분의 공유 한 번이 더 많은 사람들에게 도움이 됩니다 ✨
🔥 공유할 때마다 블로그 성장에 큰 힘이 됩니다! 감사합니다 🙏
💬 여러분의 소중한 의견을 들려주세요!
이 글에서 가장 도움이 된 부분은 어떤 것인가요?
⭐ 모든 댓글은 24시간 내에 답변드리며, 여러분의 의견이 다른 독자들에게 큰 도움이 됩니다!
🎯 건설적인 의견과 경험 공유를 환영합니다 ✨
🔔 블로그 구독하고 최신 글을 받아보세요!
🌟 React 에러부터 다양한 실생활 정보까지!
매일 새로운 유용한 콘텐츠를 만나보세요 ✨
📧 RSS 구독 | 🔖 북마크 추가 | 📱 모바일 앱 알림 설정
지금 구독하고 놓치는 정보 없이 업데이트 받아보세요!