React의 실행 과정 자세히 살펴보기
React의 실행 과정 자세히 살펴보기
여러분 혹시 React 앱이 '딱 실행되는 순간'에 무슨 일이 일어나는지 궁금해본 적 있으세요?
우리가 매일 쓰는 이 프레임워크가 브라우저에서 어떻게 돌아가는지 안다면,
디버깅도 훨씬 쉬워지고 성능 최적화도 감이 잡히기 시작해요!
안녕하세요!
오늘은 React 앱의 실행 흐름에 대해 차근차근 뜯어보는 시간을 가져보려 해요.
React를 처음 접했을 때 가장 헷갈리는 부분 중 하나가 바로 "대체 어떤 순서로 실행되고 렌더링되는 거지?"라는 거잖아요.
그래서 준비했습니다. index.html부터 컴포넌트 렌더링, 가상 DOM과 diffing 알고리즘까지!
이미지를 곁들여 시각적으로도 쉽게 이해할 수 있도록 구성했으니까, React를 막 배우는 분들이라면 꼭! 끝까지 읽어주세요 😊
목차
1. React 앱의 초기 로딩 🚀
React 앱은 단순한 HTML 문서처럼 보이지만, 사실 정교한 번들링 시스템과 렌더링 흐름을 포함하고 있어요. 앱을 브라우저에서 처음 실행할 때는 다음과 같은 단계가 순차적으로 이뤄집니다.
① HTML 파일 로드 📄
- React 프로젝트는 index.html이 기본 진입점입니다.
- 해당 HTML 파일은 매우 간단하지만 React 앱의 기반 DOM 요소를 담고 있어요.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React App</title>
</head>
<body>
<div id="root"></div>
<script src="/static/js/bundle.js"></script>
</body>
</html>
이 중에서 <div id="root">가 가장 중요해요! React가 여기 안에 모든 UI를 렌더링하거든요.
② JavaScript 번들 로드 📦
이제 HTML을 다 불러왔으면, 본격적으로 JavaScript 번들 파일이 등장합니다. React 앱에서 작성한 모든 JS 코드들은 Webpack이나 Vite 같은 번들러를 통해 bundle.js로 합쳐져요.
- 이 파일은 모든 React 컴포넌트, 상태 관리 코드, 라우팅 로직 등을 포함하고 있어요.
- 브라우저가 이 JS 번들을 실행하면서 React 앱이 동작을 시작하죠.
🔎 정리: 초기 로딩 순서
단계 | 설명 |
---|---|
1 | index.html 로드 (root div 포함) |
2 | bundle.js 로딩 (JS 번들 실행) |
3 | React 앱 구동 시작 |
이 모든 일이 단 0.몇 초 안에 일어난다는 사실, 진짜 놀랍지 않나요? 😮
이제 다음으로 넘어가서 실제 React 컴포넌트가 DOM에 어떻게 렌더링되는지 확인해볼게요!
2. ReactDOM을 사용한 렌더링 🖥️
HTML이 모두 로드되고, JavaScript 번들이 실행되면 드디어 ReactDOM이 등장해요.
이 녀석이 하는 일은, 우리가 만든 React 컴포넌트를 브라우저의 DOM에 실제로 "마운트"하는 것입니다.
즉, 눈에 보이게 만들어주는 거죠!
① createRoot 사용법 (React 18 기준)
예전에는 ReactDOM.render
를 썼지만, 이제는 React 18부터는 createRoot가 표준이 되었어요.
이건 동시성 기능(concurrent rendering)을 제대로 활용하기 위해 도입된 변화랍니다.
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
이 코드에서 createRoot
는 브라우저 DOM에서 id가 root인 요소를 찾아 React 앱을 거기에 렌더링하겠다고 선언하는 거예요.
② App 컴포넌트는 왜 항상 위에 있을까?
- App 컴포넌트는 React 앱의 진입점이자 최상위 컴포넌트입니다.
- 이 안에서 다른 모든 컴포넌트들이 트리 구조로 하위에 배치되어요.
이 구조는 마치
HTML의 <body> 안에 섹션들이 있는 것
처럼 생각하면 돼요.
모든 페이지와 기능은 결국 이 App 컴포넌트 안에서 시작됩니다.
📌 실전 포인트 요약
항목 | 설명 |
---|---|
createRoot | React 18의 렌더링 시작점. 동시성 지원 |
App 컴포넌트 | 모든 컴포넌트 트리의 최상단 위치 |
root div | 실제 HTML에서 React가 렌더링되는 공간 |
여기까지 오면 이제 화면에 React가 "짠!" 하고 나타나는 거죠.
다음 단계에서는 App 안에서 어떻게 컴포넌트들이 그려지는지 더 깊이 들어가 볼게요 🎨
3. 컴포넌트 구조와 JSX 변환 🎨
React의 진짜 매력은 바로 컴포넌트 기반 아키텍처에 있어요.
컴포넌트를 쌓고 연결하고 조립해서 하나의 앱을 완성하는 방식은 정말 직관적이고, 마치 레고 블록을 조립하는 것 같죠.
① 함수형 컴포넌트의 기본 구조
function App() {
return (
<div>
<h1>Hello, React!</h1>
<MyComponent />
</div>
);
}
이건 React 앱에서 가장 기본적인 구조예요.
<MyComponent />
처럼 다른 컴포넌트를 끼워넣는 것도 엄청 간단하죠?
② JSX: JavaScript + XML?
React에서 사용하는 문법인 JSX는 말 그대로 JavaScript 안에서 HTML을 작성하는 느낌이에요.
근데 사실 이건
브라우저가 직접 해석할 수 없어요
- Babel이 JSX를 JavaScript 코드로 변환해줘요.
- JSX는 결국
React.createElement()
호출로 바뀌어요.
🧪 JSX 변환 예시
JSX 코드 | JS 코드 (변환 결과) |
---|---|
<h1>Hello</h1> | React.createElement('h1', null, 'Hello') |
<div className="box"></div> | React.createElement('div', { className: 'box' }) |
즉, JSX는 편하게 작성하기 위한 껍데기고, 진짜 중요한 건 React의 내부 함수들이라는 거예요.
🧩 정리: React 컴포넌트 핵심 요약
- React는 컴포넌트 단위로 UI를 구성
- JSX를 이용해 컴포넌트 작성
- JSX는 Babel을 통해 JS로 변환
다음 챕터에서는, 이 JSX로 만들어진 컴포넌트가 어떻게 가상 DOM을 만들고, 최종 화면으로 이어지는지 볼 거예요.
진짜 React의 마법이 시작되는 순간이죠! 🌳✨
4. 가상 DOM과 리렌더링 과정 🌳
React의 핵심을 단 하나만 꼽으라면, 단연 Virtual DOM(가상 DOM)이에요.
그냥 DOM을 쓰지 왜 굳이 가상을 만들었을까요?
그 이유는 바로... 성능입니다.
① Virtual DOM이란?
- 메모리 상에 존재하는 DOM의 복사본이에요.
- 실제 DOM을 직접 건드리지 않고, 변경 내용을 먼저 Virtual DOM에 적용해봐요.
왜 이렇게 하냐구요?
DOM 조작은 무겁고 느리니까요
React는 효율적으로 비교하고 최소한의 변경만 실제 DOM에 반영하려는 거예요.
② 리렌더링 흐름 정리 🔄
- 컴포넌트 상태(state)나 props가 변경됨
- 변경된 상태를 기반으로 새 Virtual DOM을 생성
- 이전 Virtual DOM과 새 Virtual DOM을 비교 (Diffing)
- 변경이 필요한 최소한의 실제 DOM 조작만 수행
📊 성능 비교 예시
방식 | DOM 조작 범위 | 성능 |
---|---|---|
기존 방식 | 전체 DOM 새로 그리기 | 느림 |
React 방식 | 변경된 부분만 반영 | 빠름 |
🔍 Diffing 알고리즘의 핵심
React는 O(n) 복잡도의 효율적인 알고리즘으로 이전 가상 DOM과 새 가상 DOM을 비교해요.
동일한 컴포넌트는 key를 기준으로 비교하고, 재사용 가능한 건 살리고 아닌 건 새로 생성하죠.
이 과정을 통해 React는 실제 DOM 변경을 최소화하면서도 UI를 항상 최신 상태로 유지해주는 거예요.
정말 효율적이죠?
다음은 상태(state)와 props가 이 흐름에 어떻게 영향을 주는지 알아봅시다 ⚙️
5. 상태(State)와 Props 흐름 ⚙️
React를 제대로 이해하려면 반드시 알아야 할 두 가지가 있어요.
바로 state와 props입니다.
이 둘이 어떻게 흐르고, 변경되며, UI를 업데이트시키는지 알면 React는 거의 마스터했다고 봐도 무방해요!
① Props: 외부로부터 받는 데이터
- 부모 컴포넌트가 자식 컴포넌트에 전달하는 값이에요.
- 읽기 전용이며 컴포넌트 내부에서 수정할 수 없어요.
function Welcome(props) {
return <h1>안녕하세요, {props.name}님!</h1>;
}
② State: 내부에서 바뀌는 값
- 컴포넌트 내부에서 생성되고 관리되는 데이터입니다.
-
useState
훅을 사용해서 선언하고 갱신해요.
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>현재 카운트: {count}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
);
}
📌 Props vs State 요약 비교
구분 | Props | State |
---|---|---|
역할 | 부모 → 자식 데이터 전달 | 컴포넌트 내부 데이터 관리 |
변경 가능 여부 | 읽기 전용 | 변경 가능 (setState 또는 set 함수) |
리렌더링 | 변경 시 자식만 렌더링 | 변경 시 해당 컴포넌트 리렌더링 |
즉, props는 위에서 아래로 흐르는 값이고, state는 컴포넌트 내부에서 변화하는 값이에요.
이걸 이해하면 이제 사용자 입력이나 이벤트에 따라 어떻게 UI가 바뀌는지도 훨씬 잘 이해되실 거예요 😊
6. 이벤트 처리와 최종 업데이트 🔁
자, 이제 우리가 만든 React 앱에 사용자가 클릭하거나, 입력하거나, 마우스를 올리는 등의 이벤트가 발생할 때 무슨 일이 벌어지는지를 알아볼 차례예요.
이건 React 앱이 ‘살아있다’는 걸 보여주는 아주 중요한 부분이에요!
① 이벤트 바인딩 방식
HTML처럼 onclick
이런 거 안 써요!
React에서는 카멜 표기법으로 이벤트를 정의하고, 함수도 함께 넘겨야 해요.
function ButtonClicker() {
const handleClick = () => {
alert('버튼이 클릭되었습니다!');
};
return (
<button onClick={handleClick}>클릭해보세요</button>
);
}
② 상태(state) 변화 → 리렌더링
사용자가 이벤트를 일으키면, 대부분은 내부 상태(state)에 변화가 생겨요.
그러면 React는 전체 컴포넌트를 다시 렌더링하는 게 아니라, 변경된 부분만 골라서 가상 DOM을 통해 업데이트해요.
📌 실전 예제 - 카운터 버튼
function Counter() {
const [count, setCount] = React.useState(0);
return (
<div>
<p>현재 숫자: {count}</p>
<button onClick={() => setCount(count + 1)}>+ 증가</button>
</div>
);
}
여기서 버튼을 누를 때마다 count
값이 증가하고, 컴포넌트가 자동으로 다시 그려지는 거예요.
이게 React의 핵심 흐름이죠.
🔁 이벤트 → 상태 변화 → UI 반영 요약
- 사용자가 버튼 클릭 등 이벤트 발생
- 핸들러 함수 실행 → 상태 변화
- Virtual DOM이 새로운 UI 생성
- 변경된 부분만 DOM에 반영
📌 자주 쓰는 이벤트 목록
이벤트 종류 | 사용 예 |
---|---|
onClick | 버튼 클릭, 아이콘 클릭 |
onChange | input, select 값 변경 |
onSubmit | 폼 전송 시 |
onMouseEnter / Leave | 호버 효과 |
이처럼 이벤트 처리 → 상태 변화 → 가상 DOM 생성 → DOM 업데이트까지!
이 모든 걸 React가 알아서 해준다는 거, 진짜 대단하지 않나요?
덕분에 우리는 비즈니스 로직에만 집중할 수 있죠! 🙌
🔚 React 실행 흐름, 이제 보이시나요?
지금까지 React 앱이 브라우저에서 실제로 어떻게 실행되는지, 그리고 그 속에서 어떤 로직이 일어나는지를 단계별로 살펴봤어요.
index.html
→ bundle.js
→ createRoot
→ JSX → 가상 DOM → 상태 변경 → 이벤트 → 리렌더링
이 전체 흐름이 머릿속에 하나의 선으로 연결되었다면,
여러분은 이제 진짜 React의 구조를 꿰뚫은 거예요! 🎉
처음엔 다소 복잡하게 느껴질 수도 있어요.
하지만 몇 번만 실습을 반복하면 자연스럽게 손이 기억하게 됩니다.
특히 상태와 props의 흐름, 그리고 가상 DOM의 작동 원리를 정확히 이해하면 훨씬 안정적인 코드와 성능 좋은 React 앱을 만들 수 있어요.
조금씩, 천천히, 꾸준히. React는 그렇게 여러분 편이 되어줄 거예요 😄
✅ 다음으로 하면 좋은 실습
- React Developer Tools 확장 설치해서 Virtual DOM 직접 관찰해보기
- 상태 변경에 따라 UI가 어떻게 변하는지 console.log로 추적해보기
- 부모 → 자식 → 자식 → 다시 부모로 props/state 흐름 역추적해보기