useEffect의 dependency array

장동혁·2021년 2월 9일
3

react

목록 보기
2/2

개요

일반적으로 함수형 컴포넌트 내부에서 발생하는 side effect를 처리할 때 react 모듈에서 제공하는 useEffect함수를 사용한다. 이 때 두 번째 파라미터로 입력하는 dependency array에 의한 useEffect의 동작 원리를 이해하고 이를 기록하고자 한다.

useEffect의 동작 원리

여러가지 상황을 테스트 해보니 useEffect의 동작원리는 간단했다. 첫 번째 파라미터로 입력한 함수가 호출되는 시점은 컴포넌트가 첫 렌더링 되는 시점과 두 번째 파라미터로 입력된 dependency array의 각 element의 값이 변경되었을 때이다.

그렇다면 dependency array의 각 element의 값이 변경되는지 판단하는 시점은 언제일까?

답은 컴포넌트가 랜더링되는 시점이다. 컴포넌트가 랜더링 될 때마다 선언해 놓은 useEffect함수가 실행 되고 콜백 함수와 dependancy array가 파라미터로 전달된다. 그러면 useEffect함수의 내부 로직에 의해 dependancy array를 캐싱하고 있고 이전 각 element를 반복하면서 dependancy array의 element와 비교(===)한 뒤 다르면 첫 번째 파라미터인 콜백을 호출하는 구조이다. dependancy array를 캐싱할 수 있는 이유는 프로미스 일것이며 대략적은 코드는 다음과 같을 것으로 추측된다.

export const useEffect = (function () {
  let prevDependencyArray = [];
  return (callback, dependencyArray) => {
    for (const i in dependencyArray) {
      if (dependencyArray[i] !== prevDependencyArray[i]) {
        prevDepedencyArray = dependencyArray;
        callback();
        return;
      }
    }
  };
})();

dependency array

언뜻 보면 dependency array에 어떤 변수를 넣어도 해당 변수의 값이 변하면 콜백함수가 호출된다고 생각할 수 있다. 하지만 dependency array를 비교하려면 useEffect함수가 실행이 되어야 한다. useEffect함수가 실행이 된다는 것은 컴포넌트 함수가 호출된다는 것이고 이는 컴포넌트가 랜더링 된다는 것과 같은 뜻이다.

순차적으로 보면

  1. (재)랜더링
  2. useEffect함수 호출 (파라미터로 콜백함수, dependency array 전달)
  3. 이전 dependency array와 비교
    3-1. 3에서 다른점이 발견 될 시 콜백 호출

랜더링이 일어나지 않으면 콜백함수도 실행되지 않는다. 따라서 브라우저의 너비가 변화되면 특정 로직을 수행하기 위해 dependancy array로

useEffect(() => {
  console.debug('브라우저 너비 변경!')
},[document.body.clientWidth]}

와 같이 랜더링과 무관한 값을 넣었을 때 해당 값이 변경되더라도 콜백은 실행되지 않는다는 것을 주의해야한다. 하지만 랜더링이 랜더링이 잃어나기 전에 실제로 clientWidth이 변경되고 랜더링이 되면 이전 clientWidth와 새로운 clientWidth가 다르므로 콜백은 실행되므로 의도한 것이라면 사용 가능하다. 하지만 컴포넌트의 동작이 복잡해서 랜더링시점이 제대로 컨트롤 되지 않는다면 원하지 않는 동작이 발생할 수 있다는 것을 주의해야한다.

결론

도입부에서 말했던것 처럼 useEffect는 컴포넌트의 side effect를 처리하기 위한 함수다. 어디까지 컴포넌트의 side effect라고 정하는 것은 각자의 몫이지만 useEffect함수를 만든 의도는 컴포넌트의 상태 (props, state)의 변화에 따라 상태를 이용해 리액트와 관련 없는 부수 작업(side effect, dom 직접변경, api호출 등)를 처리하기 위한 것이기 때문이다.

profile
기록하는 습관

0개의 댓글