렌더링이 예상을 벗어나는 또 한가지 경우

정세연·2022년 5월 8일
4
post-thumbnail

오늘은 컴포넌트가 리렌더링 되는 경우 1가지를 얘기해 보려고 합니다.

언제 리렌더링이 일어날까?

내부적으로 더 자세하게 구분되어야 하겠지만 크게는

  • 부모 컴포넌트가 리렌더링 되었을 때
  • 상태가 변경되었을 때
  • props가 변경되었을 때

로 요약할 수 있을 것 같습니다. 이 부분에 대해서 많은 사람들이 이미 알고 있을 것이라고 생각합니다.

간단한 예시입니다.

function Parent() {

  return (
    <div>
      <ChildA />
    </div>
  );
}

function ChildA() {
  console.log("A is rendered!");
  return <div>ChildA</div>;
}

해당 구조에서 Parent가 리렌더링 된다면 자식 컴포넌트인 ChildA도 리렌더링이 일어날 것입니다.

삽질의 시작

여기서 구조를 조금만 바꿔보겠습니다.

function App({ children }) {

  return (
    <Parent>
      <ChildA />
    </Parent>
  );
}


function Parent({ children }) {

  return (
    <div>{children}</div>
  );
}

function ChildA() {
  console.log("A is rendered!");
  return <div>ChildA</div>;
}

크게 어색한 점은 없습니다. 많이 사용하듯 children props를 사용하여 자식 컴포넌트를 렌더링 한 모습입니다. 이제 Parent 컴포넌트에 리렌더링을 발생시켜 보겠습니다.

function Parent({ children }) {

  const [state, setState] = useState({});

  useEffect(() => {
    const id = setInterval(() => setState({}), 1000);
    return () => clearInterval(id);
  }, [state]);
  
  console.log("parent is rendered");
  
  return (
    <div>{children}</div>
  );
}

결과는 어떻게 될까요?

Parent 컴포넌트는 리렌더링이 발생하지만 자식 컴포는트는 최초 렌더링 이후 리렌더링이 발생하지 않는 모습을 확인할 수 있습니다. 이 부분이 바로 글을 작성하게 된 계기입니다. 이러한 현상의 원인을 이미 알고 있던 사람들도 많겠지만 저는 최근 개발 도중 꽤나 삽질을 하다가 그 원리를 알게 되었습니다.

원인

다시 앞으로 돌아가 보겠습니다. 언제 리렌더링이 발생할까요?

  • 부모 컴포넌트가 리렌더링 되었을 때
  • 상태가 변경되었을 때
  • props가 변경되었을 때

이것들은 독자적인 이유로 보이지만 사실 유기적인 모습을 띄고 있습니다.

리액트 공식 문서를 보신 분들이라면 아시겠지만 앞선 Parent 컴포넌트에서 리턴한 ChildA 컴포넌트는 React.createElement(ChildA, null)로 컴파일되고 이후 {type: ChildA, props: {}} 형태의 ReactElement가 생성됩니다.

여기서 주목할 점은 props입니다. 컴포넌트가 생성될 때마다 기본적으로 props는 새 객체 형태로 생성됩니다. 이로써 리액트는 불변성을 감지하고 리렌더링을 발생시킬 수 있습니다. 즉 props가 변경되었기 때문에 리렌더링이 발생하게 됩니다.

하지만 자식 컴포넌트를 children props로 전달하면 어떻게 될까요? ChildA에 대한 React.createElement(ChildA, null)가 호출 될 일이 없기 때문에 리렌더링이 발생하지 않았던 것입니다.

이 같은 원리를 깨닫기까지 많은 삽질과 서칭이 있었습니다.. 결국 공식 문서의 내용을 좀 더 잘 이해했다면.. 이라는 생각이 밀려오는 경험이었습니다.

참조

0개의 댓글