# TIL: React의 의존성 관리



재밌는 질문을 받았다.
그리고 답변을 고민하다가 React가 의존성을 관리하는 방식에 대해 알게 되어서 글로 남긴다.

# 질문

질문은 아래 컴포넌트를 렌더링하고 버튼을 2번째 눌렀을 때 왜 저 함수가 다시 호출되면서 `console.log`가 실행되는지 모르겠다는 내용이었다.

```js
import { useEffect, useState } from "react";

function UseEffectTest() {
  // state only for rerender
  const [foo, setFoo] = useState(true);

  console.log("outside of useEffect, but inside of component", "foo: ", foo);

  useEffect(() => {
    console.log("RE-RENDERED", "foo: ", foo);
  });

  return (
    <div>
      {console.log("---inside JSX---", "foo: ", foo)}
      <button
        onClick={() => {
          setFoo(false);
        }}
      >
        rerender me!
      </button>
    </div>
  );
}

export default UseEffectTest;
```

나도 모르던 내용이라 처음엔

> 스트릭트 모드 때문 아닌가?

했다. 그런데 프로덕션 빌드에서도, `next@12`와 `react@17`로 테스트해봐도 똑같더라.
그리고 버튼을 더 눌러도 다시 렌더링이 되지 않았다.

고민하다가 깨달았다.
이건 React API의 한계다.

# 답변

React 함수 컴포넌트는 의존성 배열이라는 걸 사용한다.
그리고 `foo`는 `boolean` 타입을 가진 변수인데, 의존성 배열에 들어갈 수 있다.
변화 내용을 추적하거나 의존성 그래프를 그리기 위한 정보가 아예 없는, `boolean` 같은 값들이 의존성 배열에 직접 들어간다는 것이다.
`use*`는 의존성 그래프 없이 다시 실행할지 여부를 결정해야한다.
이럴 때 쓸 수 있는 방법이 `foo`를 `false`로 놓고 컴포넌트를 다시 실행해보는 것이다.
실행하면서 의존성 배열에 다른 값이 들어오는지 확인하면, `foo`가 `false`로 바뀌었을 때 다시 실행돼야하는 코드가 있는지 알 수 있다.
이후에 버튼을 다시 클릭해도 로그가 찍히지 않는 건 이전 실행의 결과로 `foo`가 `false`로 바뀌어도 다시 실행될 필요가 없다는 걸 알았기 때문일 것이다.

---

오랜만에 답변하면서도 배울 게 있는 질문이었다.

