
useEffect 의존성 배열에 lint 경고가 뜨는 경우
페이지 랜더링 시 최초에 한번 실행할 함수로 useEffect에 함수를 넣어서 이를 보통 해결해왔다.
const handleIU = () => {
console.log('IU');
}
useEffect( () => {
handleIU();
}, [])
위 같이 useEffect에 실행할 함수(?)를 추가하면 최초 렌더링 시에 실행된다. 한번만 실행할 예정이기에 의존성 배열에 특별한 값을 추가하지는 않는다. 하지만 가끔 이렇게 함수를 넣다보면 의존성배열에서 아래처럼 lint 오류를 표기해줄때가 있다.
React Hook useEffect has a missing dependency: 'fountInit'. Either include it or remove the dependency array.
잉 왜 갑자기 함수를.. 넣으라는 lint 경고가 생긴거지? 평소에는 문제 없었는데 말이다. 역시 이럴땐 비기 "disable .. this line"을 딱 해버린다면 단숨에 미션을 클리어 해버릴수 있다. 하지만 이렇게 커밋을 올린다면 누군가가 그럼 ESlint 왜씀! 라고 한마디 달아줄 가능성이 높다. (본인은 없어서 쥬륵ㅠ) 그리고 분명 이슈가 있으니 알려주는 것일 테고 말이다.
해당 이슈가 생긴건 사용하고자하는 함수에 (위 코드 같은 경우에는 handleIU) 다른 곳에서 불러와서 사용하는 파라미터가 존재하기 때문이다.
let IU = 'IU';
// const IU = 'IU' -> 이 친구는 ???
const handleIU = () => {
console.log(IU);
}
useEffect( () => {
handleIU();
}, [])
위 코드와 같이 외부에서 사용하는 변수를 가지고 와서 콘솔을 찍게 해보면 어떻게 될까? 바로 위 표시해둔 "React Hook useEffect has a missing dependency: 'handleIU'. Either include it or remove the dependency array" 에러가 발생한다.
그런데 let으로 선언하는게 아닌 const로 선언하면 혹시 어떻게 될까?
신기하게도(?) const로 선언한 변수를 사용하면 해당 경고가 나타나지 않는다. 둘의 차이점은 "변경 가능성" 이다. let으로 선언된 경우 해당 변수가 변경될 가능성이 있기 때문에 의존성 관련 경고가 나타난다. 하지만 const 로 선언된 변수의 경우 변경 가능성이 없기 때문에 handleIU가 변경될 가능성이 없다. 때문에 경고가 생기지 않는 것이다. 함수나 컴포넌트에서 넘어온 props를 사용할때에도 변경가능성이 존재하기 때문에 해당 lint 경고가 발생한다. 아마 이 경우가 더 일반적이지 않을까 한다.
함수 무한반복 이슈
이렇게 lint 오류 해결을 했는데, 이슈가 생겼다. 페이지 진입시에 해당 함수가 계속해서 실행되는 것이다.
아니 lint만 수정했는데 대체 왜.... ^^;; 다시 의존성 배열에서 제거하면 해당 현상은 나타나지 않아서 백만번 고민 후 이슈를 찾아보기로 했다. 사실 원인은 간단하다. 함수가 실행되면서 변경되는 경우가 있으면 함수가 다시 선언되고, 의존성 배열에 넣어두었으니 useEffect가 다시 실행되는 것이다. (코드는 조금 변경했다.)
const [IU, setIU] = useState(1);
const handleIU = () => {
setIU((prev) => prev + 1);
};
useEffect(() => {
handleIU();
}, [handleIU]);
원인은 이와 같다.
handleIU 를 실행하면 IU 값에 변경이 일어나게 되고 이는 리렌더링을 발생시킨다.
이렇게 변경이 일어나면 handleIU 가 다시 재선언된다. 의존성 배열에 있는 handleIU 가 재선언됨으로 인해 useEffect 는 다시 실행되게 되고, 이렇게 handleIU 함수가 또 실행된 것이다...(그렇게 무한 반복..)
그러면 lint 오류를 포기해야만 하는걸까...? Nope. handleIU 함수를 수정하면 가능한다.
const [IU, setIU] = useState(1);
const handleIU = useCallback(() => {
setIU((prev) => prev + 1);
}, []);
useEffect(() => {
handleIU();
}, [handleIU]);
위 처럼 handleIU 함수를 useCallback 으로 묶는다면 리렌더링시에 캐시된 함수를 그대로 가지고 오기 때문에 변화가 없고,
이에 useEffect는 다시 동작하지 않는다! 따라서 무한실행도 막을수있다.
생각보다 쉽고
생각보다 섬세한 친구다..
'Front-end' 카테고리의 다른 글
| [FE] dynamic import와 LCP (1) | 2025.08.22 |
|---|---|
| [FE] Nextjs Image에서 priority가 미치는 영향 (1) | 2025.08.21 |
| [Firebase] Page Not fount, This file does not exist and there was no index.html 해결하기 (feat. Next.js 빌드 방식) (3) | 2025.08.09 |
| [Firebase] Firebase Hosting Setup Complete 해결하기!(feat. Nextjs) (1) | 2025.08.08 |
| [FE] Figma와 cursor MCP 연결하기! (0) | 2025.08.01 |