[TIL] useEffect... 당신은 도대체

이진호·2023년 11월 9일
13

TIL

목록 보기
25/66
post-thumbnail
post-custom-banner

챌린지 수업을 들으면서 라이프 사이클에 대해서 배우면서 나왔던 질문에 대해서 정리를 하려고 한다.

useEffect... 당신은 도대체

질문에 대한 내용은 아래와 같다.

const [state, setState] = useState(0);
  console.log(state); // (1)

  useEffect(() => {
    setState(1);
    return () => {
      console.log(state); // (2)
    };
  }, [state]);

위 코드를 실행하면 0 1 0 1이 나오는데 그 원리에 대해서 이해가 안가서 동작 원리에 대한 질문이었다.

음? 이거 완전 무한 재귀 같은데?

처음 코드를 얼추 보자마자 무한 재귀로 진행될 것 같았다. useEffect의 dependency는 state의 값의 변화에 따라서 업데이트 될 때 마다 실행을 하는데 안에서는 setState로 state 변경을 시도하기 때문이다.

하지만 얼마안가 다행히 재귀가 아니라는 것은 금방 판단할 수 있었다.

setState를 당연하게도 안에 함수를 넣어서 이전 값을 넣어서 갱신하는 것이라고 생각했는데 그게 아니라 특정 값 1을 넣고 있으니 어느 순간 더 이상 useEffect가 실행되지 않기 때문이다.

그게 아니라면 어떻게 동작할까?

일단 처음에 생각했던 무한 재귀 호출로 프로그램이 종료되지 않을 것 같다라는 것이 판단을 했으니 0 1 0 1으로 출력되는 원인에 대해서 고민을 했다.

  1. 컴포넌트가 생겨나면서 1번 로그가 실행될 것이다. 이때의 state값은 0이다. 그렇기에 처음에 0이 출력이 된다.
  2. 랜더링을 마치고 난 뒤에 useEffect가 실행이 될 것이다.
  3. setState를 실행하면서 state가 변경이 되면서 현재 컴포넌트가 업데이트를 한다.

오케이! 여기까지는 이해를 했다. 이어서 보자면

  1. 다시 한번 현재 컴포넌트가 실행이 되면서 1번 로그가 출력이 된다. 이때는 setState로 인해서 state의 값이 변했으므로 1이 출력된다.
  2. 그리고 useEffect의 dependency 중 state의 값이 변경이 됐으므로 다시 useEffect를 실행한다.
  3. 이때, useEffect 내에서 clean up 함수가 있으므로 이를 먼저 실행한다. 그렇기에 2번 로그가 출력이 된다. 이때 state의 값은 클로저로 인한 prevState의 값으로 0이 출력이 된다.
  4. 그 이후에 다시 useEffect 내부를 실행하게 된다.

이 부분이 최대 난관이다. 이때 실행하는 setState가 애매했다. setState에는 현재 이전 값과 동일한 1의 값이 들어간다. 여기서 변경을 일으킬까?

확실한 구분을 위해서 코드를 아래처럼 변경을 했다. 그리고 브라우저 상에서 어떻게 동작하는지 확인한 결과 다시 한번 1번 로그가 실행이 됐다.

이것만 보면 마치 setState를 실행 시킨다면 컴포넌트를 무조건 다시 한번 호출되는 것 처럼 보인다.
setState를 할 당시에 state는 이미 값이 1이고 이는 원시값이기 때문에 둘의 값은 같고 랜더링이 일어나면 안된다. 그런데 만약 setState에 같은 값이 들어가도 변경이 발생한다면 불변성을 유지하면서 값을 넣을 필요가 없는 것이 아닌가?

역시 정답은 공식 문서!

리액트 공식문서를 확인하였다. 공식문서 상에서 호출되기는 하지만 코드에 영향을 미치지 않는다고 한다. 심도있게 배운 것 같아 정말 기분이 좋았다. 오늘 잠 못잘 뻔 했는데 정말 다행이다.

Object.is 비교에 의해 결정된 대로 사용자가 제공한 새 값이 현재 상태와 동일하다면, React는 컴포넌트와 그 자식들을 다시 렌더링하지 않습니다. 이것은 최적화입니다. 경우에 따라 React가 자식을 건너뛰기 전에 컴포넌트를 호출해야 할 수도 있지만, 코드에 영향을 미치지는 않습니다.

참고 문서

profile
dygmm4288
post-custom-banner

3개의 댓글

comment-user-thumbnail
2023년 11월 9일

이걸 다 정리하는 빛진호... 갓진호..

1개의 답글
comment-user-thumbnail
2023년 11월 14일

기본을 단단히 할 수 있는 좋은 글 이었습니다.
감사합니다.

답글 달기