우당탕탕

React useEffect 의존성 배열 때문에 삽질한 경험과 해결 방법 본문

언어/JavaScript

React useEffect 의존성 배열 때문에 삽질한 경험과 해결 방법

모찌모찝 2026. 5. 27. 09:49

React 개발하면서 useEffect 훅의 의존성 배열 때문에 생각보다 고생을 많이 했어요. 저도 처음엔 왜 이걸 써야 하는지, 어떤 값들을 넣어야 하는지 감이 안 와서 값이 안 바뀌거나 무한루프에 빠지곤 했거든요.

이 글에선 제가 겪었던 삽질들, 그 원인 그리고 의존성 배열을 제대로 사용하는 방법을 차근차근 정리해봤습니다. 저처럼 헷갈리는 분들께 큰 도움이 될 거예요.

React useEffect 의존성 배열 왜 중요한지 삽질 후기 관련 이미지

React useEffect 의존성 배열 왜 중요한지 삽질 후기 관련 정보

useEffect 의존성 배열, 사실 뭐길래?

사실 useEffect 안에 넣은 코드는 컴포넌트가 렌더링될 때마다 실행돼요. 그런데 의존성 배열에 넣은 값들이 변할 때만 실행하도록 제어할 수 있거든요. 의존성 배열을 비워 두면 마운트 시에만 실행되고, 배열에 상태나 props 변수를 넣으면 그 값이 변할 때마다 실행됩니다.

이게 참 좋은 기능인데 여기서 많이 삽질하는 이유는, 어떤 값을 넣어야 하는지 헷갈리고, 누락하면 의도하지 않은 동작이 생기기 때문이에요.

의존성 배열을 잘못 써서 막혔던 경험

처음에 저는 이렇게 썼는데, 무한루프가 났어요.

const [count, setCount] = React.useState(0);

React.useEffect(() => {
  // count가 변할 때마다 상태를 바꾸는 함수 호출
  setCount(prev => prev + 1);
}, [count]);

처음에는 count가 바뀔 때만 실행돼서 괜찮다고 생각했는데, setCount 때문에 count가 계속 바뀌면서 useEffect도 계속 실행돼서 무한루프가 됐죠. 이걸 몰라서 한참 헤맸어요.

또, 의존성 배열을 아예 빈 배열로 두면 원하는 값이 바뀌어도 effect가 재실행 안돼서 데이터가 업데이트 안되는 문제도 발생했습니다.

제가 쓴 의존성 배열 관리법, 이렇게 하면 됩니다

제가 찾아낸 가장 중요한 팁은 “effect 안에서 사용하는 모든 상태와 props는 의존성 배열에 꼭 넣어야 한다”는 거였어요. 그래야 React가 언제 effect를 다시 실행할지 정확히 알거든요.

근데 함수나 객체 같은 참조형 데이터는 매번 새로 생성되니까, 무한루프의 원인이 되기 쉬워요. 그래서 useCallback이나 useMemo를 써서 의존성을 안정화하는 게 중요하다는 것도 알게 됐죠.

다음은 제가 쓴 예시 코드입니다.

const MyComponent = ({ userId }) => {
  const [userData, setUserData] = React.useState(null);

  // 데이터를 불러오는 함수, useCallback으로 감싸서 참조 안정화
  const fetchUserData = React.useCallback(() => {
    fetch(`https://api.example.com/users/${userId}`)
      .then(res => res.json())
      .then(data => setUserData(data));
  }, [userId]);

  // userId나 fetchUserData가 바뀌면 effect 재실행
  React.useEffect(() => {
    fetchUserData();
  }, [fetchUserData]);

  return (
    <div>
      {userData ? <pre>{JSON.stringify(userData, null, 2)}</pre> : '로딩 중...'}
    </div>
  );
};

이렇게 하면 userId가 바뀔 때마다 fetchUserData가 새로 만들어지고, 그 덕분에 useEffect가 정확하게 실행됩니다.

React useEffect 의존성 배열 왜 중요한지 삽질 후기 관련 이미지

React useEffect 의존성 배열 왜 중요한지 삽질 후기 관련 정보

여기서 삽질했던 부분들, 왜 그랬는지

한번은 useEffect 의존성 배열에 함수(fetchUserData)를 직접 넣지 않고 빈 배열로 두고, 함수 안에서 userId를 참조해서 데이터를 가져오게 했어요. 그랬더니 userId가 바뀌어도 effect가 다시 안 실행되더라고요.

React.useEffect(() => {
  fetch(`https://api.example.com/users/${userId}`)
    .then(res => res.json())
    .then(data => setUserData(data));
}, []); // userId 빠짐

이 문제는 userId를 의존성 배열에 넣어야 하는데, 안 넣어서 생긴 거였어요. 훅이 마운트 때만 실행되니, userId가 업데이트돼도 재호출을 안 했던 거죠.

그리고 또, 함수 내부에서 상태를 업데이트 하는 경우, 그 상태도 의존성 배열에 넣거나, 함수 자체를 useCallback으로 감싸서 안정화해야 무한루프 없이 잘 돌아갑니다.

조금 더 알면 유용한 트릭들

의존성 배열에 대해 ESLint가 알려주는 게 있으니 꼭 ESLint 플러그인을 활성화해보세요. 자칫 빠뜨린 의존성을 찾아서 알려줘서 도움이 많이 됩니다.

그리고 참조형 데이터(객체, 배열, 함수)를 의존성 배열에 넣으면 매번 새로운 참조라서 effect가 예상보다 많이 실행될 수 있어요. 그래서 이렇게 참조를 안정화 하는 게 관건입니다.

자주 물어보시는 것들

Q. 의존성 배열에 모든 상태를 넣으면 성능에 문제 없나요?

A. 상태가 많아질수록 effect가 자주 실행될 수 있어서, 필요하지 않은 값은 빼야 합니다. 하지만 대부분 상태는 넣는 게 맞고, 불필요한 실행은 useMemo, useCallback으로 최적화하세요.

Q. 의존성 배열에 함수를 직접 넣지 말라는 얘기도 있는데 왜인가요?

A. 함수는 매 렌더링마다 새로 생성되기 때문에, 그냥 넣으면 effect가 너무 자주 실행될 수 있어요. 그래서 useCallback으로 감싸서 함수 참조를 유지하는 걸 권장해요.

React useEffect 의존성 배열 왜 중요한지 삽질 후기 관련 이미지

React useEffect 의존성 배열 왜 중요한지 삽질 후기 관련 정보

마무리하자면, useEffect 의존성 배열은 리액트 컴포넌트의 업데이트 주기를 세밀하게 제어하는 중요한 도구예요. 저도 삽질하면서 배운 만큼 제대로 활용하면 데이터 일관성과 성능 향상에 큰 도움이 됩니다. 다음에는 useMemo, useCallback과 함께 더 나은 최적화 팁도 공유할게요.

Comments