몸과 마음이 건전한 SW 개발자

[React] useEffect cleanup function (내가 한 실수 포함) 본문

프론트엔드

[React] useEffect cleanup function (내가 한 실수 포함)

스위태니 2025. 8. 22. 12:17
728x90

▶▷ 서론◁◀

  • dayjs를 수정하다가 현재 페이지(컴포넌트) 외에 전역으로 영향을 미친다는 사실을 알게 되었다. 그러다보니 weekStart를 메인 페이지에서 1로 설정했고 다른 페이지에서 2로 설정했다면 충돌이 날 수밖에 없게 된다. (에러가 나지는 않지만 둘 중 하나의 방식만 선택됨) 이런 경우에 useEffect를 써서 각 컴포넌트에서만 실행되게 하고 싶었고 그 방법을 cleanup function에서 찾았다.

▶▷ 목차 ◁◀

  1. 정의
  2. 언제 실행되는가
  3. 자 사용하는 패턴
  4. 내가 사용한 패턴
  5. 주의사항
  6. 정리하기

1. 정의 ◁◀

  • React의 useEffect에서 return하는 함수는 cleanup function(정리 함수)라고 부른다.
  • 이 함수는 컴포넌트가 언마운트되거나 의존성 배열이 변경되어 effect가 다시 실행되기 전에 호출된다.

 2. 언제 실행되는가 ◁◀

 

  1. 컴포넌트 언마운트 시: 컴포넌트가 DOM에서 제거될 때
  2. 의존성 배열 변경 시: 다음 effect 실행 전에 이전 effect를 정리
  3. 컴포넌트 리렌더링 시 (의존성이 변경된 경우)

 


 3. 자주 사용하는 패턴 ◁◀

1. 이벤트 리스너 제거

useEffect(() => {
  const handleResize = () => {
    setWindowWidth(window.innerWidth);
  };
  
  window.addEventListener('resize', handleResize);
  
  // cleanup: 이벤트 리스너 제거
  return () => {
    window.removeEventListener('resize', handleResize);
  };
}, []);

 

2. 타이머 정리

useEffect(() => {
  const timer = setInterval(() => {
    setCount(prev => prev + 1);
  }, 1000);
  
  // cleanup: 타이머 정리
  return () => {
    clearInterval(timer);
  };
}, []);

 

3. API 요청 취소

useEffect(() => {
  const controller = new AbortController();
  
  fetch('/api/data', { signal: controller.signal })
    .then(response => response.json())
    .then(data => setData(data))
    .catch(err => {
      if (err.name !== 'AbortError') {
        console.error(err);
      }
    });
  
  // cleanup: 진행 중인 요청 취소
  return () => {
    controller.abort();
  };
}, []);

 

4. 구독(subscription) 해제

useEffect(() => {
  const subscription = someObservable.subscribe(data => {
    setData(data);
  });
  
  // cleanup: 구독 해제
  return () => {
    subscription.unsubscribe();
  };
}, []);

4. 내가 사용한 패턴 ◁◀

useEffect(() => {
  // 현재 설정 백업
  const originalWeekStart = dayjs.Ls.ko?.weekStart || 1

  // 임시로 일요일 시작 설정
  dayjs.locale('ko')
  dayjs.updateLocale('ko', {
    weekStart: 0
  })

  // cleanup: 원래 설정으로 복원
  return () => {
    dayjs.updateLocale('ko', {
      weekStart: originalWeekStart
    })
  }
}, [])
  • 이 패턴은 전역 설정 임시 변경 패턴이다.
  • 컴포넌트가 마운트될 때 dayjs의 주간 시작일을 일요일로 변경하고, 언마운트될 때 원래 설정으로 되돌린다.
  • 이렇게 하면 해당 컴포넌트가 다른 컴포넌트나 전역 상태에 영향을 주지 않도록 할 수 있다.

5. 주의사항 ◁◀

 

  • cleanup function은 동기적으로 실행되어야 한다 (async 함수 사용 불가)
  • 의존성 배열이 있는 경우, 배열이 변경될 때마다 cleanup이 먼저 실행되고 새로운 effect가 실행된다
  • cleanup을 잊으면 메모리 누수나 예상치 못한 동작이 발생할 수 있다

 


 6. 정리하기 ◁◀

  • 전역으로 설정하는 경우 스크롤이 될 수도 있고, 내가 설정한 dayjs를 사용할 수도 있다.
  • 이런 경우에 useEffect의 cleanup 함수를 사용해보자.
  • 하지만 cleanup 함수를 사용하기 전에 내가 사용하는 라이브러리의 함수가 전역으로 관리되는지 생각하고 개발할 필요가 있다. 

728x90