개발

Reactjs - useEffect 와 의존성 배열 완벽 가이드

syaku 2024. 11. 6. 15:10
반응형

React의 useEffect와 의존성 배열 완벽 가이드

React의 useEffect는 컴포넌트의 생명주기와 관련된 부수 효과(side effects)를 처리하는 핵심 Hook입니다. 특히 의존성 배열(dependency array)의 올바른 사용은 애플리케이션의 성능과 안정성에 큰 영향을 미칩니다.

useEffect의 기본 구조

useEffect(() => {
  // 실행할 코드

  return () => {
    // 클린업 코드
  }
}, [의존성1, 의존성2, ...]);

의존성 배열의 세 가지 사용 패턴

1. 빈 배열 사용

useEffect(() => {
  console.log('컴포넌트 마운트 시에만 실행');
}, []);
  • 컴포넌트가 처음 마운트될 때만 실행
  • 주로 초기 데이터 fetch나 이벤트 리스너 등록에 사용

2. 의존성이 있는 배열

useEffect(() => {
  console.log(`count가 ${count}로 변경됨`);
}, [count]);
  • 지정된 의존성(count)이 변경될 때마다 실행
  • 특정 상태나 props의 변화에 반응해야 할 때 사용

3. 의존성 배열 생략

useEffect(() => {
  console.log('매 렌더링마다 실행');
});
  • 컴포넌트가 리렌더링될 때마다 실행
  • 성능 문제가 발생할 수 있어 주의 필요

클린업 함수의 역할

useEffect(() => {
  const subscription = api.subscribe();

  // 클린업 함수
  return () => {
    subscription.unsubscribe();
  };
}, [api]);
  • 메모리 누수 방지
  • 이벤트 리스너 제거
  • 이전 상태 정리
  • 다음 경우에 실행됨:
    1. 컴포넌트 언마운트 시
    2. 의존성이 변경되어 effect가 재실행되기 전

의존성 배열 사용 시 주의사항

1. 잘못된 의존성 설정

// 잘못된 예
useEffect(() => {
  setTotal(count * price);
}, []); // count와 price가 변경되어도 total이 업데이트되지 않음

// 올바른 예
useEffect(() => {
  setTotal(count * price);
}, [count, price]);

2. 객체와 배열 의존성

// 주의가 필요한 경우
useEffect(() => {
  doSomething(options);
}, [options]); // options가 객체라면 매 렌더링마다 새로 생성될 수 있음

// 해결 방법
useEffect(() => {
  doSomething(options.id, options.type);
}, [options.id, options.type]); // 필요한 프로퍼티만 의존성으로 지정

실제 사용 예시

1. API 호출

useEffect(() => {
  const fetchData = async () => {
    setLoading(true);
    try {
      const response = await api.getData(id);
      setData(response);
    } catch (error) {
      setError(error);
    } finally {
      setLoading(false);
    }
  };

  fetchData();
}, [id]); // id가 변경될 때만 API 재호출

2. 이벤트 리스너

useEffect(() => {
  const handleResize = () => {
    setWindowSize({
      width: window.innerWidth,
      height: window.innerHeight
    });
  };

  window.addEventListener('resize', handleResize);

  return () => {
    window.removeEventListener('resize', handleResize);
  };
}, []); // 마운트 시에만 리스너 등록

성능 최적화 팁

  1. 필요한 의존성만 포함하기
useEffect(() => {
  // user.name만 사용한다면
}, [user.name]); // user 객체 전체 대신 필요한 속성만 의존성으로 지정
  1. 함수 의존성 제거하기
useEffect(() => {
  // 함수를 effect 내부로 이동
  const handleData = () => {
    // ...
  };

  handleData();
}, [필요한_의존성만]);
  1. useCallback과 함께 사용
const memoizedCallback = useCallback(() => {
  doSomething(dependency);
}, [dependency]);

useEffect(() => {
  memoizedCallback();
}, [memoizedCallback]);

결론

useEffect와 의존성 배열의 올바른 사용은 React 애플리케이션의 성능과 안정성에 큰 영향을 미칩니다. 의존성 배열을 신중하게 설정하고, 클린업 함수를 적절히 활용하며, 성능 최적화를 고려하는 것이 중요합니다.

반응형