React를 좀 더 자세히 알아보고자한다.
앞선 포스팅에서 React의 기본에 대해서 꽤나 많이 다루었지만, 뭐랄까... 개발하면 할수록 뭔가 비어있다는 느낌이 강하게 든다.
프로젝트를하면서 알게 된것들, 배웠던것들 글로 남겨야지 하면서 바쁘다는 핑계로 간략하게 회사 회고록에 남기거나 나중에 자세하게 해야지 하면서 미뤄뒀었다. 그리고 최근 프로젝트중에 Next.js를 쓸 기회가 생겨서 더욱 React에서 뭔가가 비어있다가 느껴졌다.
DOM
React보다 더 이전의 Javascript의 개념부터 시작해야한다. 이 글에서는 자세히 다루지 않겠다.
DOM(Document Object Model)은 XML이나 HTML 문서에 접근하기 위한 일종의 인터페이스이다.
문서 내의 모든 요소를 정의하고, 각각의 요소에 접근하는 방법을 제공한다.
DOM은 W3C의 표준 객체 모델이며, 계층구조로 표현된다.
Virtuual DOM
React는 실제로 DOM을 제어하는 방식이 아니라 중간에 가상의 DOM인 Virtual DOM을 두어 개발의 편의성(DOM을 직접 제어하지 않음)과 성능(배치 처리로 DOM 변경)을 개선했다.
가상 DOM은 실제 DOM의 구조와 비슷한, React 객체의 트리다. 개발자는 DOM을 직접 제어하지 않고 Virtual DOM을 제어하고, React에서 적절하게 Virtual DOM을 DOM에 반영하는 작업을 한다.
ReactDOM.render(
<App/>,
document.getElementById('root')
)
// JSX 문법 변환
ReactDOM.render(
React.createElement(App)
, document.getElementById('root'));
위와 같이 ReactDOM.render() 함수를 호출하면 JSX문법을 변환한 Javascript 코드를 이용해서 Virtual DOM을 만들기 시작한다.
render() 함수를 호출할 때 React.createElemet(App) 객체를 파라미터로 전달하며, render() 함수는 React에서 사용하는 타입의 컴포넌트를 생성한다.
이때 생성하는 컴포넌트는 주로 ReactCompositeComponent 객체와 ReactDOMComponent 객체다.
ReactCompositeComponent 객체는 DOM이 아닌 컴포넌트를 생성할 때 사용된다. ReactDOMComponent 객체는 DOM을 만들 때 생성하는 컴포넌트다.
render() 함수가 생성한 컴포넌트를 React 컴포넌트에 마운트하기 위해 ReactReconciler.mountComponent() 메서드를 호출한다. ReactReconciler.mountComponent() 메서드에서는 실제 ReactCompositeComponent 객체와 ReactDOMComponent 객체의 mountComponent() 메서드를 호출하며, 이 시점에 주요 작업이 시작된다.
ReactCompositeComponent
ReactCompositeComponent의 주요 작업은 다음과 같다.
- constructor() 메서드 실행
- componentWillMount() 메서드 실행
- 렌더링 실행
- 배치 처리 작업(ReactReconcileTransaction 객체)에 메서드나 속성 등록
- componentDidMount() 메서드가 있으면 componentDidMount() 메서드 등록
- ref 속성이 있으면 attachRefs 속성 등록
- 하위 ReactComponent 객체가 있으면 ReactComponent 객체를 생성하고 다시 ReactReconciler.mountComponent() 메서드를 실행
App 컴포넌트가 생성되면 <div> 엘리먼트를 생성한다. <div> 엘리먼트와 같은 실제 DOM과 함께 ReactDOMComponent 객체가 생성되며 주요 작업은 다음과 같다.
- 실제 DOM 생성
- style 속성과 attr 속성 추가
- 배치 처리 작업(ReactReconcileTransaction 객체)에 사용자 이벤트 등록
- 하위 ReactComponent 객체가 있으면 ReactComponent 객체를 생성하고 다시 ReactReconciler.mountComponent() 메서드를 실행
- 최상위 DOM(root DOM)에 DOM을 추가(현재 최상위 DOM은 document 객체에 추가되지 않은 상태)
자식 컴포넌트로 내려가면서 ReactDOMComponent 객체와 ReactCompositeComponent 객체의 주요 작업을 반복적으로 실행하며 Virtual DOM을 생성한다.
이렇게 Virtual DOM이 완성된 후 등록된 배치 처리 작업이 다음과 같이 실행된다.
- ReactReconcileTransaction 객체
- componentDidMount() 메서드를 실행한다(componentDidXXX() 메서드 실행 시점에는 DOM에 접근할 수 있다).
- 기본 이벤트를 등록한다.
- 추가한 이벤트를 등록한다.
- ref 속성 추가 등 기타 작업을 실행한다.
- ReactDefaultBatchingStrategy 객체
- componentWillMount() 메서드와 componentDidMount() 메서드에서 상태를 변경했다면 이 시점에 상태를 갱신하는 작업이 시작된다.
이 작업들을 참고한 Naver D2에서 애니메이션으로 표현한 영상을 제공한다.
https://d2.naver.com/helloworld/9297403