Skip to content

useEffect 의존성 배열

dannysir edited this page Nov 22, 2024 · 1 revision

useEffect와 useCallback의 의존성 배열 다루기

개발을 하다보니 아래와 같은 문제를 마주치게 되었다. 아래 문제는 useEffect 내부에서 사용하는 요소가 의존성 배열에 없기 때문에 발생하는 문구인데 단순하게 의존성 배열에 해당 함수나 값을 넣게 되면 무한 렌더링이 발생할 수 있다.

스크린샷 2024-11-20 오후 7 28 26

useEffect의 의존성 배열 이해하기

의존성 배열이란?

useEffect의 두 번째 인자로 전달되는 배열을 의존성 배열(dependencies array)이라고 한다. 이 배열 내부의 값들이 변경될 때마다 useEffect가 재실행된다.

useEffect(() => {
  // 수행할 작업
}, [dependency1, dependency2]);

나의 실수 1.

내가 가장 먼저 했던 실수는 아래처럼 useEffect 내부에서 사용하는 함수를 의존성 배열에 넣지 않아서 발생했다.

javascript
Copy
const MyComponent = () => {
  const [data, setData] = useState([]);

  const fetchData = () => {
// API 호출 등의 로직
  };

  useEffect(() => {
    fetchData();
  }, []);// 빈 의존성 배열
};

문제점

  1. ESLint 규칙 위반
    • "React Hook useEffect has a missing dependency: 'fetchData'"
  2. 클로저 문제: fetchData 함수가 컴포넌트 내부의 상태나 props를 사용한다면, 항상 첫 렌더링 시점의 값을 참조하게 된다.
  3. 잠재적 버그: 의존성 배열이 비어있어서 fetchData 함수가 업데이트되더라도 effect가 재실행되지 않는다.

나의 실수 2.

이후 해당 문제를 해결하기 위해 아래처럼 함수를 그대로 의존성 배열에 넣었다.

그런데 이렇게 할 경우 리렌더링이 일어날 때마다 fetchData 함수가 새로 생성되고 useEffect가 매번 실행되는 문제가 발생한다.

const MyComponent = () => {
  const [data, setData] = useState([]);

  // 🔴 잘못된 예시: 매 렌더링마다 새로운 함수가 생성됨
  const fetchData = () => {
    // API 호출 로직
  };

  useEffect(() => {
    fetchData();
  }, [fetchData]); // fetchData가 매번 새로 생성되어 무한 루프 발생
};

useCallback으로 문제 해결하기

useCallback 소개

useCallback은 함수를 메모이제이션하여 불필요한 재생성을 방지할 수 있다.

const MyComponent = () => {
  const [data, setData] = useState([]);

  // ✅ 올바른 예시: 의존성이 변경될 때만 함수가 새로 생성됨
  const fetchData = useCallback(() => {
    // API 호출 로직
  }, []); // 빈 의존성 배열: 컴포넌트가 마운트될 때만 함수 생성

  useEffect(() => {
    fetchData();
  }, [fetchData]); // 이제 안전하게 의존성으로 사용 가능
};

useCallback 사용 시 주의사항

1. 의존성 배열 관리

useCallback의 의존성 배열도 useEffect와 마찬가지로 잘 확인해야 한다.

// 🔴 잘못된 예시: 필요한 의존성 누락
const handleUpdate = useCallback(() => {
  console.log(data); // data는 의존성 배열에 포함되어야 함
}, []);

// ✅ 올바른 예시
const handleUpdate = useCallback(() => {
  console.log(data);
}, [data]);

2. 과도한 사용 피하기

모든 함수에 useCallback을 적용하는 것은 오히려 성능을 저하시킬 수 있다.

const SimpleComponent = () => {
  // 🔴 불필요한 사용: 단순한 함수의 경우 useCallback이 필요하지 않음
  const handleClick = useCallback(() => {
    console.log('clicked');
  }, []);

  // ✅ 이렇게 작성하는 것이 더 명확하고 효율적
  const handleClick = () => {
    console.log('clicked');
  };
};

언제 useCallback을 사용해야 할까?

  1. useEffect의 의존성으로 함수를 사용할 때
  2. 자식 컴포넌트의 props로 함수를 전달할 때
  3. 복잡한 로직이 포함된 함수가 불필요하게 재생성되는 것을 방지하고 싶을 때

📜 개발 일지

⚠️ 트러블 슈팅

❗ 규칙

🗒️ 기록

기획
회의록
데일리스크럼
그룹 멘토링
그룹 회고

😲 개별 멘토링

고동우
김진
서산
이시은
박진명
Clone this wiki locally