브라우저 렌더링 원리: Reflow와 Repaint 최적화 가이드 (CRP 심층 분석)
📌 핵심 요약
- CRP(Critical Rendering Path)의 5단계: DOM → CSSOM → Render Tree → Layout → Paint
- 성능의 주범 Reflow(Layout)와 Repaint의 차이점
- 애니메이션 성능 최적화: 왜
top/left대신transform을 써야 하는가? (GPU 가속과 Composite)
"사용자가 주소창에 URL을 입력하고 엔터를 쳤을 때, 화면에 네이버 메인이 뜨기까지 무슨 일이 일어나는가?"
이 질문은 네트워크 관점(DNS, TCP/IP)에서도 답변할 수 있지만, 프론트엔드 개발자라면 렌더링 엔진(Rendering Engine)이 HTML과 CSS를 해석해서 픽셀로 바꿔주는 과정, 즉 CRP(Critical Rendering Path)를 설명할 수 있어야 합니다. 이 원리를 알아야 "왜 리액트가 Virtual DOM을 쓰는지", "왜 애니메이션이 버벅이는지" 이해할 수 있습니다.
1. 렌더링 파이프라인 (The Pipeline)
브라우저는 다음 5단계를 거쳐 화면을 그립니다.
- DOM 트리 생성: HTML 문서를 파싱 하여 태그 간의 관계(부모-자식)를 트리 구조로 만듭니다.
- CSSOM 트리 생성: CSS 파일과 인라인 스타일을 파싱 하여 스타일 규칙 트리를 만듭니다.
- Render Tree 생성: DOM과 CSSOM을 결합하여 "실제로 화면에 표시될 노드"만 추려냅니다.
- Layout (Reflow): 각 노드가 화면의 어느 위치에, 어떤 크기(px)로 배치될지 기하학적 계산을 수행합니다.
- Paint (Repaint): 계산된 위치에 색상을 채우고, 텍스트를 그리고, 이미지를 렌더링 합니다.
- Composite: 여러 레이어(Layer)를 합쳐서 최종적으로 화면에 출력합니다.
⚠️ 주의: Render Tree의 비밀
display: none이 적용된 요소는 Render Tree에서 제외됩니다. (화면에 공간도 차지하지 않음)
반면, visibility: hidden은 공간은 차지하므로 Render Tree에 포함됩니다. (Layout 단계 계산에 참여함)
2. 성능 킬러: Layout (Reflow)
웹 성능 최적화의 핵심은 "Layout 단계를 최대한 피하는 것"입니다.
Layout(Reflow)은 요소의 위치와 크기를 재계산하는 과정입니다. 부모 요소의 크기가 바뀌면, 자식 요소들의 위치도 싹 다 다시 계산해야 합니다. 즉, 도미노처럼 연산이 일어납니다.
Reflow가 발생하는 경우
- 창 크기 변경 (Resizing)
- 폰트 변경, 스타일 추가/제거
- 위치/크기 관련 속성 변경:
width,height,top,left,margin,padding등
3. Paint (Repaint)
Layout이 끝나면 픽셀을 그리는 Paint 단계가 실행됩니다. Reflow가 발생하면 Repaint는 무조건 따라옵니다. 하지만 레이아웃 수치에는 영향을 주지 않고 "보이는 모습"만 바뀌면, Layout을 건너뛰고 Paint만 수행합니다. 이를 Repaint라고 합니다.
Repaint만 발생하는 경우 (비용 절감)
color,background-color,visibility,box-shadow등
4. 최적화 끝판왕: Composite (GPU 가속)
가장 이상적인 것은 Layout과 Paint를 모두 건너뛰고 Composite 단계만 수행하는 것입니다. 이것이 가능한 속성이 바로 Transform과 Opacity입니다.
| 애니메이션 속성 | 발생 단계 | 비용 |
|---|---|---|
left, top |
Layout -> Paint -> Composite | 매우 비쌈 (CPU 사용) |
transform |
Composite Only | 매우 저렴 (GPU 사용) |
transform: translate()를 사용하면 브라우저는 해당 요소를 별도의 레이어(Layer)로 분리하여 GPU에게 던져버립니다. 메인 스레드(CPU)는 레이아웃 계산에서 해방되고, GPU가 비트맵 이미지를 이동시키기만 하므로 60fps 애니메이션이 부드럽게 돌아갑니다.
5. 결론
브라우저는 게으를수록(Lazy) 빠릅니다. 성능 최적화를 위해 다음 3가지를 기억하세요.
- DOM 트리의 깊이를 얕게 유지하십시오.
- 애니메이션에는 반드시
transform과opacity만 사용하십시오. - DOM 변경은 모아서 한 번에(Batch) 처리하십시오. (React가 알아서 해주는 이유)