-
[React] 리액트 Render와 CommitReact 2023. 10. 24. 17:36
리액트에서 컴포넌트는 화면에 보이기 전에 반드시 렌더링이 된다고 합니다.
그리고 이 렌더링 과정을 공식문서에는 아래와 같은 세 가지 단계로 설명을 하고 있습니다.
1. 렌더링 트리거 (Triggering a render)
2. 컴포넌트 렌더링 (Rendering the component)
3. DOM에 커밋 (Commiting to the Dom)먼저 각 단계가 어떤 것을 의미하는지 알아보겠습니다.
| 렌더링 트리거 (Trigger a render)
컴포넌트가 렌더링 되는 이유는 2가지가 있다고 하는데 아래와 같습니다.
1. 컴포넌트의 초기에 렌더링
2. 해당 컴포넌트나 상위 컴포넌트의 상태(state)가 업데이트되었을 때1. 초기 렌더링
앱이 시작되면 초기 렌더링을 트리거하는 것이 필요합니다. 그리고 이것은 타깃 DOM 노드와 함께 createRoot를 호출하고,
컴포넌트와 함께 render 메서드를 호출하는 것으로 수행이 됩니다.
import App from "./App.js"; import { createRoot } from "react-dom/client"; const root = createRoot(document.getElementById("root")); root.render(<App />);
-> createRoot는 브라우저 DOM 노드 내 React 컴포넌트를 보여주는 루트를 생성
2. 상태 업데이트에 의한 재렌더링
컴포넌트가 초기에 렌더링이 되면 set함수를 사용해 상태(state)를 업데이트하면 추가적인 렌더링을 실행할 수 있습니다.
컴포넌트의 상태를 업데이트하면 자동으로 렌더 큐에 추가됩니다.
| 컴포넌트 렌더링(Rendeting the component)
컴포넌트 렌더링이 트리거 된 후, 리액트는 화면에 어떤 것이 보여야 할지 알아내기 위해 컴포넌트를 호출합니다.
-> "Rendering"은 리액트가 컴포넌트를 호출하는 것을 의미
1. 초기 렌더링에서 리액트는 root컴포넌트를 호출
2. 그 후의 렌더링에서는 리액트는 상태의 업데이트로 렌더링이 트리거 된 컴포넌트를 호출이런 프로세스는 재귀적으로 발생합니다. 만약 업데이트된 컴포넌트가 다른 컴포넌트를 반환하면,
리액트는 다음에 그 컴포넌트를 렌더링 합니다. 마찬가지로 이 컴포넌트가 또 다른 컴포넌트를 반환하면,
리액트는 그 컴포넌트를 다음으로 렌더링을 합니다.
이는 다른 중첩된 컴포넌트가 없고 리액트가 화면에 어떤 것을 표시해 줄지 정확히 알기 전까지 계속됩니다.
export default function Hello() { return ( <div> <h1>Hello</h1> <World /> <World /> <World /> </div> ); } function World() { return <p>hello world</p> }
위 코드에서는 초기 렌더링이 진행되는 동안, 리액트는 <div>, <h1>, 3개의 <p> 태그에 대한 DOM 노드를 생성을 하고,
재 렌더링 되는 동안에는 리액트는 이전 렌더링 이후 바뀐 속성이 있으면 그 속성이 어떤 것인지 계산을 합니다.
| DOM에 커밋(Commiting to the Dom)
컴포넌트를 렌더링 한 후 리엑트는 DOM수정을 합니다.
1. 초기 렌더링에서 리액트는 appendChild()를 사용하여 생성된 모든 DOM 노드를 화면에 표시
2. 재 렌더링 시에는 리액트는 최근 렌더링 결과와 일치하도록 최소한의 필수 작업을 적용 (diffing 알고리즘)리액트는 렌더링 간 차이가 있는 DOM노드만 변경을 해줍니다.
아래 예시를 보면 매초 state가 업데이트되어 리렌더링 될 때 <input>의 값이 사라지지 않는 것을 볼 수 있습니다.
export default function App() { const [currentTime, setCurrentTime] = useState(new Date()); useEffect(() => { const intervalId = setInterval(() => { setCurrentTime(new Date()); }, 1000); return () => { clearInterval(intervalId); }; }, []); return ( <> <h1>{currentTime.toLocaleTimeString()}</h1> <input /> </> ); }
위 코드에서 리액트는 새로운 currentTime을 가지고 <h1> 태그의 내용만 업데이트해 줍니다.
그리고 <input>은 JSX에서 이전과 같은 위치에 나타나기 때문에 그 값을 건드리지 않습니다.
| 브라우저 페인트 (Browser paint)
렌더링이 끝나고 리액트가 DOM을 업데이트하면 브라우저는 화면을 다시 페인트(repaint)를 하는데
이를 "브라우저의 렌더링"이라고 합니다.
| 참고
'React' 카테고리의 다른 글
[React] React lazy로 웹 성능 최적화 하기 (코드 스플리팅) (0) 2024.02.12 [React] 상태 관리를 통한 사용자 경험 개선 (페이지 전환) (0) 2024.02.06 [React] 이벤트 버블링(bubbles, propagates) (0) 2023.10.23 [React] 커스텀 훅 만들기(Custom Hooks) (1) 2023.10.09 [React] create-react-app 작업 환경 구성, 파일 정리 (0) 2023.07.18