[서버] HTML/CSS/JS 전달
↓
[브라우저 네트워크 계층] 파일 다운로드
↓
[브라우저 렌더링 엔진] HTML/CSS 파싱 → DOM/CSSOM 생성
↓
[렌더링 엔진] 스타일 계산 → Render Tree 생성
↓
[렌더링 엔진] Layout(배치)
↓
[렌더링 엔진] Paint(픽셀 그리기)
↓
[GPU] Composite(레이어 합성)
↓
[브라우저] 화면에 표시
1. HTML 파싱 → DOM 생성
태그마다 노드가 생성됨.
2. CSS 파싱 → CSSOM 생성
스타일 시트 내용을 트리 구조로 만듦.
3. DOM + CSSOM = Render Tree 생성
각 요소가 어떤 스타일을 적용받는지 결정.
4. Layout(배치)
각 요소가 화면의 어디에 위치하고 얼마나 큰지 계산.
5. Paint(그리기)
각 요소를 픽셀 단위로 실제로 칠함.
6. Composite
레이어를 합성하고 브라우저에 표시.
📌 중요한 개념
✅ 2. React 렌더링이 DOM을 “최소 변경”하는 원리
React는 단순 DOM 작업을 직접 하지 않고:
✅ UI = f(state) 함수라고 가정하고 렌더링
상태가 바뀌면 컴포넌트를 다시 함수처럼 실행해서 새로운 Virtual DOM을 만듦.
👉 하지만 바뀐 부분만 실제 DOM에 반영해야 효율적이니까…
✅ Virtual DOM diff(비교) 단계가 등장
React는:
이전 Virtual DOM
새로 계산한 Virtual DOM
둘을 비교함.
→
✅ className만 바뀌었으니
✅ 실제 DOM에서도 class 속성만 교체
✅ 실제 layout 계산도 paint 재실행도 최소화됨
즉, React가 하는 일은:
“리렌더링은 컴포넌트 함수 재실행일 뿐이고,
실제 DOM 변경은 diff에서 결정된다.”
그래서 성능이 좋아지는 것.
✅ 3. Virtual DOM에서 className 비교는 이렇게 일어남
리렌더링 시
이런 식으로 Virtual DOM 객체가 생성됨.
JS로 표현하면:
{
type: "button",
props: {
className: "rounded p-2 text-white bg-green-500",
children: "동적 버튼"
}
}
이전 Virtual DOM의 같은 버튼 노드와 비교해서:
태그 동일 → 계속 탐색
className 문자열 비교 → 변경됨
따라서 class 속성만 업데이트
→ DOM 속성 바꿔주는 정도면 매우 빠름
→ Layout과 Paint도 브라우저가 최소 범위만 다시 수행
✅ 4. Tailwind JIT는 “클래스 문자열만 보고 스타일 추가하는 엔진”
Tailwind JIT(Just-In-Time)는 이런 구조:
✅ 빌드 시
코드 안의 모든 Tailwind class 문자열을 스캔해서
필요한 CSS만 생성 (트리셰이킹)
예:
bg-green-500이 등장하면 그 CSS 정의만 만들어 둠.
✅ 런타임에는 “정적 CSS”만 브라우저가 읽음
Tailwind는 런타임에 JS 동작이 없음.
그냥 CSS만 브라우저가 적용.
즉,
React가 동적으로 className 문자열만 바꾸면
Tailwind는 그 문자열에 해당하는 CSS를 이미 빌드해 둔 걸 적용한다.
✅ 브라우저 입장에서는 그냥 CSS 클래스가 바뀌었을 뿐
✅ 새로운 JS 비용 없음
✅ Paint만 다시 일어나는 수준
그래서 Tailwind가 빠른 거야.
✅ 5. CSS-in-JS 는 왜 로딩이 느리고 Tailwind보다 무거운가?
CSS-in-JS (styled-components, emotion 등)는 Tailwind와 다름.
✅ CSS-in-JS는 런타임에 JS로 CSS를 생성
즉 이런 코드가:
const Button = styled.button background-color: ${(props) => props.color};;
실행될 때마다 JS가 DOM에
🚨 런타임 비용 발생
JS 실행 시간
DOM에 스타일 태그 주입 비용
해시 생성 비용
SSR 시에도 스타일 문자열 생성
Tailwind는 빌드 시 정적 CSS 생성 → 런타임 작업 0
CSS-in-JS는 런타임에 계속 JS가 실행됨 → 느리고 무거움
✅ 그래서 초기 로딩 시간에 차이가 크게 난다.
✅ Tailwind가 훨씬 빠르고 가볍다.
✅ 6. Server Components와 Tailwind/CSS-in-JS 관계
Next.js의 서버 컴포넌트는:
렌더링을 서버에서 하고
HTML을 완성된 형태로 브라우저에 전달함
JS 번들을 최소화할 수 있음
📌 Tailwind는 SSR과 특히 잘 맞음
→ 이미 CSS를 빌드 타임에 생성해 두기 때문
→ 서버는 그냥 class 문자열이 들어간 HTML을 전달하면 됨
→ 브라우저는 CSS 파일 한 번만 읽으면 됨
✅ JS 다운로드 감소
✅ 스타일 계산 비용 없음
✅ 초기 로딩 빠름
📌 반면 CSS-in-JS는 SSR 단계에서도 스타일을 “문자열로 생성”해야 함
→ 서버에서 스타일 생성 JS 실행
→ 클라이언트에서 hydration할 때도 JS 필요
→ 번들 사이즈 커짐
→ 느림
✅ 7. 전체 흐름을 하나의 그림으로 정리하면
🔷 Tailwind + React + 브라우저 렌더링 흐름
Tailwind가 빌드 시 필요한 CSS만 만들어 둠
React는 리렌더링 시 Virtual DOM만 재계산
Diff에서 달라진 className만 실제 DOM에 패치
브라우저는 변경된 스타일만 다시 Paint
초기 로딩도 빠르고, 동적 업데이트도 빠름
🔶 CSS-in-JS 흐름
런타임에 JS로 스타일 생성
DOM에 style 태그 삽입
브라우저가 다시 CSSOM 생성
Paint
런타임 비용으로 초기 로딩이 느림
CSR, SSR 모두 JS 비용이 큼