[번역] React 파이버 트리 순회는 어떻게 동작하나요?
React Internals Deep Dive - EP15
![[번역] React 파이버 트리 순회는 어떻게 동작하나요?](https://cdn.hashnode.com/res/hashnode/image/upload/v1714984766193/dd1d92a0-3e22-409d-a6b3-c1fe5847c036.jpeg)
영문 블로그 글을 번역했습니다. 허가를 받으면 시리즈를 이어갈 예정입니다.
원문링크:https://jser.dev/react/2022/01/16/fiber-traversal-in-react
ℹ️React Internals Deep Dive에피소드 15,유튜브에서 제가 설명하는 것을 시청해주세요.
⚠React@18.2.0기준, 최신 버전에서는 구현이 변경되었을 수 있습니다.
💬 역자 주석: JSer의 코멘트는 ❗❗로 표시 해뒀습니다.
그 외 주석은 리액트 소스 코드 자체의 주석입니다.
... 은 생략된 코드입니다.
Fiber Tree 구조
앞서 설명했듯이, React는 내부적으로 파이버 트리를 유지하며 계속 업데이트합니다. 각 파이버 노드에는 구조를 형성하는 3가지 프로퍼티가 있습니다.
child, 이름에 따라 그 자식 파이버.sibling, 이름에 따라 그 형제 파이버return, (일종의)부모 파이버라고 생각할 수 있습니다.
children이 없기 때문에, 제가 추측하기로 React 팀은 트리 탐색을 가능한 한 간단하게 처리하고 싶기에, 이 세 가지 프로퍼티는 충분히 잘 작동할 것입니다.
이런 일이 있을 수 있습니다.
Fiber Tree는 어떻게 순회하는가
파이버 트리를 순회해야 하는 많은 시나리오가 있습니다. 예를 들어, React가 파이버 트리를 순회하여 패시브 이펙트(예: useEffect())를 마운트하는 방법은 다음과 같습니다(소스).
export function commitPassiveMountEffects(
root: FiberRoot,
finishedWork: Fiber
): void {
nextEffect = finishedWork;
commitPassiveMountEffects_begin(finishedWork, root);
}
function commitPassiveMountEffects_begin(subtreeRoot: Fiber, root: FiberRoot) {
while (nextEffect !== null) {
const fiber = nextEffect;
const firstChild = fiber.child;
if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && firstChild !== null) {
ensureCorrectReturnPointer(firstChild, fiber);
nextEffect = firstChild;
} else {
commitPassiveMountEffects_complete(subtreeRoot, root);
}
}
}
function commitPassiveMountEffects_complete(
subtreeRoot: Fiber,
root: FiberRoot
) {
while (nextEffect !== null) {
const fiber = nextEffect;
if ((fiber.flags & Passive) !== NoFlags) {
setCurrentDebugFiberInDEV(fiber);
try {
commitPassiveMountOnFiber(root, fiber);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(fiber, fiber.return, error);
}
resetCurrentDebugFiberInDEV();
}
if (fiber === subtreeRoot) {
nextEffect = null;
return;
}
const sibling = fiber.sibling;
if (sibling !== null) {
ensureCorrectReturnPointer(sibling, fiber.return);
nextEffect = sibling;
return;
}
nextEffect = fiber.return;
}
}
React는 begin() 과 complete()로 각 노드를 두 번 밟기 때문에, 캡처와 버블 단계가 있는 DOM 이벤트라고 생각하면 되고, begin()은 capture 단계, complete()는 bubble 단계라고 생각하면 됩니다.
부모 파이버 노드가 먼저 begin() 되지만 자식보다 나중에 complete() 됩니다.
이 접근 방식은 begin과 complete의 포스트픽스(💬 _begin 이런 형식의 접미사 네이밍) 와 함께 React 소스 코드의 모든 곳에 있으므로, 깊이 빠지기 전에 이 접근 방식에 익숙해져야 합니다.
코딩 챌린지
알고리즘에 대한 이해를 높이기 위해 코딩 챌린지를 준비했습니다. 즐겨보세요!
(원본 게시일: 2022-01-16)
About the author
Software engineer for web tech. Interested in sustainable growth as software engineer.
Comments
Join the discussionNo comments yet. Be the first to comment.
React Internals Deep Dive 번역 시리즈
[번역] 리액트 내부 작동원리에 대한 JSer의 시리즈입니다. https://jser.dev/series/react-source-code-walkthrough


