노트

브라우저 렌더링 파이프라인

Critical Rendering Path

프런트엔드#browser#performance · 연결된 개념 14개

쉽게 말하면

브라우저 렌더링 파이프라인은 HTML·CSS·JS를 받아 화면 그림으로 바꾸는 순서예요. 설계도를 읽고, 무엇을 어디에 둘지 재고, 색을 칠하고, 투명 필름 여러 장을 겹쳐 완성하는 식이죠.

비유가 깨지는 곳 그림처럼 한 번 그리고 끝나지 않아요. 뭔가 바뀔 때마다 다시 돌고, 바뀐 내용에 따라 레이아웃부터 할지 합성만 할지가 달라요. 60Hz 화면이면 한 프레임을 약 16.7ms 안에 끝내야 해요.

브라우저가 받은 HTML·CSS·JS를 화면의 픽셀로 바꾸는 순서. 처음 로드할 때도, 이후 무언가 바뀔 때도 같은 단계를 거친다. 바뀐 내용에 따라 어느 단계부터 다시 시작하는지만 다르다.

단계

  1. 파싱(Parsing): HTML을 위에서부터 읽어 DOM(Document Object Model) 트리를, CSS를 읽어 CSSOM(CSS Object Model) 트리를 만든다. 동기 <script>를 만나면 파싱이 멈추고, CSS는 렌더링을 막는 리소스다
  2. 스타일 계산(Style): DOM과 CSSOM을 합쳐 노드마다 최종 스타일을 정한다(캐스케이드가 여기서 적용된다)
  3. 렌더 트리(Render Tree): 실제로 그릴 노드만 모은다. display: none은 빠지고, visibility: hidden은 자리를 차지하므로 남는다
  4. 레이아웃(Layout): 노드마다 크기와 위치를 계산한다. 다시 계산하는 것을 리플로우라고 부른다
  5. 페인트(Paint): 글자·색·테두리·그림자를 픽셀로 칠한다. 다시 칠하는 것을 리페인트라고 부른다
  6. 합성(Compositing): 여러 레이어를 순서대로 겹쳐 최종 프레임을 만든다. 주로 GPU(Graphics Processing Unit)가 맡는다 → 합성 단계와 transform·opacity
flowchart TD
  H[HTML] -->|파싱| D[DOM]
  C[CSS] -->|파싱| O[CSSOM]
  D --> S[스타일 계산]
  O --> S
  S --> R["렌더 트리 (그릴 노드만)"]
  R --> L["레이아웃 (크기·위치)"]
  L --> P["페인트 (픽셀 칠하기)"]
  P --> X["합성 (레이어 겹치기)"]

한 프레임은 대략 JS → 스타일 → 레이아웃 → 페인트 → 합성 순으로 흐르고, 60Hz 화면이라면 이 모든 과정이 약 16.7ms 안에 끝나야 끊기지 않는다. 화면을 다시 그릴 기회는 이벤트 루프의 렌더링 단계에서 오고, requestAnimationFrame 콜백은 그 직전에 실행된다.

자주 헷갈리는 점

  • 서버에서 렌더링(SSR, Server-Side Rendering)하거나 서버 컴포넌트(React Server Components)를 써도 서버가 보내는 것은 클래스가 붙은 HTML과 CSS 파일뿐이다. 스타일 계산·레이아웃·페인트는 언제나 브라우저가 한다. Tailwind CSS가 "서버용 CSS"가 아닌 이유도 같다
  • SPA(Single Page Application)는 처음에 빈 HTML을 받고 JS가 DOM을 만든 뒤에야 이 파이프라인이 의미 있는 화면을 그린다. React는 Virtual DOM과 재조정으로 실제 DOM 변경을 줄이는데, 결국 이 파이프라인을 다시 도는 횟수를 줄이는 일이다
  • 레이아웃 값을 읽는 코드가 끼어들면 브라우저가 단계를 앞당겨 실행한다 → 레이아웃 스래싱

출처: MDN — How browsers work: Render · MDN — Critical rendering path

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • 스트리밍 SSR

    스트리밍 SSR(Streaming Server-Side Rendering)은 서버가 페이지 전체를 다 만들 때까지 기다리지 않고, 준비된 부분의 HTML(HyperText Markup Language)부터 먼저 보내고 느린 부분은 준비되는 대로 같은 응답에 이어서 흘려보내는 렌더링 방식이다. suspense 경계가 나눔의 단위다.

  • CSS-in-JS와 빌드 타임 CSS

    JS(JavaScript) 안에서 스타일을 정의하고, 렌더링할 때 라이브러리가 클래스를 만들어 style 태그로 주입하는 방식. styled-components와 Emotion이 대표다. React 18 이후 서버 컴포넌트(React Server Components)·스트리밍 SSR(Streaming Server-Side Rendering)이 자리 잡으면서 런타임에 CSS를 만드는 방식은 줄고, 빌드할 때 CSS를 뽑는 방식이 늘었다(2026 기준).

  • 브라우저 캐시

    한 번 받은 리소스(HTML·CSS·JS·이미지)를 브라우저가 저장해 두었다가 다시 쓰는 기능. 서버가 응답 헤더로 얼마나, 어떻게 캐시할지 알려 주고 브라우저가 그대로 따른다.

  • 크로스 브라우징

    크로스 브라우징은 브라우저 종류·버전·기기가 달라도 웹 페이지가 같은 기능을 제공하도록 만드는 일이다. 모든 브라우저에서 픽셀까지 똑같이 보이게 하는 것이 목표가 아니라, 지원하기로 한 환경에서 핵심 기능이 동작하고 오래된 환경에서도 쓸 수는 있게(점진적 향상, Progressive Enhancement) 하는 것이 목표다.

  • 부분 사전 렌더링(PPR)

    PPR(Partial Prerendering)은 한 라우트를 빌드 때 만든 정적 셸(Static Shell)과 요청 때 채우는 동적 구멍으로 나눠, 셸은 즉시 보내고 구멍은 스트리밍으로 채우는 렌더링 모델이다. Next.js 16에서 Cache Components(cacheComponents: true)를 켜면 기본 동작이다(2026 기준).

보기 옵션