layoutpaintperformance

reflow와 repaint의 차이를 설명해 주세요

예상 시간
6
30초 답변

꼬리질문

조금 더 깊게 물어본다면

답변 뒤에 이어질 수 있는 질문들을 하나씩 열어볼 수 있어요.

reflow가 repaint보다 비싼 이유는?

부가 설명

reflow와 repaint의 차이는 브라우저가 어느 단계부터 다시 일해야 하는지의 차이입니다.

브라우저는 화면을 그릴 때 style, layout, paint, composite 단계를 거칩니다. 여기서 layout은 요소의 위치와 크기를 계산하는 단계이고, paint는 계산된 위치 위에 색상과 배경 같은 픽셀을 그리는 단계입니다.

reflow와 repaint의 기준

reflow는 layout 단계부터 다시 계산하는 작업입니다. 요소의 크기나 위치가 바뀌면 주변 요소의 배치도 달라질 수 있으므로 layout을 다시 계산합니다.

repaint는 layout은 그대로 두고 paint 단계만 다시 실행하는 작업입니다. 요소가 차지하는 공간은 그대로인데 색상, 배경, 그림자처럼 보이는 픽셀만 바뀔 때 발생합니다.

box.style.width = "200px"; // reflow 가능: 크기와 배치가 바뀜
box.style.color = "red"; // repaint 가능: 공간은 그대로, 색만 바뀜
box.style.transform = "translateX(10px)"; // composite에서 처리될 수 있음

즉 핵심은 “화면이 바뀌었는가?”가 아니라 “배치까지 다시 계산해야 하는가?”입니다.

layout이 다시 계산되는 이유

layout은 요소 하나의 width, height만 계산하지 않습니다. 요소가 화면에서 어디에 놓이는지, 부모 안에서 얼마만큼의 공간을 차지하는지, 주변 형제 요소가 어디로 밀리는지까지 계산합니다.

이 계산에는 CSS box model도 포함됩니다. 브라우저는 content 크기만 보지 않고 padding, border, margin까지 포함해 요소가 차지하는 공간을 계산합니다.

  • content: 실제 내용 영역
  • padding: content와 border 사이의 안쪽 여백
  • border: 테두리
  • margin: 다른 요소와의 바깥 여백

Chrome 또는 Firefox 개발자 도구의 Computed 탭에서 이 구조를 확인할 수 있습니다.

이 화면에서 content, padding, border, margin이 layout에서 차지하는 공간을 확인할 수 있습니다. 이미지 아래에 보이는 box-sizing, display, float, line-height, position, z-index는 선택한 요소의 계산된 CSS 속성입니다.

reflow가 더 비싼 이유

repaint는 이미 계산된 위치 위에 픽셀을 다시 칠합니다. 반면 reflow는 위치와 크기를 다시 맞춥니다.

예를 들어 위쪽 요소의 높이가 커지면 아래 요소의 y 위치가 밀립니다. 부모 요소의 크기가 바뀌면 자식 요소의 배치도 다시 계산됩니다. 그래서 reflow는 한 요소에서 시작해 주변 요소로 영향이 퍼질 수 있습니다.

layout thrashing

layout 계산은 비싸기 때문에 브라우저가 잠시 미뤄둘 수 있습니다. 그런데 최신 위치나 크기가 필요한 값을 읽으면 브라우저는 미뤄둔 layout을 즉시 계산해야 합니다.

box.style.width = "200px";
const rect = box.getBoundingClientRect();

style.width를 바꾼 뒤 getBoundingClientRect()를 읽으면 브라우저는 최신 좌표와 크기를 알려줘야 합니다.

문제는 이 패턴이 반복될 때입니다.

for (const box of boxes) {
  box.style.width = "200px"; // write
  const height = box.offsetHeight; // read: 최신 layout 필요
  box.style.height = `${height + 10}px`; // write
}

이 코드는 요소마다 “쓰기 → 읽기 → 쓰기”를 반복합니다. 브라우저는 매 반복마다 layout을 다시 맞춰야 하므로 계산이 여러 번 쪼개져 발생합니다. 이런 상황을 layout thrashing이라고 부릅니다.

보통은 읽기와 쓰기를 나누면 줄일 수 있습니다.

const heights = boxes.map((box) => box.offsetHeight); // read를 먼저 모음
 
boxes.forEach((box, index) => {
  box.style.height = `${heights[index] + 10}px`; // write를 나중에 모음
});

정리하면 reflow와 repaint는 변경된 CSS 속성이 브라우저 렌더링 파이프라인의 어느 단계까지 되돌아가게 만드는지의 차이입니다. 배치를 바꾸면 reflow, 배치는 그대로 두고 픽셀만 바꾸면 repaint입니다.

한 줄 정리

reflow는 요소의 위치와 크기를 다시 계산하는 작업이고, repaint는 계산된 위치 위에 픽셀을 다시 칠하는 작업입니다.