카테고리 없음

렌더링에서 reflow, repaint

Neda 2023. 10. 9. 20:20

렌더링에서 reflow, repaint

브라우저는 렌더링 단계에서 웹 페이지의 구조를 잡기 위해 reflow를 발생시키고, 시각적 업데이트 하기 위해 repaint를 발생시킨다.

 

리플로우

reflow는 렌더링 트리에서 노드의 크기와 위치를 다시 계산하여 레이아웃을 잡는 작업이다. 

부모요소에 리플로우가 발생하면 DOM 노드의 구조에 따라서 관련있는 자식 요소에 리플로우가 발생할 수 있다.

리페인트보다 처리 비용이 높다.

 

리페인트

repaint는 화면에 변경사항이 발생하여 시각적으로 업데이트되어야 할 때 발생한다.

리플로우 후에 발생한다.

 

리플로우와 리페인트를 발생시키는 요인들

  • DOM 노드의 변경: 노드 추가, 추가 업데이트, 노드 삭제 등
  • DOM 노드의 노출 변경: display:none 속성을 통한 노출 변경.
    • (visibility: hidden은 레이아웃을 변경하지 않으므로 리페인트만 발생)
  • 애니메이션: 짧은 시간동안 여러 번 변경이 발생하는 자바스크립트 애니메이션
  • 스타일: 스타일의 규칙의 추가, 변경
  • 사용자의 행동: 사용자의 행동으로 인한 레이아웃(ex. 화면 사이즈 조절), 스타일 변경(ex. 스타일 변경, 테마 변경

 

리플로우, 리페인트를 줄이기 위한 노력들

같은 형태의 작업끼리 묶어 한 번에 처리하기

  • 같은 역할을 하는 것들끼리 코드의 순서를 배치
  • 타이머를 사용하여 코드 실행 시점이 서로 달라지면 이것도 여러 번 리플로,리페인트
const box1width =  document.getElementById('box1').style.clientWidth;
document.getElementById('box2').style.width = box1width + 'px';
const box1height =  document.getElementById('box1').style.clientHeight;
document.getElementById('box2').style.height = box1height + 'px';
const { clientWidth: box1width, clientHeight:box1height } =  document.getElementById('box1');
document.getElementById('box2').style.width = box1width+'px';
document.getElementById('box2').style.height = box1height+'px';

 

display 속성으로 숨기기

  • dispaly 속성을 사용하여 화면에서 없애거나 다시 나타나게 할 때 리플로우, 리페인트 발생
  • display: none일 때는 화면에 보이지 않으므로 이때 스타일을 변경해도 리페인트 발생하지 않음. 
    • 여러 스타일 변경이 필요할 때 숨긴 후에 처리하고 다시 표시하도록 하여 최적화 가능
element.style.dispaly = 'none';

// 스타일 변경해도 리페인트 되지 않음

element.style.dispaly = 'block';

 

node 복제 후 스타일 변경 후 교체하기

const element = document.getElementById('box');
const clone = element.cloneNode(true);

// clone한 노드는 DOM 트리에 아직 추가하지 않았으므로
// 스타일 변경을 해도 리페인트가 발생하지 않음

const parentNode = element.parentNode;
parentNode.replaceChild(clone, element);

 

변수 캐싱

  • 특정 변수 또는 메서드는 호출만으로 리플로를 발생
  • 자주 사용하는 변수를 따로 저장하여 사용
const width = element.scrollWidth;
const height = element.scrollHeight;


// width,height를 사용하는 로직

 

클래스 사용

  • 자주 사용하는 특정 스타일 규칙이 있다면, 직접 스타일을 변경하지 말고 클래스로 규칙을 만들고 클래스를 적용,해체 하는 방식으로 사용
element.addEventListener("click", (e) => {
  e.target.classList.toggle("active");
});