TOC
- 들어가며
- Overview의 목적
- 1. React Internals 학습 팁
- 2. 중단점을 활용한 디버깅
- 3. React Internals 개요
- 4. 요약
- 학습을 진행하며
- References
들어가며
본문 링크: Overall of React Internals
React v18.2.0 기준입니다.
아래부터는 내용을 요약한 부분입니다!
반말은 내용의 요약, 존댓말은 제가 작성한 내용입니다.
Overview의 목적
- React 내부는 너무 어렵고, 어떻게 시작할 지 모른다. 나도 그랬다.
- React Internals에 대한 대략적인 개요 설명
- React Internals를 배우는 몇 가지 팁 제안
1. React Internals 학습 팁
- React 공식사이트 봐라.
- React API들 학습 가능
- React 코어 팀 생각도 학습 가능(제작자 의도)
- React Repo 팔로우해라.
- PR과 코드리뷰가 대부분 코드 주석보다 더 낫다.
- React 소스 코드를 믿고 살펴봐라, 블로그 게시글이 아니라.
- 대부분 코드 안 다루고 아이디어만 다룸
- 게시글 봐도 React 퀴즈 같은 거도 못 품
- React 베이스 엄청 크니까 핵심경로를 찾아라.
- 모든 걸 한 번에 이해할 필요는 없다.
- 어떻게 작동하는지 대략적으로 파악하고 하나씩 풀어라.
- 지식과 이해의 네트워크를 형성하라.
2. 중단점을 활용한 디버깅
2.1. 중단점 설정
이후 내용은 아래 코드처럼 컴포넌트가 실행될 때 중단되도록, 그리고 useEffect hook이 실행될 때 중단되도록 debugger breakpoint를 설정했다. 중단될 때의 상황과 콜스택을 살펴볼 것이니 이에 초점을 맞춰본다.
function App() {
const [count, setCount] = useState(1);
debugger; // This debugger tells me when the component is run
useEffect(() => {
debugger; // This debugger tells me when effect hooks are run
setCount((count) => count + 1);
}, []);
return <button>{count}</button>;
}
ReactDOM.createRoot(document.getElementById("container")).render(<App />);
2.2. 첫번째 일시정지 : 컴포넌트 렌더링

아래는 콜스택에서 중요한 함수들이다.
ReactDOMRoot.render()
- 우리가 작성한 user-side 코드
createRoot()
호출 후render()
호출
scheduleUpdateOnFiber()
- React에 렌더링할 위치를 알려줌
- 초기 마운트에는 이전 버전이 없으므로 루트에서 호출
ensureRootIsScheduled()
performConcurrentWorkOnRoot()
가 예약되어 있는지 확인
scheduleCallback()
- 실제 스케줄링은 React 스케줄러의 일부
- 스크린샷에서
postMessage()
에 의해 비동기화되는 것을 확인 가능
workLoop()
- React 스케줄러가 작업을 처리하는 방법
performConcurrentWorkOnRoot()
- 이제 예약된 작업이 실행되고 있음
- App 컴포넌트가 실제로 렌더링됨
2.3. 두 번째 일시정지: DOM 조작

- UI 라이브러리로서의 목표 : DOM 업데이트를 관리하는 것
- "렌더링" 단계 이후의 "커밋" 단계에 해당
commitRoot()
- 이전 렌더링 단계에서 파생
- 필요한 DOM 업데이트 커밋
- 이펙트 처리 등의 작업 수행
commitMutationEffects()
- 호스트 DOM의 실제 업데이트
2.4. 세 번째 일시정지: 이펙트 실행

flushPassiveEffects()
:useEffect()
에 의해 생성된 모든 패시브 이펙트 플러시postMessage()
에 의해 비동기화 → 즉시 실행되지 않고 예약됨(scheduled)flushPassiveEffects()
에 중단점 추가하면commitRoot()
내부에 있음을 쉽게 확인 가능
2.5. 컴포넌트 렌더링에서 재정지

- 위의
useEffect()
에서는 리렌더링을 트리거하기 위해setState()
호출 - 콜스택의 전체 리렌더링이 첫 번째 중단점 일시정지(컴포넌트 렌더링)와 매우 유사함을 확인 가능
- 단,
performConcurrentWorkOnRoot()
내부에서는mountIndeterminateComponent()
가 아닌updateFunctionComponent()
를 호출한다는 점이 다름
3. React Internals 개요

3.1. Trigger
- 모든 작업이 이 단계에서 시작되어 붙은 이름
- 초기 마운트이든, state hook에 따른 리렌더이든
- 앱의 어떤 부분을 렌더링(
scheduleUpdateOnFiber()
)해야 하는지, 어떻게 렌더링해야 하는지 React 런타임에 알려줌 create a task(작업 생성)
이라고 생각할 수 있음ensureRootIsScheduled()
는 작업 생성의 마지막 단계scheduleCallback()
에 의해 작업이 Scheduler에게 전달
3.2. Schedule
- React 스케줄러 - 우선순위에 따라 작업을 처리하는 우선순위 큐
- 런타임 코드에서
scheduleCallback()
을 호출하여 렌더링이나 이펙트 실행과 같은 작업을 예약(schedule) - Scheduler 내부의
workLoop()
는 작업이 실제로 실행되는 방식 - 더 자세한 내용은 How React Scheduler Works 참고
3.3. Render
- 예약된 작업(
performConcurrentWorkOnRoot()
) - 새로운 Fiber Tree 계산, 호스트 DOM에 적용할 때 필요한 업데이트 파악을 의미
- Fiber Tree : 앱의 현재 상태를 나타내는 내부 트리
- 이전에는 가상 DOM (Virtual DOM)이라고 부름
- 지금은 DOM에만 사용되는 것이 아니어서 용어 교체(React 팀에서!)
나의 의견
:Virtual DOM
이라는 용어가 너무 익숙한데 바뀌었었군요...😨
performConcurrentWorkOnRoot()
- Trigger 단계에서 생성
- Scheduler에서 우선순위 결정
- Render 단계에서 실행
- 마치 난쟁이가 Fiber Tree를 걸어다니며 리렌더링이 필요하거나 호스트 DOM에 필요한 업데이트를 알아내는 과정
- 동시 모드(concurrent mode)로 인해 "Render" 단계가 중단되었다가 다시 시작될 수 있어 꽤 복잡한 단계가 됨
- 더 자세한 내용은 아래 참고
3.4. Commit
- Fiber Tree가 구성되고, 최소 업데이트가 도출되면, 호스트 DOM을 업데이트하기 위한 단계
- 단지 DOM 조작(
commitMutationEffects()
)만은 아님- 예를 들면, 모든 종류의 이펙트는 여기서 처리(
flushPassiveEffects()
,commitLayoutEffects()
)
- 예를 들면, 모든 종류의 이펙트는 여기서 처리(
- 관련 에피소드
4. 요약
- 대충 debugger 몇 개 설정했는데, 얼마나 많은 정보를 얻을 수 있는지 봐라.
- 겁먹지 말고 한 번에 퍼즐 하나씩만 맞춰라.
학습을 진행하며
이후에 제대로 다뤄주겠지?
Overview이기 때문에 이후에 각 훅이나 동작들에 대해 코드 베이스 레벨로 깊게 다루게 될 거에요. 그래서 그런지, 이번 overview에서는 여러 지식들(특히 외계어 같은 함수명들)이 쏟아지는데 제대로 설명해주지 않고 넘어가요. 그래서 이후에 제대로 다루기 위한 Preview라고 생각하고 넘어가볼게요.
코드베이스 언젠가 까보자
위에서 React 베이스 엄청 크니까 핵심경로 찾으라는 구절이 나왔어요. 하지만 그렇다고 바로 코드 베이스를 뚫어보지 않고, 이 Internals Deep Dive를 다 진행한 뒤에 중간중간 지식의 거점들을 두고 파보면 훨씬 편하게 갈 수 있겠다는 생각을 했습니다.
번역본.. 있을 것 같은데
내용 원문은 영문이라, 한글 번역도 함께 할까 했어요. 그러다 그런 생각이 들었어요. "내가 하려 했다면, 누군가 이미 해놨다." 내가 겪은 오류는 누군가 먼저 겪었으니 찾아보라는 개발 격언이랑 일맥상통합니다. 아무튼 찾으니 바로 보기 좋게 번역된 번역 시리즈가 나오더라고요. 그래서 영어 원문과 함께 한글 번역본을 동시에 참고하며 정리하고 있습니다.
React 퀴즈 풀기
블로그 포스트 보지 말고 코드 보라는 내용에서 React 퀴즈가 언급되어 풀어보려 했어요. 총 31개의 문제인데... 풀다가 포기했습니다. 제가 이렇게 React 동작을 잘 모르는지 몰랐어요. 부끄럽습니다. 이번 기회에 공부 많이 해서 지식 잘 쌓고 제대로 풀어봐야겠어요.