Reflow 최적화

강성훈·2022년 8월 19일
0

기술면접

목록 보기
2/9

자료: https://lists.w3.org/Archives/Public/public-html-ig-ko/2011Sep/att-0031/Reflow_____________________________Tip.pdf

reflow란

문서 내 노드들의 레이아웃, 포지션을 재계산 후 다시 뿌려주는 행위로 Repaint보다도 더 심각한 퍼포먼스 저하를 유발시키는 프로세스이다. 특정
엘리먼트에 대한 Reflow 발생 시, 페이지에서의 해당 요소는 즉시 Reflow State가 되며 해당 엘리먼트의 자식요소와 부모/조상 요소역시
레이아웃 계산을 진행한다. 쉽게 말해 페이지를 전체 다시 렌더링 하는것고 다른 바 없다.

신경써야 하는 이유

Reflow는 퍼포먼스 측면에서 매우 고비용을 발생시키는 프로세스로, 휴대전화와 같은 저성능 디바이스에서는 특히나 더욱 느린 DOM 스크립팅을 발생시키는 주범이다.

reflow 원인

특정 엘리먼트에 스타일변화가 생길 경우 레이아웃 재정리를 위해 Reflow가 실행된다. 자식요소에 아무 변화가 없더라도 기계는 이를 미리 알고있지 못한다. 그렇기 때문에 작은 변화에도 자식개체 뿐 아니라, 페이지 전체에 Reflow가 실행된다.

  • 윈도우 리사이징
  • 폰트의 변화
  • 스타일 추가 또는 제거
  • 내용 변화 (인풋박스에 텍스트 입력 등..)
  • :hover와 같은 CSS Pseudo Class
  • 클래스 Attribute의 동적 변화
  • JS를 통한 DOM 동적 변화
  • 엘리먼트에 대한 offsetWidth / offsetHeight (화면에서 보여지는 좌표) 계산시
  • 스타일 Attribute 동적변화

reflow 최적화 방법

  1. 클래스 변화에 따른 스타일 변화를 원할 경우, 최대한 DOM 구조 상 끝단에 위치한 노드에 주기
  2. 인라인 스타일을 최대한 배제
  3. 애니메이션이 들어간 엘리먼트는 가급적 position:fixed 또는 position:absolute 로 지정
  4. 퀄리티와 퍼포먼스 사이에서 타협
  5. 테이블 레이아웃을 피하기
  6. IE의 경우, CSS에서의 JS표현식을 피하기
  7. JS를 통해 스타일변화를 주어야 할 경우, 가급적 한번에 처리
  8. CSS Rules는 필요한 만큼만 정리
  9. position:relative 사용 시 주의

클래스 변화에 따른 스타일 변화를 원할 경우, 최대한 DOM 구조 상 끝단에 위치한 노드에 주기

클래스 변화로 인한 Reflow는 막을 수 없다. 그러나 이로 인한 reflow의 범위를 줄일 수 있다. DOM 트리에서 가급적 하위에 위치한 노드에 클래스 변화를 줄 경우, 이는 리플로우의 행동반경을 전체 페이지가 아닌 일부 노드들로 제한할 수 있다. 다시말해 페이지를 감싸는 클래스를 수정하는 행위는 되도록 피해야 한다.

OOCSS 방식을 통해 클래스변화가 발생한다면, 특정 엘리먼트에 대해 상당히 많은 클래스를 적용시켜서 reflow가 상당히 발생할 거 같지만, 실제로는 리플로우의 영향을 최소화함으로써 퍼포먼스적인 측면에서 큰 이득이 발생한다.

인라인 스타일을 최대한 배제

인라인 스타일을 적용할 경우 페이지에 있는 노드가 바껴 repaint 혹은 reflow가 발생 할 때, 이 스타일을 재해석하고, reflow 작업을 다시 발생시키게 된다. 즉 다시말해 수차례에 reflow 작업을 발생시키는 것이다. 그런데 인라인 스타일을 쓰지 않는다면 외부스타일 클래스의 조합으로 단 한번만 리플로우를 발생시킨다.

애니메이션이 들어간 엘리먼트는 가급적 position:fixed 또는 position:absolute 로 지정

우리가 js 혹은 css를 가지고 애니메이션을 만들어 적용시키는 것은, 초당 수 많은 reflow를 발생시키게 하는 행위이다. 이러한 경우에 해당 개체의 position 속성을 fixed 또는 absoute로 주게 되면 다른 요소들의 레이아웃에 영향을 주지 않는다. 즉, repaint만 발생시키는 것이다.

퀄리티와 퍼포먼스 사이에서 타협

가로로 100px 이동하는 애니메이션이 존재한다고 가정하자
이때 첫번 째 방법은 한 동작에 1px 씩 움직이는 것이고 두번 째 방법은 3px씩 움직이는 것이다. 물론 퀄리티로 따져보면 첫번 째 방법이 훨씬 부드럽게 보인다. 그러나 3px 씩 움직이는 것 보다 퍼포먼스가 떨어진다. 당연히 많은 reflow를 발생시키에 일어나는 일이다. 그렇기에 퀄리티와 퍼포먼스를 조정 해야한다.

테이블 레이아웃을 피하라

아마 프론트엔드 개발자가 되기 위해 공부를 하고 있다면 한번 쯤은 들어봤을 말이다. 테이블 레이아웃을 피하라는 것, 테이블로 구성된 페이지 레이아웃은 점진적 페이지렌더링이 적용되지 않는다. 쉽게 말해 테이블 중 어느 한 곳이라도 바뀌면 테이블 전체에 reflow가 발생하는 거다.

JS를 통해 스타일변화를 주어야 할 경우, 가급적 한번에 처리

var toChange = document.getElementById('elem');
toChange.style.background = '#333';
toChange.style.color = '#fff';
toChange.style.border = '1px solid #ccc';

다음 코드를 생각해 보자. 이 코드는 여러번 reflow와 repaint를 발생시킨다. 이를 다시 바꿔보면 다음과 같이 해결 할 수 있다.

/* CSS */
#elem { border:1px solid #000; color:#000; background:#ddd; }
.highlight { border-color:#00f; color:#fff; background:#333; }
/* js */
document.getElementById('elem').className = 'highlight';

position:relative 사용 시 주의

relative는 자신의 위치 기준으로 움직이는 방식으로, 노드가 움직일 경우 모든 노드에 위치에 영향을 주게된다. 즉 relative는 수 많은 reflow를 발생 시킬 수도 있다는 것이다.

profile
고등학생 주니어 개발자

0개의 댓글