Files
2nd/10_Wiki/Topics/Reflow_&_Repaint.md
T

50 KiB

category, tags, title, last_updated
category tags title last_updated
Unified
auto-consolidated
technical-documentation
Reflow & Repaint|Reflow & Repaint
2026-05-02

Reflow & Repaint

📌 Brief Summary

리플로우(Reflow)는 브라우저가 렌더 트리를 기반으로 문서 내 요소들의 정확한 위치와 크기(기하학적 구조)를 계산하여 배치하는 과정이며, 리페인트(Repaint)는 계산된 레이아웃을 바탕으로 화면에 실제 픽셀을 그리는 시각적 업데이트 과정이다 [1-6]. 리플로우는 요소의 추가/삭제나 크기 변경 시 발생하며 계산 비용이 매우 높은 반면, 리페인트는 배경색이나 그림자 등 시각적 속성만 변경될 때 발생한다 [5-7]. 이 두 과정은 브라우저의 중요 렌더링 경로(Critical Rendering Path)의 핵심 단계로, 과도하게 발생할 경우 브라우저 성능 저하와 화면 끊김(Jank) 현상을 유발하므로 웹 프론트엔드 성능 최적화에 있어 필수적으로 관리해야 하는 요소이다 [5, 8-10].


Reflow(Layout)와 Repaint(Paint)는 브라우저 렌더링 과정에서 요소의 크기, 위치를 계산하고 시각적 요소를 화면에 그리는 비용이 높은 작업입니다. 브라우저의 렌더링 최적화를 달성하고 매끄러운 사용자 경험(예: 60fps 유지)을 제공하기 위해서는 DOM 트리의 깊이 감소, 상태 변경의 일괄 처리, 하드웨어 가속 등을 통해 이 과정이 발생하는 빈도와 연산량을 최소화해야 합니다.


**Reflow(레이아웃)**는 브라우저가 화면에 표시될 DOM 요소들의 정확한 위치와 기하학적 크기를 재계산하는 과정이며, **Repaint(페인트)**는 레이아웃의 변화 없이 요소의 색상이나 그림자 같은 시각적 속성만을 화면에 다시 그리는 과정입니다 [1-6]. 이 두 과정은 웹 페이지 렌더링에 필수적이지만 연산 비용이 높아 과도하게 발생할 경우 애플리케이션의 성능 저하와 버벅거림(Jank)을 유발하므로 프론트엔드 최적화의 핵심 대상이 됩니다 [7-9].


Reflow는 브라우저가 문서의 레이아웃이나 요소의 기하학적 구조(너비, 높이, 위치 등)를 다시 계산하는 과정이며, Repaint는 레이아웃에는 영향을 주지 않는 시각적 변화(색상, 배경 등)를 화면에 다시 그리는 과정이다 [1, 2]. 이 두 과정은 처리 비용이 매우 높아 과도하게 발생할 경우 CSS 애니메이션과 자바스크립트의 성능을 저하시키고 화면의 버벅거림(Janky)을 유발한다 [3-5]. 따라서 효율적인 CSS 속성 선택과 DOM 조작의 최소화를 통해 Reflow와 Repaint의 발생을 줄이는 것은 유지보수 가능하고 확장성 있는 프론트엔드 아키텍처를 구축하기 위한 필수적인 렌더링 파이프라인 최적화 기법이다 [5-7].


웹 브라우저가 화면을 렌더링하는 과정에서 'Reflow(레이아웃)'는 요소의 정확한 크기와 위치 등 기하학적 구조를 계산하는 단계입니다. 반면 'Repaint(페인트)'는 계산된 구조를 바탕으로 배경색이나 텍스트 색상 같은 시각적 요소를 화면의 픽셀로 그려내는 과정입니다. 두 과정 모두 연산 비용이 들며 프레임 속도와 애플리케이션 성능에 직결되므로, 이를 최소화하는 것이 프론트엔드 렌더링 최적화의 핵심입니다 [1-3].


Reflow(리플로우)는 브라우저가 페이지 요소의 레이아웃과 기하학적 구조를 다시 계산하는 과정이며, Repaint(리페인트)는 레이아웃에 영향을 주지 않고 색상 등의 시각적 속성만 변경될 때 발생합니다 [1, 2]. 이 두 가지 과정은 브라우저 렌더링 엔진에 큰 부담을 주어 UI 성능 저하와 자바스크립트 실행 지연을 유발할 수 있는 핵심 병목 지점입니다 [1, 3]. 따라서 대규모 프론트엔드 프로젝트에서 유지보수 가능하고 최적화된 CSS를 설계하려면 리플로우와 리페인트를 최소화하는 전략이 필수적입니다 [4].


Reflow(리플로우)는 요소의 크기나 위치 등 레이아웃 구조가 변경될 때 브라우저가 문서의 구조를 다시 계산하는 과정이며, Repaint(리페인트)는 레이아웃에 영향을 주지 않는 시각적 속성(색상 등)이 변경될 때 화면을 다시 그리는 작업입니다 [1, 2]. 두 과정 모두 브라우저의 연산 리소스를 많이 소모하므로, 쾌적한 사용자 경험과 웹 성능을 유지하려면 이를 최소화해야 합니다 [1, 3, 4]. 유지보수와 성능을 모두 고려한 CSS 실전 설계에서는 이러한 브라우저 렌더링 파이프라인의 특성을 이해하고 효율적인 스타일링과 애니메이션 전략을 채택해야 합니다 [3, 5].


리플로우(Reflow)는 브라우저가 페이지의 레이아웃 변경 사항을 감지하여 문서 내 요소들의 크기, 위치 등 기하학적 구조를 재계산하는 과정입니다. 리페인트(Repaint)는 레이아웃에는 영향을 주지 않고 색상, 가시성 등 시각적인 껍데기(skin)만 변경될 때 발생하는 렌더링 과정입니다. 두 과정 모두 브라우저의 연산 비용이 매우 높으며 잦은 발생은 웹 페이지 및 애니메이션의 성능 저하(버벅거림 등)로 직결되므로, 실무 CSS 설계 시 이를 최소화하는 구조와 스타일 작성 전략이 필수적입니다.


리플로우(Reflow)는 요소의 너비, 높이 등 레이아웃이나 기하학적 구조가 변경될 때 브라우저가 문서의 구조를 재계산하는 과정이며, 리페인트(Repaint)는 레이아웃에 영향을 주지 않는 시각적 요소(색상, 배경 등)가 변경될 때 발생하여 화면을 다시 그리는 과정입니다 [1-3]. 두 과정 모두 연산 비용이 높고 렌더링 성능을 저하시켜 화면 끊김(Jank) 현상을 유발할 수 있으므로, CSS 및 애니메이션 구현 시 이들의 발생을 최소화하는 최적화 전략이 필수적입니다 [1, 4, 5].


Reflow(리플로우)는 요소의 크기나 위치 등 레이아웃이 변경될 때 브라우저가 문서의 구조와 기하학적 형태를 다시 계산하는 과정이며, Repaint(리페인트)는 레이아웃에 영향을 주지 않는 시각적 요소(색상, 배경 등)가 변경될 때 화면에 다시 픽셀을 그리는 과정입니다. 이 두 과정은 브라우저의 렌더링 리소스를 크게 소모하므로 성능 저하와 프레임 드롭의 주요 원인이 됩니다. 유지보수성이 높고 사용자 경험(UX)이 뛰어난 CSS를 설계하기 위해서는 불필요한 리플로우와 리페인트를 최소화하는 렌더링 최적화 전략이 필수적입니다.

📖 Core Content

렌더링 파이프라인 내의 역할 브라우저는 수신된 HTML과 CSS를 파싱하여 DOM (Document Object Model)과 CSSOM을 구축한 후, 가시적인 콘텐츠만 포함하는 렌더 트리(Render Tree)를 생성한다 [11-14]. 이 렌더 트리가 완성되면 요소들을 화면에 나타내기 위해 리플로우(Layout)와 리페인트(Paint) 단계가 순차적으로 실행된다 [1, 13].

리플로우 (Reflow / Layout)

  • 리플로우는 렌더 트리의 루트부터 아래로 탐색하며 뷰포트 크기와 박스 모델을 기반으로 모든 표시되는 요소의 정확한 너비, 높이, x/y 위치 좌표를 계산하는 과정이다 [1, 3, 7, 15].
  • HTML 요소들은 연속적인 문서 흐름의 일부이기 때문에, 특정 요소 하나의 기하학적 변화만으로도 트리 전체에 걸친 연쇄적인 재계산(Cascade of recalculations)을 유발할 수 있다 [1, 5, 16].
  • 브라우저 창 크기 조절, DOM 노드의 추가 및 제거, width, height, margin, padding 등의 레이아웃 관련 속성을 조작할 때 발생한다 [5, 7, 17, 18].
  • 이는 매우 계산 집약적인 작업이며, 실행되는 동안 브라우저 메인 스레드에서 사용자의 상호작용을 차단(User-Blocking)할 수 있다 [5, 7, 16].

리페인트 (Repaint / Paint)

  • 레이아웃 계산이 완료된 후, 기하학적 구조와 스타일을 바탕으로 텍스트, 색상, 그림자 등의 시각적 요소를 화면에 픽셀로 래스터화(Rasterize)하여 그리는 단계이다 [2, 4, 6, 7].
  • background-color, box-shadow, visibility, 텍스트 색상 등 레이아웃이나 요소의 크기에 영향을 주지 않는 시각적인 속성만 변경될 때 독립적으로 발생한다 [6, 7, 18].
  • 기하학적 계산을 수반하지 않기 때문에 리플로우보다는 계산 비용이 적게 들지만, 시각적 변경이 과도하게 발생할 경우 (예: 배경색 애니메이션) 렌더링 파이프라인을 방해하여 프레임 드롭(Jank)을 일으킬 수 있다 [2, 19, 20].

성능 최적화 전략

  • 불필요한 연산 최소화: DOM 트리의 깊이를 줄이고, 복잡한 CSS 선택자(특히 자손 선택자)나 사용하지 않는 CSS 규칙을 제거하여 브라우저의 매칭 및 계산 부담을 줄여야 한다 [21, 22].
  • 배칭(Batching) 및 레이아웃 스래싱 방지: DOM 변경 사항을 가급적 일괄 처리하고, 리플로우를 유발하는 속성을 읽고 쓰는 작업을 코드 내에서 번갈아 실행하여 발생하는 '레이아웃 스래싱(Layout Thrashing)' 현상을 피해야 한다 [7, 10, 23].
  • 문서 흐름 분리: 복잡한 렌더링 변경이나 애니메이션을 수행할 때는 대상 요소에 position: absolute 또는 position: fixed를 적용하여 일반적인 문서 흐름에서 분리(Out of the flow)시킴으로써 다른 요소들에 미치는 연쇄적인 리플로우를 방지할 수 있다 [22].
  • GPU 가속 활용: top이나 left 대신 transform: translate() 속성을 활용하거나 opacity를 제어하면, 레이아웃이나 페인트 사이클을 유발하지 않고 GPU를 활용한 컴포지팅(Compositing) 단계에서 화면을 업데이트할 수 있어 60fps의 부드러운 애니메이션을 유지할 수 있다 [2, 20, 24, 25].

DOM 구조 및 CSS 규칙 최적화

  • 불필요한 DOM 트리의 깊이를 줄여야 합니다. DOM 트리의 특정 노드가 변경되면 루트부터 하위 노드까지 계산이 파급되어 Reflow에 소요되는 시간이 길어집니다 [1]. React의 경우, 불필요한 래퍼(wrapper) 대신 Fragment를 사용하여 DOM 노드 수를 줄이면 브라우저의 레이아웃과 페인트 속도를 개선할 수 있습니다 [2, 3].
  • 사용하지 않는 CSS 규칙을 최소화하고, 특히 하위 선택자(descendant selectors)와 같이 CPU 연산력을 더 많이 요구하는 복잡한 CSS 선택자의 사용을 피하는 것이 좋습니다 [1]. display: none을 사용하면 요소가 Render Tree에서 완전히 제거되어 레이아웃에서 배제되므로, 렌더링을 억제할 때 유용하게 활용할 수 있습니다 [4].

DOM 접근 및 수정의 일괄 처리 (Batching)

  • 요소의 크기나 위치 등을 계산하는 속성을 반복적으로 읽고 쓰는 작업을 교차로 실행하면 "레이아웃 스래싱(Layout Thrashing)"이라는 비효율적인 Reflow가 발생합니다 [5].
  • 이를 방지하기 위해서는 DOM 값을 읽는 단계와 수정하는 단계를 명확히 분리하여 렌더링 엔진의 작업을 일괄 처리(batch)해야 합니다 [6, 7].
  • 루프 내부에서 DOM을 조작하는 것을 피하고, 접근해야 하는 DOM 노드나 속성값을 변수에 캐싱(Caching)하여 불필요하게 DOM 구조에 반복적으로 접근하는 것을 최소화해야 합니다 [6, 8].

애니메이션 최적화 및 하드웨어 가속(GPU) 활용

  • 박스 모델의 속성(width, height, margin, top, left 등)을 직접적으로 애니메이션 처리하는 것은 피해야 합니다 [9, 10].
  • 대신 시각적 변화나 애니메이션 처리를 할 때 CSS의 transform 속성(예: transform: translate())이나 opacity를 사용하면 브라우저가 새로운 Reflow나 Repaint 주기를 유발하지 않고 GPU를 통해 해당 요소를 자체 레이어에서 처리할 수 있습니다 [11-14].
  • 복잡한 렌더링 변경이나 애니메이션을 수행할 때는 position: absolute 또는 position: fixed를 적용하여 해당 요소를 문서의 일반적인 흐름(flow)에서 분리시켜 다른 요소에 미치는 Reflow 영향을 최소화해야 합니다 [1].
  • JavaScript로 애니메이션을 동기화해야 하는 경우 window.requestAnimationFrame을 사용하여 브라우저가 동시 애니메이션을 단일 Reflow 및 Repaint 주기로 통합 최적화할 수 있도록 지원해야 합니다 [13, 15].

  • Reflow (Layout) 개념 및 발생 원인

    • Reflow는 문서 흐름 내에서 요소의 위치, 크기(width, height, margin, padding, border 등)를 계산하는 과정입니다 [1, 4, 6].
    • DOM 요소의 추가 및 제거, 브라우저 창 크기 조절, 폰트 크기 변경, 또는 레이아웃에 영향을 주는 CSS 속성 변경 시 트리거됩니다 [4-6, 10].
    • 웹 문서는 연속적인 흐름으로 구성되어 있어, 단일 요소의 구조적 변화가 부모나 자식 요소 등 DOM 트리 전체에 걸친 재계산을 연쇄적으로 유발할 수 있으므로 연산 비용이 매우 높은 사용자 차단(User-Blocking) 작업입니다 [1, 3, 5, 6].
  • Repaint (Paint) 개념 및 발생 원인

    • Repaint는 레이아웃에 영향을 주지 않고, 요소의 가시성, 배경색, 텍스트 색상, 그림자 등의 시각적 스타일만 변경될 때 발생합니다 [2, 4, 6].
    • 기하학적 재계산이 필요하지 않아 Reflow보다는 상대적으로 비용이 적지만, 애니메이션 처리 중 불필요하게 자주 발생하면 여전히 프레임 드랍이나 성능 저하를 초래할 수 있습니다 [7, 9, 11].
  • Reflow / Repaint 최소화 및 렌더링 최적화 방법

    • DOM 조작 일괄 처리(Batching) 및 레이아웃 스래싱(Layout Thrashing) 방지: DOM 읽기 및 쓰기 작업을 혼합하지 않고 한 번에 처리하여 브라우저가 레이아웃을 여러 번 재계산하는 것을 방지해야 합니다 [2, 8, 9, 12, 13].
    • GPU 가속 활용 (Compositing): top, left와 같은 레이아웃 속성 대신 transform을, 색상 변경 대신 opacity를 사용하여 애니메이션을 구현하면 Reflow나 Repaint 없이 브라우저가 별도 레이어에서 요소를 처리할 수 있습니다 [8, 9, 11].
    • 구조 및 스타일 최적화: DOM 트리의 깊이를 줄이고, 연산이 많이 필요한 복잡한 CSS 선택자(특히 자손 선택자)의 사용을 지양해야 합니다 [14]. 레이아웃 변화 없이 요소를 숨기려면 display: none (Reflow 유발) 대신 visibility: hidden을 사용하는 것이 좋습니다 [15].
    • 문서 흐름(Flow)에서 분리: 애니메이션 등 복잡한 렌더링 변경이 일어나는 요소는 position: absolute 또는 position: fixed를 사용하여 주변 요소의 Reflow에 영향을 주지 않도록 격리해야 합니다 [14].
  • React의 렌더링 메커니즘과 성능 최적화

    • 기존의 직접적인 DOM 조작은 매 변경마다 비용이 높은 Reflow와 Repaint를 유발하기 때문에 느릴 수밖에 없습니다 [16].
    • React는 **Virtual DOM**을 사용하여 메모리 상에서 이전 상태와 새로운 상태를 비교(Diffing)한 뒤, 변경된 최소한의 부분만 실제 DOM에 일괄 반영함으로써 렌더링 파이프라인의 낭비를 방지합니다 [16, 17].
    • 또한 React 18부터 도입된 자동 일괄 처리(Automatic Batching) 기능은 비동기 작업(Promise, setTimeout 등) 내에서 발생하는 여러 상태 업데이트를 단 한 번의 리렌더링으로 묶어서 처리하여 DOM 연산 횟수를 획기적으로 줄여줍니다 [18-20].

  • Reflow와 Repaint의 개념 및 발생 원인

    • Repaint: 요소의 스킨(outline, visibility, background color 등)이 변경되어 가시성에만 변화가 생길 때 발생한다 [2]. 브라우저가 DOM 트리의 다른 노드들의 가시성까지 확인해야 하므로 비용이 든다 [2].
    • Reflow: 요소의 크기(width, height, margin, padding 등)나 위치가 변경되어 페이지의 레이아웃이 바뀔 때 발생한다 [2, 3]. 한 요소의 Reflow는 자식 요소, 조상 요소, 그리고 DOM 트리에서 뒤따르는 요소들의 연쇄적인 Reflow를 유발하여 거의 전체 페이지를 다시 레이아웃하는 것과 같은 엄청난 처리 비용을 요구한다 [2, 4, 8].
    • 주요 원인: 창 크기 조절, 폰트 변경, :hover 등의 가상 클래스 활성화, 스크립트를 통한 DOM 조작, offsetWidth 또는 offsetHeight 계산, 인라인 스타일 변경 등이 모두 Reflow를 트리거한다 [9, 10].
  • CSS 및 애니메이션 최적화 전략

    • 레이아웃 속성 애니메이션 지양: width, height, margin, left, top 등의 속성을 애니메이션화하면 지속적인 Reflow와 Repaint 사이클이 발생하여 성능을 크게 떨어뜨린다 [3, 5, 8, 11]. 대신 레이아웃 재계산을 피하고 GPU 가속(Compositing)을 활용할 수 있는 transformopacity를 사용해야 한다 [8, 12, 13].
    • 고비용 속성 최소화 및 will-change 활용: box-shadow, filter, border-radius와 같이 렌더링 리소스를 많이 소모하는 속성의 사용을 주의해야 한다 [12, 14]. 브라우저에게 변경이 일어날 요소를 미리 알려주는 will-change 속성을 활용하면 성능 최적화에 도움이 되지만, 너무 많은 요소에 남용하면 성능 저하를 유발할 수 있다 [7, 15, 16].
    • 애니메이션 요소의 위치 독립: 애니메이션을 적용할 요소에 position: fixed 또는 absolute를 설정하면 다른 요소의 레이아웃에 영향을 주지 않아 무거운 Reflow 대신 상대적으로 가벼운 Repaint만 발생하게 할 수 있다 [17, 18].
  • DOM 조작 및 스크립트 실행 최적화

    • DOM 조작 최소화 및 일괄 처리: documentFragment를 사용해 DOM 업데이트를 일괄로 처리하거나 노드를 복사하여 변경한 후 원본과 한 번에 교체하는 방식으로 Reflow/Repaint 횟수를 줄일 수 있다 [6, 19]. 또한 여러 개의 인라인 스타일을 반복해서 설정하기보다는 CSS 클래스 한 번의 변경으로 스타일을 적용해야 한다 [17, 19].
    • 레이아웃 스래싱(Layout Thrashing) 방지: DOM 읽기와 쓰기를 좁은 루프 안에서 번갈아 수행하면, 브라우저는 정확한 수치를 반환하기 위해 강제로 동기적인 Reflow를 실행하게 되어 심각한 병목 현상이 발생한다 [7, 10]. 이를 막기 위해 읽기/쓰기 작업을 분리하고, requestAnimationFrame을 사용하여 브라우저의 렌더링 주기에 맞추어 업데이트해야 한다 [7, 10].
  • 구조적 최적화 고려사항

    • DOM 트리 하단에서의 클래스 변경: Reflow의 파급 범위를 최소화하기 위해, 상위 래퍼(wrapper) 요소보다는 DOM 트리에서 최대한 하단에 위치한 요소의 클래스를 변경하는 것이 유리하다 [20].
    • 테이블 레이아웃 지양 및 선택자 단순화: 테이블 레이아웃은 렌더링 시 여러 번의 계산 패스가 필요하고, 작은 변경에도 내부의 모든 노드에 Reflow를 유발하므로 피해야 한다(필요시 table-layout: fixed 사용) [21, 22]. 더불어 불필요하게 깊게 중첩되고 복잡한 CSS 선택자는 렌더링 파싱 속도를 늦추므로 단순하고 직접적인 선택자를 사용해야 한다 [19, 23, 24].

  • 렌더링 파이프라인의 이해: 브라우저는 HTML과 CSS를 파싱하여 각각 DOM과 CSSOM을 구성하고, 이를 결합해 화면에 보일 요소들만 포함하는 렌더 트리(Render Tree)를 생성합니다 [4-7]. 이후 렌더 트리를 기반으로 기하학적 구조를 계산하는 Reflow 단계를 거쳐, 픽셀로 변환하는 Repaint, 그리고 여러 레이어를 합성하는 Compositing 단계로 렌더링을 마칩니다 [1, 7, 8].
  • Reflow (Layout) 상세:
    • 뷰포트의 크기와 박스 모델을 기반으로 모든 가시적 요소의 x, y 좌표 및 너비와 높이를 계산합니다 [1, 2].
    • 브라우저 창의 크기 조절, DOM 요소의 추가 및 제거, 또는 너비(width), 높이(height), 여백(margin, padding)과 같이 레이아웃에 영향을 미치는 CSS 속성 변경 시 발생합니다 [2, 3, 9, 10].
    • HTML 요소들은 연속적인 문서 흐름(Document Flow) 안에 존재하므로, 한 요소의 기하학적 변화가 다른 요소들까지 연쇄적으로 재계산하게 만들어 연산 비용이 매우 높습니다 [1, 9, 11, 12].
  • Repaint (Paint) 상세:
    • 레이아웃(크기나 위치)의 변화 없이, 요소의 시각적 형태만 변경될 때 발생합니다 [2, 3, 10].
    • 배경색, 텍스트 색상, 그림자(box-shadow), 가시성 변경 등이 이에 해당합니다 [2, 3, 10].
    • Reflow보다는 연산 비용이 적게 들지만, 잦은 Repaint 역시 렌더링 파이프라인을 방해해 스크롤이나 애니메이션 시 화면이 버벅거리는 현상(Jank)을 초래할 수 있습니다 [8, 11-13].
  • 성능 최적화 기법 (Optimization Strategies):
    • DOM 조작 최소화: 불필요한 DOM 트리의 깊이를 줄이고 복잡한 하위 CSS 선택자 사용을 피해야 합니다 [13, 14]. DOM 읽기와 쓰기를 번갈아 하여 발생하는 '레이아웃 스래싱(Layout Thrashing)'을 방지하기 위해 조작을 일괄 처리(Batching)하는 것이 좋습니다 [2, 15].
    • GPU 가속 활용: top이나 left 속성 대신 transformopacity를 사용하면, Reflow와 Repaint를 유발하지 않고 GPU를 통해 애니메이션을 처리할 수 있습니다 [8, 12, 13, 16].
    • 스타일 및 위치 최적화: Reflow를 피하면서 요소를 숨길 때는 display: none 대신 visibility: hidden을 사용하고 [16], 복잡한 렌더링 변화나 애니메이션이 있는 요소는 position: absoluteposition: fixed를 사용해 문서의 기본 흐름에서 분리해야 합니다 [14].

  • 리플로우(Reflow)와 리페인트(Repaint)의 정의 및 차이점

    • Reflow (Layout): 요소의 너비, 높이, 마진, 패딩 등 기하학적 형태나 레이아웃이 변경될 때 브라우저가 페이지의 구조를 다시 계산하는 현상입니다 [1, 5]. 특정 요소에서 리플로우가 발생하면 해당 요소의 자식, 상위 조상 요소, 그리고 DOM 트리의 뒤따르는 요소들까지 연쇄적으로 리플로우가 발생하게 되므로 매우 높은 처리 비용이 요구됩니다 [2].
    • Repaint: 요소의 레이아웃은 변하지 않되, 배경색, 아웃라인, 가시성(visibility) 등 시각적 요소(skin)만 변경될 때 발생합니다 [1, 2]. 오페라(Opera) 브라우저에 따르면, 리페인트 역시 브라우저가 DOM 트리의 다른 모든 노드의 가시성을 검증해야 하므로 비용이 많이 드는 작업입니다 [2].
  • 발생 원인(Triggers)

    • 윈도우 창 크기 조절, 폰트 변경, 스타일시트 추가/제거, DOM 조작, 입력 창의 텍스트 변경 등은 리플로우를 유발합니다 [6].
    • CSS :hover 가상 클래스 활성화, 클래스 속성 조작, 여러 개의 인라인 스타일 적용 등도 원인이 됩니다 [6, 7].
    • 특히 자바스크립트에서 offsetWidthoffsetHeight와 같은 레이아웃 속성을 계산하거나 읽고 쓰는 행위를 반복하면, 브라우저가 정확한 치수를 제공하기 위해 레이아웃 큐를 비우고 동기적으로 리플로우를 실행하는 레이아웃 스래싱(Layout Thrashing)이 발생합니다 [6, 8, 9].
  • 최적화 및 최소화 기법

    • GPU 가속 활용: 애니메이션 적용 시 레이아웃 속성(width, height, top, left 등) 대신 transformopacity를 사용하면 리플로우와 리페인트를 모두 방지하고 GPU 컴포지팅(Compositing)만 발생시켜 성능을 크게 높일 수 있습니다 [10-12].
    • DOM 및 클래스 조작 최적화: DOM 조작 시 documentFragment를 사용하여 변경 사항을 일괄 처리(batch)하거나 requestAnimationFrame을 사용하여 애니메이션을 렌더링 주기에 동기화해야 합니다 [8, 9, 13]. 또한 요소의 클래스를 변경할 때는 DOM 트리의 최대한 아래쪽(하위 노드)에서 변경하여 리플로우의 영향을 받는 노드 수를 줄여야 합니다 [14].
    • 인라인 스타일 지양: 자바스크립트를 통해 인라인 스타일을 여러 번 설정하는 것을 피하고, 대신 미리 정의된 CSS 클래스를 변경하는 방식으로 제어해야 합니다 [7, 15].
    • 절대 위치 지정: 애니메이션이 적용되는 요소는 position: fixed 또는 absolute로 설정하여, 다른 요소들의 레이아웃에 영향을 미치지 않고 리페인트만 발생하도록 격리해야 합니다 [7].
    • 테이블 레이아웃 지양: 테이블은 셀 크기 변경 시 전체 노드의 리플로우를 유발하고 렌더링에 여러 번의 패스(pass)가 필요하므로 레이아웃 목적으로 사용해서는 안 됩니다 [16].

  • 개념과 차이점 및 발생 원인

    • Reflow (Layout): 브라우저 창 크기 조절, 폰트 변경, 새로운 DOM 요소 추가/제거, width, height, margin, padding, top 등 기하학적 형태나 레이아웃에 영향을 주는 속성이 변경될 때 발생합니다 [3, 6, 7]. 한 요소의 Reflow는 자식 및 조상 요소, 그리고 DOM에서 그 뒤에 나타나는 모든 요소의 연쇄적인 Reflow를 유발하므로 매우 큰 비용이 듭니다 [2, 4].
    • Repaint: color, background-color, outline, visibility 등 요소의 레이아웃에는 영향을 주지 않으면서 겉모습만 변경될 때 발생합니다 [2, 3, 6].
  • 성능 최적화 및 유지보수를 위한 CSS 설계 기법

    • 레이아웃 스래싱(Layout Thrashing) 방지 및 DOM 조작 최소화: JavaScript를 통해 다수의 인라인 스타일을 설정하면 개별적으로 Reflow가 발생합니다 [5, 8]. 변경 사항을 외부 CSS 클래스에 그룹화하여 한 번의 조작으로 DOM 트리의 클래스 속성을 변경하는 방식이 성능과 유지보수에 훨씬 유리합니다 [8, 9]. DOM을 읽고 쓰는 과정을 철저히 분리하여 레이아웃 스래싱을 방지해야 합니다 [10].
    • 클래스 변경의 범위 제한: Reflow의 파급 범위를 줄이려면 DOM 트리에서 가능한 가장 낮은 위치(하위 노드)에 있는 요소의 클래스를 변경해야 합니다 [5, 11].
    • 올바른 애니메이션(transition/keyframes) 전략: width, height, box-shadow 등의 속성을 애니메이션으로 처리하면 지속적으로 Reflow와 Repaint를 유발해 화면이 끊길 수 있습니다 [6, 12, 13]. 대신 레이아웃을 다시 계산하지 않는 transformopacity, filter 속성만 사용하여 애니메이션을 작성해야 GPU 가속(Compositing)을 통한 부드러운 렌더링이 가능해집니다 [3, 13, 14].
    • 요소의 위치 및 속성 분리: 애니메이션이 들어간 요소에 position: fixed 또는 absolute를 적용하면 해당 요소가 문서의 흐름에서 분리되어 주변 요소의 레이아웃에 영향을 주지 않으므로, 비용이 큰 전체 Reflow 대신 Repaint만 발생시킬 수 있습니다 [5, 8, 15].
    • 선택자 및 레이아웃 구조 단순화: 다중 경로를 요구하는 복잡한 CSS 선택자를 피하고 [9], 전체 노드의 Reflow를 자주 유발하는 테이블(table) 기반의 레이아웃을 피해야 합니다 [5, 16].

리플로우(Reflow)와 리페인트(Repaint)의 개념 및 원인

  • 리페인트(Repaint): 아웃라인, 가시성, 배경색 등 요소의 시각적 형태만 변경될 때 발생합니다 [1]. 브라우저는 이 과정에서 DOM 트리의 다른 노드들의 가시성까지 확인해야 하므로 비용이 발생합니다 [1].
  • 리플로우(Reflow): 페이지의 전체 또는 일부 레이아웃에 영향을 주는 변경이 있을 때 발생하며, 리페인트보다 훨씬 연산 비용이 큽니다 [1, 2]. 특정 요소가 리플로우되면 자식 노드, 조상 노드는 물론 DOM 트리에서 그 뒤에 오는 요소들까지 연쇄적으로 리플로우를 유발합니다 [1].
  • 주요 발생 원인: 창 크기 조절, 폰트 변경, DOM 스크립트 조작, offsetWidthoffsetHeight 등의 계산, 인라인 스타일 설정 등이 리플로우를 유발합니다 [3]. 애니메이션을 적용할 때 width, height, margin, padding, left/top과 같이 레이아웃을 계산해야 하는 속성을 변경하는 것도 성능을 저하시키는 주된 원인입니다 [4-6].

유지보수 가능하고 성능을 높이는 CSS 구조 설계 전략

  • DOM 트리 하위에서 클래스 변경하기: 리플로우의 연쇄적 파급 효과를 줄이기 위해, 큰 래퍼(wrapper) 요소보다는 DOM 트리의 가능한 한 가장 깊은 하단에 있는 요소의 클래스를 변경해야 합니다 [7]. OOCSS, BEM과 같은 객체 지향적 접근은 이러한 클래스 변경 범위를 최소화하여 리플로우의 영향을 줄이는 데 도움을 줍니다 [7].
  • 다중 인라인 스타일 지양: 자바스크립트로 인라인 스타일을 여러 번 설정하면 매번 리플로우가 발생할 수 있습니다 [8]. 대신 모든 변경 사항을 묶은 외부 CSS 클래스를 사용하여 단 한 번의 리플로우만 발생하도록 해야 합니다 [8, 9].
  • 테이블 레이아웃 사용 금지: 테이블은 내부 요소의 크기 변화가 구조 전체의 리플로우를 유발하기 쉬우며, 브라우저가 레이아웃을 계산하기 위해 여러 번 렌더링을 시도해야 할 수 있으므로 레이아웃용으로는 피해야 합니다 [10]. 부득이하게 사용할 경우 table-layout: fixed 속성을 권장합니다 [11].
  • CSS 컨테인먼트(Containment) 활용: contain 속성 등을 활용하여 브라우저에 페이지의 특정 영역을 격리하도록 지시하면, 다른 부분과 독립적으로 레이아웃과 페인트를 처리할 수 있어 스타일 재계산 성능을 최적화할 수 있습니다 [12, 13].

애니메이션 성능 최적화 방법

  • GPU 가속 활용: widthheight 대신 transformscale, opacity, filter와 같은 속성을 애니메이션에 활용해야 합니다 [6, 14, 15]. 이러한 속성들은 레이아웃 변경(리플로우)을 일으키지 않고 렌더링 계층에서만 처리되므로 GPU 가속을 유도하여 렌더링 성능을 획기적으로 높일 수 있습니다 [15].
  • position: fixed 또는 absolute 활용: 애니메이션이 적용되는 요소에 절대 위치(absolute 또는 fixed)를 부여하면 해당 요소가 다른 요소의 레이아웃에 영향을 미치지 않기 때문에, 무거운 리플로우 대신 비교적 가벼운 리페인트만 발생합니다 [8, 16].
  • will-change 속성과 레이아웃 스래싱(Layout Thrashing) 방지: 브라우저가 애니메이션을 최적화할 수 있도록 will-change 속성을 통해 변경 사항을 미리 힌트로 제공할 수 있습니다 [17, 18]. 또한 DOM 읽기와 쓰기를 분리하고, requestAnimationFrame을 사용하여 애니메이션과 DOM 업데이트를 브라우저 렌더링 주기에 맞춰 일괄 처리(batch)해야 합니다 [19, 20].

리플로우와 리페인트의 개념 및 비용

  • 리플로우(Reflow): 요소의 레이아웃, 크기, 위치 등에 영향을 주는 변경 사항이 있을 때 발생합니다. 한 요소에서 리플로우가 발생하면 해당 요소의 자식, 부모 노드는 물론 DOM 트리에서 그 뒤에 오는 모든 요소까지 재계산되어야 하므로 성능 측면에서 매우 비쌉니다 [3, 5]. 심한 경우 페이지 전체를 다시 레이아웃하는 것과 같습니다 [5].
  • 리페인트(Repaint): 윤곽선(outline), 가시성(visibility), 배경색 등 레이아웃에는 영향을 주지 않지만 시각적인 스킨이 변경될 때 일어납니다 [3]. 브라우저는 시각적 변화를 반영하기 위해 다른 모든 노드의 가시성을 확인해야 하므로 이 또한 비용이 듭니다 [3]. 브라우저는 렌더 트리 생성 후 레이아웃을 계산하고 그 후에 페인트를 수행합니다 [6].

발생 원인

  • 창 크기 조절, 폰트 변경, 스타일시트 추가/제거, 사용자의 입력(텍스트 타이핑 등), DOM 조작, :hover와 같은 가상 클래스 활성화, offsetWidthoffsetHeight 속성 계산, 인라인 스타일 설정 등이 리플로우를 유발합니다 [7, 8].
  • 애니메이션 적용 시 width, height, margin, padding, top, left, box-shadow 등의 속성을 변경하면 레이아웃 스래싱(Layout Thrashing)과 리페인트 주기를 촉발하여 성능이 급격히 저하됩니다 [4, 9, 10].

최적화 및 감소 기법

  • DOM 및 스타일 조작 최소화: 여러 개의 인라인 스타일을 각각 적용하는 것을 피하고, 변경 사항을 외부 클래스로 결합하여 한 번의 클래스 속성 조작으로 리플로우가 한 번만 발생하게 해야 합니다 [8, 11]. DOM 트리의 가능한 가장 낮은 계층(하위)에서 클래스를 변경하여 리플로우의 영향을 받는 노드 수를 줄이는 것이 좋습니다 [12]. DOM 변경 시에는 documentFragment를 사용하여 일괄 업데이트해야 합니다 [11, 13].
  • 애니메이션 최적화: 레이아웃을 건드리는 속성 대신 transform, opacity, filter 속성을 사용하여 애니메이션을 처리하면 리플로우를 방지하고 렌더링 성능을 높일 수 있습니다 [2, 10, 14]. 또한 position: fixed 또는 absolute인 요소에 애니메이션을 적용하면 전체 문서의 리플로우 대신 부분적인 리페인트만 유발할 수 있습니다 [15].
  • 브라우저 힌팅(Hinting) 및 동기화: 잦은 변경이 예상되는 요소에 will-change 속성을 부여하여 브라우저가 렌더링을 미리 최적화하도록 유도할 수 있습니다 [16-18]. 아울러 애니메이션은 브라우저의 리페인트 주기와 동기화되는 requestAnimationFrame을 사용하여 일괄 처리해야 합니다 [13, 18].
  • 레이아웃 스래싱 방지 및 기타 주의사항: DOM을 읽고 쓰는 작업을 명확히 분리하여(배칭) 브라우저가 강제로 동기식 리플로우를 발생시키는 레이아웃 스래싱을 방지해야 합니다 [13, 18]. 또한 렌더링을 지연시키고 작은 변경에도 모든 노드의 리플로우를 발생시키는 테이블(Table) 레이아웃 사용을 피하고 [19], 너무 복잡하고 깊게 중첩된 CSS 선택자를 사용하지 말아야 합니다 [11].

Reflow와 Repaint의 개념 및 발생 원인

  • Reflow (Layout): 브라우저가 렌더링 과정에서 페이지의 레이아웃을 다시 계산하는 단계입니다. width, height, margin, padding, top, left와 같이 요소의 기하학적 구조를 변경하는 속성이 애니메이션되거나 조작될 때 발생합니다 [1, 2]. 한 요소에서 리플로우가 발생하면 자식 요소, 부모 요소 및 DOM 트리 구조에서 뒤따르는 다른 요소들까지 연쇄적인 리플로우가 유발되므로 성능에 매우 치명적입니다 [3]. 리플로우는 창 크기 조절, 폰트 변경, DOM 노드 조작, 그리고 JavaScript에서 offsetWidthoffsetHeight를 계산하여 레이아웃 정보를 읽어올 때도 유발됩니다 [4].
  • Repaint (Paint): 레이아웃이나 요소의 기하학적 구조에는 영향을 주지 않으면서 color, background-color, visibility, box-shadow, outline 같은 시각적 속성만 변경될 때 발생합니다 [2, 3, 5]. 리플로우보다는 상대적으로 가볍지만, 브라우저가 다른 노드들의 가시성 등을 확인하고 다시 그려야 하므로 여전히 높은 연산 비용이 듭니다 [3, 6].

성능 최적화(Reflow & Repaint 감소) 핵심 기법

  • Compositing(합성) 속성 활용: 애니메이션을 구현할 때는 리플로우와 리페인트를 유발하는 속성 대신 transformopacity를 사용하는 것이 가장 이상적입니다 [6, 7]. 이 속성들은 브라우저의 GPU 가속을 통해 처리(Composite 단계만 수행)되므로 레이아웃 재계산이나 페인팅 과정 없이 부드러운 60fps 애니메이션을 제공합니다 [2, 8].
  • DOM 조작 및 스타일 변경의 일괄 처리(Batching): JavaScript를 통해 개별적으로 여러 개의 인라인 스타일을 설정하면 잦은 리플로우가 발생합니다 [9]. 이를 방지하려면 documentFragment를 활용해 DOM 조작을 일괄 처리하거나, JavaScript로 개별 속성을 변경하는 대신 CSS 클래스를 한 번에 교체하는 방식을 사용해야 합니다 [10, 11].
  • Layout Thrashing(레이아웃 스래싱) 방지: JavaScript 루프 내부에서 DOM의 레이아웃 값(예: offsetWidth)을 읽고 즉시 쓰는 작업을 반복하면, 브라우저가 정확한 값을 반환하기 위해 강제로 동기적인 리플로우를 수행하여 프레임률이 급감합니다 [12, 13]. DOM 읽기와 쓰기 작업을 분리하고, requestAnimationFrame을 사용하여 브라우저의 리페인트 주기에 맞춰 애니메이션을 동기화해야 합니다 [12, 13].
  • DOM 트리 하단부에서의 클래스 변경: 리플로우의 연쇄 작용 스코프를 제한하기 위해, 최상위 래퍼(Wrapper)나 부모 요소 대신 화면 변경에 직접적인 영향을 받는 가장 하위의 DOM 노드에서 클래스를 변경하는 것이 좋습니다 [14].
  • 레이아웃 흐름에서 분리 (position: absolute/fixed): 애니메이션이 적용되는 요소에 position: absolute 또는 fixed를 부여하면 해당 요소가 문서의 정상적인 흐름(Flow)에서 빠지게 됩니다 [9, 15]. 결과적으로 애니메이션 중 주변 요소들의 레이아웃에 영향을 주지 않아 전체 리플로우 대신 해당 요소의 리페인트만 유발하게 됩니다 [15].
  • will-change 속성의 활용: 특정 요소가 곧 애니메이션될 것임을 브라우저에 미리 알려주어 렌더링 최적화를 준비하게 할 수 있습니다 [16, 17]. 이 속성을 사용하면 브라우저가 요소를 최적화할 수 있지만, 성능 문제 발생을 방지하는 최후의 수단으로 써야 하며 과도한 사용은 오히려 성능을 저하시킬 수 있습니다 [16, 18].
  • 테이블 레이아웃 및 복잡한 선택자 회피: 테이블(<table>)은 내용물이나 셀 하나의 크기가 변해도 전체 테이블 노드의 레이아웃을 다시 계산하기 위해 여러 번의 리플로우 패스를 거칠 수 있어 레이아웃 용도로 부적합합니다 [19]. 또한 불필요하게 복잡하거나 깊게 중첩된 CSS 선택자는 브라우저의 파싱 속도를 늦추므로 최대한 직관적이고 단순하게 작성해야 합니다 [11, 20].

⚖️ Trade-offs & Caveats

No trade-offs available.

🔗 Knowledge Connections

  • Related Topics: Critical Rendering Path, DOM & CSSOM, Render Tree, GPU Compositing
  • Projects/Contexts: Frontend Performance Optimization, React Virtual DOM and Reconciliation
  • Contradictions/Notes: 소스에 따르면 리페인트(Repaint)는 레이아웃 재계산이 없기 때문에 리플로우(Reflow)보다 상대적으로 시스템 비용이 덜 드는 작업으로 설명된다 [2, 20]. 그러나 두 작업 모두 과도하게 트리거될 경우 메인 스레드를 점유하고 배터리 소모 및 버벅임(Jank)을 유발하므로, 성능 최적화 시에는 둘 중 어느 하나를 무시하지 않고 두 과정 모두를 최소화하는 것이 브라우저 렌더링 최적화의 핵심이다 [19, 20].

Last updated: 2026-04-25



Last updated: 2026-04-25



Last updated: 2026-04-25


  • Related Topics: CSS 성능 최적화, CSS 애니메이션(transition / keyframes), DOM 조작과 렌더링 파이프라인, GPU 가속(Compositing)
  • Projects/Contexts: 확장 가능한 CSS 아키텍처 설계, 실무에서의 CSS 상태 관리 및 프론트엔드 성능 개선
  • Contradictions/Notes: 브라우저 제조사들이 성능 저하의 주범으로 지목하는 Reflow와 Repaint 자체를 브라우저 환경에서 완전히 없앨 수는 없습니다. 하지만 개발자는 불필요한 레이아웃 속성 변경이나 레이아웃 스래싱을 피하도록 설계함으로써 그 영향을 획기적으로 최소화할 수 있습니다 [20, 25, 26]. will-change 속성 또한 브라우저 최적화를 돕는 훌륭한 도구이지만, 과도하게 사용할 경우 오히려 디바이스 리소스를 고갈시켜 프레임 드랍을 유발할 수 있으므로 최후의 수단으로 신중히 사용해야 합니다 [15, 16, 27].

Last updated: 2026-04-26


  • Related Topics: [[Critical Rendering Path|Critical Rendering Path]], DOM 및 CSSOM, Render Tree, Compositing (GPU 가속), [[Virtual DOM|Virtual DOM]]
  • Projects/Contexts: 프론트엔드 성능 최적화 ([[Web Performance Optimization|Web Performance Optimization]]), React 컴포넌트 렌더링 아키텍처
  • Contradictions/Notes: 소스 간의 상충되는 의견은 없으며, 모든 자료가 일관되게 Reflow와 Repaint의 발생 횟수를 최소화하는 것이 브라우저의 렌더링 성능 및 60 FPS 유지에 필수적이라고 강조합니다 [8, 12, 17, 18].

Last updated: 2026-04-25


  • Related Topics: CSS 성능 최적화(CSS Performance Optimization), 애니메이션 최적화(Animation Optimization), 렌더링 파이프라인(Rendering Pipeline), 레이아웃 스래싱(Layout Thrashing)
  • Projects/Contexts: 실무에서의 CSS 상태 관리 및 애니메이션 설계, 대규모 프론트엔드 프로젝트의 UI 성능 개선
  • Contradictions/Notes: will-change 속성은 브라우저에 요소의 변경을 미리 알림으로써 렌더링을 최적화할 수 있는 힌트를 주지만, 너무 많은 요소에 불필요하게 남용할 경우 오히려 자원을 소모하여 애니메이션 성능을 저하시킬 수 있으므로 기존 성능 문제가 있을 때 최후의 수단(last resort)으로만 사용해야 합니다 [9, 17, 18]. 또한 브라우저가 성능 향상을 위해 여러 리플로우를 묶어서 처리(dirty reflows)하는 과정에서 간혹 렌더링 버그(예: 그림자가 잔류하는 현상 등)가 발생할 수 있으며, 이 경우 강제로 리플로우를 유발하여 버그를 수정해야 하는 예외 상황도 존재합니다 [19, 20].

Last updated: 2026-04-26


  • Related Topics: CSS 애니메이션 성능 최적화 (transition / keyframes), CSS 구조 설계 방식, DOM 렌더링 파이프라인
  • Projects/Contexts: 실무에서 CSS 관리하는 방법, 유지보수 가능하게 CSS 아키텍처 구축
  • Contradictions/Notes: 빈번하게 변경되는 요소에 대해 브라우저가 미리 최적화를 준비할 수 있게 하는 will-change 속성은 성능 향상에 큰 도움이 됩니다 [10, 17, 18]. 하지만 이 속성을 불필요하게 너무 많은 요소에 남용할 경우 도리어 브라우저의 리소스를 과도하게 소모시켜 성능 저하(Performance issues)를 일으킬 수 있으므로 최후의 수단으로만 신중히 사용해야 합니다 [17, 18].

Last updated: 2026-04-26


  • Related Topics: 실무에서 CSS 관리하는 방법, 애니메이션 (transition / keyframes), CSS 구조 설계 방식 BEM
  • Projects/Contexts: 실무에서 대규모 프론트엔드 프로젝트의 CSS를 설계하거나 인터랙티브 UI 애니메이션을 구현할 때, 화려함("예쁘게")에 치중하여 성능을 저하시키는 코드를 피하고, 성능 최적화 및 유지보수성이 확보된 코드를 작성하기 위한 지침으로 사용됩니다.
  • Contradictions/Notes: 성능을 높이기 위해 사용하는 will-change 속성의 경우, 브라우저의 최적화를 돕는 좋은 힌트가 되지만 필요 이상으로 많은 요소에 남용하면 오히려 시스템 리소스를 과도하게 소모하여 성능 문제를 유발할 수 있으므로 최후의 수단으로 신중히 사용해야 합니다 [17, 18]. 또한, 극한의 상황에서는 애니메이션의 시각적 부드러움을 다소 희생하더라도 한 번에 이동하는 픽셀 폭을 넓혀 CPU의 부하(리플로우 과부하)를 줄이는 것이 모바일 기기 등에서 유리할 수 있습니다 [16].

Last updated: 2026-04-26



Last updated: 2026-04-26


  • Related Topics: CSS 애니메이션(transition / keyframes), CSS 아키텍처 및 렌더링 파이프라인
  • Projects/Contexts: 실무에서 CSS 관리하는 방법, 반응형 디자인 및 고성능 UI 구현
  • Contradictions/Notes: 소스 문헌들은 will-change 속성이 리플로우 및 페인트를 대비한 최적화에 도움을 준다고 소개하면서도, 이를 너무 많은 요소에 남용하거나 미리 예측하여 사용하면 도리어 브라우저 리소스와 메모리를 소모시켜 성능 병목(bottleneck)을 유발할 수 있다고 일관되게 경고합니다 [16-18].

Last updated: 2026-04-26