React를 직접 만들어보자 - (4)

이동창·2022년 5월 14일
0

React-From-Scratch

목록 보기
4/6

Fiber

이 때 생각해봐야 하는 것이, 과연 어떻게 unit을 나눌 것인가 이다.
이 때 등장하는 개념이 바로 fiber tree이다.

다음은 Fiber 트리의 예제이다.

여기서 우리는 root fibernextUnitOfWork로 설정하고 performUnitOfWork를 실행한다.
performUnitOfWork 함수는 다음과 같은 세가지 작업을 하는데

  1. element를 Dom에 추가하고
  2. 그 element의 자식들의 fiber를 생성한다.
  3. 마지막으로 다음 unit of work를 선택한다.

이 때 3번에서, 다음 unit of work를 선택하는 방법을 설정해야 하는데,
통상적으로 children으로 설정하게 된다.
다만, children이 없다면 sibling element를,
만약 sibling도 없다면 uncle element를 fiber로 만들고 다음 unit of work로 설정한다.
마지막으로 uncle도 없다면, sibling 이나 unlce을 찾을 때까지 부모 element로 올라가고
그렇게 root에 도달하면 render를 종료한다.

예를 들어서, 위의 그림에서 <p>에 대해 performUnitOfWork 를 실행하면
형제 element인 <a>를 다음 unit of work로 설정하고,
<a>에 대해 performUnitOfWork를 실행하면,
삼촌 element인 <h2>를 다음 unit of work로 설정한다.

마지막으로 <h2>는 형제나 삼촌 element가 없으므로 부모인 div로 올라가고
div도 마찬가지인 상황이므로 결국 부모인 root에 도달하게 되므로 render가 완료된다.

function performUnitOfWork(fiber) {
  // fiber의 dom을 만든다
  if (!fiber.dom) fiber.dom = createDom(fiber);
  // fiber의 부모에 이를 붙인다
  if (fiber.parent) fiber.parent.dom.appendChild(fiber.dom);

  const elements = fiber.props.children;
  let index = 0;
  let prevSibling = null;

  // fiber의 자식을 하나씩 탐색한다
  while (index < elements.length) {
    const element = elements[index];

    const newFiber = {
      type: element.type,
      props: element.props,
      parent: fiber,
      dom: null,
    };

    // 만약 index가 0이라면 자식, 아니라면 자식의 형제로 설정
    if (index === 0) fiber.child = newFiber;
    else prevSibling.sibling = newFiber;

    // 이전 sibling을 prevSibling에 저장하면서 사슬마냥 sibling끼리 이을 수 있게 됨
    prevSibling = newFiber;
    index++;
  }

  // 위에는 피버 트리를 세팅하는 작업이고
  // 여기서부터 unitOfWork가 할당된다고 보면 됨
  // 만약 fiber의 child가 있다면 그것을 리턴하고 nextUnitOfWork에 할당
  if (fiber.child) return fiber.child;

  let nextFiber = fiber;
  // children이 없다면 sibling을 return, 그것도 없다면 부모로 계속 올라가며 sibling 탐색하고 return
  while (nextFiber) {
    if (nextFiber.sibling) {
      return nextFiber.sibling;
    }
    nextFiber = nextFiber.parent;
  }
}

0개의 댓글