Published On

Reflow와 Repaint의 차이점


Reflow와 Repaint란?

ReflowRepaint는 브라우저가 웹 페이지를 렌더링할 때 발생하는 두 가지 주요 작업입니다.

이 작업들은 DOM(문서 객체 모델)의 변화에 따라 브라우저가 페이지를 다시 계산하고 화면에 표시하는 과정을 의미합니다.

Reflow란?

Reflow는 DOM 요소의 레이아웃을 변경할 때 발생하는 과정으로, 브라우저가 요소들의 크기, 위치, 배치를 다시 계산하는 작업입니다. DOM 트리에 변화가 생기면 브라우저는 그에 맞춰 페이지의 레이아웃을 다시 계산해야 합니다.

  • Reflow는 매우 비용이 큰 작업입니다. DOM의 상위 노드에서 Reflow가 발생하면 해당 노드의 자식 노드들도 Reflow가 발생하며, 모든 관련 요소가 다시 계산됩니다.
  • 페이지 구조가 복잡할수록 Reflow는 더 많은 리소스를 요구하므로, 이를 최소화하는 것이 성능 최적화에 매우 중요합니다.

Repaint란?

Repaint는 요소의 시각적 스타일(색상, 배경색, 그림자 등)이 변경될 때 발생하는 과정으로, 요소의 배치는 그대로 유지되지만 화면에 그려지는 방식이 변경됩니다. Repaint는 레이아웃을 다시 계산하지 않으므로 Reflow에 비해 비용이 적게 듭니다.

  • Repaint는 부모 노드와 자식 노드 간의 관계를 가지지 않으므로, 특정 요소에서 발생한 Repaint는 다른 요소에 영향을 주지 않습니다.

Reflow와 Repaint의 차이점

특징ReflowRepaint
작업요소의 레이아웃(크기, 위치 등)을 다시 계산요소의 시각적 스타일(색상, 테두리 등)만 다시 그리기
영향 범위상위 노드에서 발생 시 하위 노드까지 영향을 미치며, 큰 범위에서 발생특정 요소에만 발생하며, 다른 요소에 영향 없음
성능 비용매우 높은 비용 (CPU 사용량이 큼)상대적으로 낮은 비용
발생 시점DOM 구조 변경, 요소의 위치나 크기 변화 시색상, 배경색, 텍스트 스타일 등 시각적 변화 시

이러한 이유 때문에, Reflow를 최소화 해야됩니다.

속성

속성Reflow 유발Repaint 유발
width, height(요소 크기 변화로 인해 레이아웃 재계산)
padding, margin(요소 간 간격 변경으로 레이아웃 영향)
position (top, left 등)(요소 위치 변화로 인해 레이아웃 재배치)
color, background-color(요소의 시각적 스타일만 변경됨)
box-shadow, text-shadow(시각적 효과만 변경됨)
opacity, transform(투명도만 변경됨), (요소의 위치나 크기가 시각적으로만 변경됨)

Reflow를 최소화해야 하는 이유

Reflow는 레이아웃을 다시 계산하는 복잡한 과정이기 때문에, 성능에 매우 큰 영향을 미칩니다. 특히 페이지의 DOM 구조가 복잡하거나 대규모의 요소들이 존재할 경우, Reflow가 자주 발생하면 CPU 부하가 커지고, 페이지의 반응 속도가 저하될 수 있습니다. 따라서 Reflow를 최소화하는 것이 성능 최적화의 중요한 요소입니다.

Reflow를 최소화하기 위한 방법

React 코드를 기준으로 예시 코드를 통해 설명하겠습니다.

  1. DOM 조작 최소화:

React에서는 DOM을 직접 조작하지 않지만, 상태(state) 변경이 빈번하게 발생하면 렌더링이 자주 일어나 Reflow가 발생할 수 있습니다.

이를 해결하려면 상태 변경을 한 번에 묶어서 처리하는 것이 좋습니다.

// 잘못된 예시: 상태를 개별적으로 업데이트해 Reflow가 자주 발생
const Component = () => {
  const [width, setWidth] = useState(100);
  const [height, setHeight] = useState(200);

  const handleResize = () => {
    setWidth(150);
    setHeight(300); // 상태를 개별적으로 업데이트해 렌더링이 자주 발생
  };

  return <div style={{ width: `${width}px`, height: `${height}px` }} />;
};

// 올바른 예시: 상태를 한 번에 업데이트해 Reflow 최소화
const Component = () => {
  const [size, setSize] = useState({ width: 100, height: 200 });

  const handleResize = () => {
    setSize({ width: 150, height: 300 }); // 상태를 한 번에 업데이트해 렌더링 최소화
  };

  return (
    <div style={{ width: `${size.width}px`, height: `${size.height}px` }} />
  );
};
  1. CSS 스타일 변경 최소화:

React에서 인라인 스타일을 자주 변경할 경우 Reflow가 발생할 수 있습니다. 가능한 한 CSS 클래스를 활용하거나, 스타일 변경을 한 번에 처리하여 Reflow를 줄일 수 있습니다.

// 잘못된 예시: 스타일을 개별적으로 변경
const Component = () => {
  const [style, setStyle] = useState({});

  const handleStyleChange = () => {
    setStyle((prev) => ({ ...prev, width: "150px" }));
    setStyle((prev) => ({ ...prev, padding: "20px" })); // Reflow가 자주 발생
  };

  return <div style={style}></div>;
};

// 올바른 예시: 스타일을 한 번에 변경해 Reflow 최소화
const Component = () => {
  const [style, setStyle] = useState({});

  const handleStyleChange = () => {
    setStyle({ width: "150px", padding: "20px" }); // Reflow를 최소화하기 위해 스타일을 한 번에 적용
  };

  return <div style={style}></div>;
};
  1. 애니메이션 최적화:

레이아웃에 영향을 미치지 않는 속성(예: opacity, transform)을 사용하여 애니메이션을 구현하면 Reflow를 방지할 수 있습니다.

// 올바른 예시: transform 속성으로 애니메이션 구현 (Repaint만 유발)
const Component = () => {
  const [translate, setTranslate] = useState({ x: 0, y: 0 });

  const handleMove = () => {
    setTranslate({ x: 100, y: 50 }); // 레이아웃에 영향 없이 transform으로 처리
  };

  return (
    <div
      style={{ transform: `translate(${translate.x}px, ${translate.y}px)` }}
    />
  );
};
  1. 클래스 추가/제거 최적화:

React에서 클래스를 동적으로 추가하거나 제거할 때도 Reflow가 발생할 수 있습니다. 클래스를 한 번에 변경하거나, 렌더링을 최소화하는 방식으로 Reflow를 줄일 수 있습니다.

// 잘못된 예시: 클래스를 개별적으로 변경
const Component = () => {
  const [isActive, setIsActive] = useState(false);

  const handleToggle = () => {
    setIsActive(!isActive); // 클래스가 개별적으로 적용됨
  };

  return <div className={isActive ? "active" : "inactive"} />;
};

// 올바른 예시: 여러 클래스를 한 번에 적용
const Component = () => {
  const [className, setClassName] = useState("inactive");

  const handleToggle = () => {
    setClassName(className === "inactive" ? "active" : "inactive"); // 클래스 변경을 한 번에 적용
  };

  return <div className={className} />;
};

결론

Reflow와 Repaint는 브라우저 렌더링 과정에서 필수적으로 발생하는 작업이지만, 그 처리 비용은 매우 다릅니다.

Reflow는 레이아웃 전체를 다시 계산해야 하기 때문에 성능에 큰 영향을 미치므로, 이를 최소화하는 것이 중요합니다.