[ Frontend > React ]
[리액트 19] 1편. 패키지 구조
React 패키지 구조 (웹 개발)
혼자서 리액트 코드도 뜯어보고, 잘 만들어진 중국어 리액트 설명도 많이 차용했습니다. 설명이 틀릴 수도 있지만, 최대한 맞는 설명이 되도록 많이 자료를 찾아보고 코드도 보면서 만들었으니 도움이 되시면 좋겠습니다. 현재 댓글 기능이 없어서 크로스 체크가 불가 합니다. 얼른 댓글 관리할 수 있는 백오피스를 만들어 함께 의견을 공유할 수 있도록 노력하겠습니다.
리액트 프로젝트는 packages 디렉토리에 총 37개(@19.1.0 기준)의 패키지가 있습니다.
이 중 웹 개발을 위해 사용자가 설치하는 기본 패키지는 2개이고 기본 패키지를 구현하는데 필요한 내부 구현 패키지가 4개가 있습니다.
1. 기본 패키지, 내부 구현 패키지
사용자가 설치하는 기본 패키지는 react, react-dom 패키지입니다. 내부 구현 패키지로 shard, react-dom-bindings, react-reconciler, scheduler 4개가 있습니다.
1.1 react 패키지
React의 기본 패키지로 React Component(React Element)를 정의하는 데 필요한 핵심 함수들만을 제공합니다.
단독으로는 사용되지 않고, 보통 Renderer(react-dom, react-native)과 함께 사용합니다.
React 애플리케이션 작성 시 대부분 이 패키지의 API를 사용합니다.
1.2 react-dom 패키지
Renderer 중 하나로, React와 플랫폼(브라우저) 간의 연결 다리 역할을 합니다.
Browser나 Node.js 환경에서 사용할 수 있습니다. 내부 구현 패키지로 react-dom-bindings를 사용합니다.
React-Reconciler에서 만들어낸 결과를 실제 웹 UI로 출력하는 기능을 담당합니다. 이 패키지는 다음 API 한줄로 설명할 수 있습니다.
//React 17 까지ReactDOM.render(<App />, document.getElementById('root'));// React 18 이후ReactDOM.createRoot(document.getElementById('root')).render(<App />);
1.3 react-reconciler 패키지
React가 작동할 수 있도록 하는 핵심 패키지입니다. react-dom, react, scheduler 간의 호출과 협업을 조율합니다.
React 애플리케이션의 상태 입력과 결과 출력을 관리하며, 입력된 데이터를 Renderer가 사용할 수 있는 형식으로 변환해 전달합니다.
역할
입력을 받아들인 후(scheduleUpdateOnFiber), Fiber 트리 생성 로직을 하나의 콜백 함수로 캡슐화합니다(여기에는 Fiber 트리 구조, fiber.updateQueue 큐, 조정 알고리즘 등이 포함됩니다).
콜백 함수(performSyncWorkOnRoot 또는 performConcurrentWorkOnRoot)를 scheduler에 전달하여 스케줄링하도록 합니다.
scheduler는 콜백 함수 실행 시점을 제어하며, 콜백 함수가 실행을 마치면 새로운 Fiber 트리를 얻게 됩니다.
그 다음 렌더러(예: react-dom, react-native 등)를 호출하여, Fiber 트리 구조를 실제 화면에 반영합니다.
1.4 scheduler
스케줄링 로직의 핵심 구현체로, react-reconciler가 넘긴 콜백 함수의 실행 시점을 조정합니다.
Concurrent 모드에서는 이 스케줄러 덕분에 작업 분할(타임 슬라이싱)을 통해 렌더링을 중단할 수 있습니다.
역할
react-reconciler가 전달한 콜백을 실행.
콜백의 실행 타이밍을 조절하여 작업을 분할할 수 있게 해줘서 중단 가능한 렌더링을 구현할 수 있게 해줍니다.(Concurrent 모드)
1.5 react-dom-bindings
react-dom의 내부 구현 패키지로 React에서 DOM환경(브라우저)와 연결해주는 다리 역할을 합니다. React18 버전부터 react-dom으로부터 분리되었습니다. 플랫폼에 따라 다른 renderer 구현이 필요한데, 모바일 환경인 react-native는 react-native-renderer를 사용하고, 브라우저는 readt-dom으로 react-dom-bindings를 내부 구현으로 사용합니다.
역할
react-dom에서 내부 구현체로 사용하여 DOM 노드 생성.
실제 DOM 설정 및 업데이트.
1.6 shared
React 여러 패키지에서 공통적으로 사용하는 유틸리티, 상수, 구조체 등을 모아놓은 패키지입니다. 또한 사용하는 객체들을 공유하는 패키지입니다. 만약 react 패키지가 useState훅을 사용한다면, react-reconciler 패키지에서 shared에 할당한 useState훅을 사용하는 것입니다. react에서 직접 react-reconciler 패키지를 참조하지 않고 shared 패키지를 거쳐서 가져오게 됩니다.
역할
런타임 중 React 패키지 간의 변수 공유.
Fiber 노드의 타입, 상태 관련 상수들 제공.
React 내부 전용 유틸리티 함수 제공.
2. 계층의 분리 (비공식적)
React 애플리케이션 전체 구조는 인터페이스 계층(api)와 코어 계층(core) 두 부분으로 나눌 수 있습니다. (비공식적입니다.)
2.1 인터페이스 계층(api)
react 패키지가 인터페이스 계층에 해당합니다. 우리가 개발 중에 사용하는 대부분의 API가 이 패키지에서 제공됩니다.(전부는 아닙니다 ex. useFormState는 react-dom 패키지)
React 실행 후 렌더링을 변경할 수 있는 기본 동작 3가지는 다음과 같습니다.
클래스 컴포넌트에서 setState() 사용.
함수형 컴포넌트에서 hook을 사용하고, dispatchAction을 통해 hook 객체를 변경.
context 변경 (이 또한 setState나 dispatchAction을 사용하긴 함)
위에서 언급한 setState와 dispatchAction 모두 react 패키지에서 제공됩니다. 그리고 우리는 React의 다른 패키지와 상호작용하고 동작시키기 위해서 react 패키지의 api를 사용합니다.
2.2 코어 계층(core)
React의 코어 계층은 크게 3부분(scheduler, reconciler, renderer)으로 구성됩니다.
scheduler (스케줄러) - scheduler 패키지
react-reconciler가 제공하는 콜백 함수를 작업(task) 객체로 포장합니다.
내부적으로 task queue(작업 큐)를 유지하며, 우선순위가 높은 작업이 앞에 위치합니다.
작업 큐를 순회하며 작업을 하나씩 처리하고, 큐가 빌 때까지 실행합니다.
reconciler (리컨실러) - react-reconciler 패키지
개발자가 선택한 renderer를 장착합니다. (HostConfig(렌더링 인터페이스)가 구현된 객체. ex. react-dom, react-native)
react와 react-dom에서 발생한 업데이트 요청 수신
Fiber 트리 구성 과정을 콜백 함수로 감싸 scheduler로 전달.
renderer (렌더러) - react-dom 패키지
React 앱 시작(createRoot, render)
HostConfig를 구현하여 fiber 트리를 실제 DOM 구조로 렌더링
브라우저 환경 : DOM 생성
SSR : 문자열 생성
HostConfig
HostConfig는 실제 렌더링을 하는 인터페이스라고 생각하면 됩니다. 예를 들면, rendering이라는 함수를 인터페이스로 구현을 하는데 react-dom은 DOM 객체를 추가하는 방식으로 구현하고, react-native는 모바일 확경에 맞는 객체를 추가하는 방식으로 구현될 것입니다.
3. 리액트 개요도
다음은 React의 핵심 세 가지 패키지의 주요 역할과 호출 관계를 하나의 개요도로 표현했습니다.

빨간색은 진입 함수, 초록색은 출구 함수 입니다. 거시적인 아키텍처 관점에서 패키지들 간의 의존성과 호출 관계를 설명하는 그림을통해 먼저 전체 구조를 파악하고 함께 각 모듈을 공략해 나갑시다!!