JavaScript | Reflow 란 (feat. 브라우저 렌더링)

dev_hee·2021년 10월 26일
16

웹 성능

목록 보기
3/4
post-thumbnail

들어가며...

프론트 엔드 개발자라면 브라우저 렌더링 과정을 알아야한다. 그리고 브라우저 렌더링 과정에서 핵심은 reflow이다. DOM 요소를 다룰 때, reflow가 최대한 발생하지 않도록 조심해야 한다. 따라서 이 글을 작성하며 브라우저 렌더링과정과 리플로우에 대해서 알아보고자 한다.

브라우저 렌더링

브라우저는 다음과 같은 방식으로 화면에 렌더링을 한다.

브라우저 렌더링 과정

  1. Load: 브라우저는 HTML, CSS, JS, 이미지, 폰트 파일 등 렌더링에 필요한 리소스를 서버에게 요청하고 응답을 받는다.

  2. HTML과 CSS는 렌더링 엔진에 의해 파싱되고 트리구조가 생성되며, 자바스크립트는 자바스크립트 엔진에 의해 파싱되고 AST를 생성된다.

  3. 렌더링 엔진은 HTML과 CSS 파일을 로드받은 다음, 파싱하여 DOM과 CSSOM을 생성하고, 그를 결합하여 렌더 트리를 생성한다.

  4. 자바스크립트 엔진은 JS 파일을 로드 받은 다음, 파싱하여 AST(Abstract Syntax Tree)를 생성하고, 바이트 코드로 변환하여 실행한다. 자바스크립트는 인터프리터 언어이므로 문 단위로 해석되고 실행된다. 이때 자바스크립트는 DOM API를 통해서 DOM이나 CSSOM을 변경할 수 있다. 변경된 DOM과 CSSOM은 다시 렌더 트리로 결합된다.

  5. 렌더 트리를 기반으로 HTML요소의 레이아웃(위치와 크기)을 계산하고 브라우저 화면에 페인팅 한다.

4번 과정에 의해서 5번에서 다시 레이아웃을 재계산 하는 상황을 Reflow라고 부른다.

Reflow와 Repaint

Repaint

재결합된 렌더 트리를 기반으로 다시 화면에 페인트하는 것을 말한다.

Reflow

레이아웃 계산을 다시 하는 것으로, Reflow가 발생하면 Repaint는 필연적으로 발생한다.
리플로우는 HTML 요소들의 위치와 크기를 다시 계산해야 하기 때문에, 리페인트에 비해서 시간이 오래걸린다.
즉, 변경하려는 특정 요소의 위치와 크기뿐 아니라, 연관된 다른 요소들의 위치와 크기까지 재계산해야 하기 때문이다. 따라서 리플로우가 자주 발생하도록 하는 코드는 지양해야한다.

Reflow가 발생했는지 확인하는 방법

크롬 브라우저에서 개발자 도구를 사용해 리플로우가 발생했는지 확인할 수 있다.
아래와 같은 HTML코드를 작성하고, 크롬 브라우저로 연다.

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>reflow</title>
    <style>
      .box {
        background-color: red;
        width: 100px;
        height: 100px;
      }
    </style>
  </head>
  <body>
    <div class="box"></div>
    <script>
      // Reflow를 발생시키는 코드
      const $box = document.querySelector('.box');
      $box.onclick = () => {
        $box.style.width = '200px';
        $box.style.height = '200px';
      };
    </script>
  </body>
</html>

크롬의 개발자 도구의 Perfomance(성능)탭을 클릭하고 새로고침 아이콘을 클릭한다.

새로고침 클릭

아래 사진과 같이 box요소를 클릭하지 않고, 중지를 누른 경우엔 초기에 단 한번 레이아웃 계산이 발생하고, 리플로우가 발생하지 않았다.

리플로우가 발생하지 않은 경우

하지만 box요소를 클릭하고 중지를 누른 경우엔 초기에 레이아웃 계산과, 리플로우가 한번 발생한 것을 확인할 수 있다.

리플로우가 발생한 경우

Reflow가 발생하는 경우

리플로우가 자주 발생하지 않도록 코드를 작성해야, 브라우저 렌더링 성능을 높이고 사용자 경험을 좋게 만들 수 있다. 그렇다면 리플로구아 발생하는 경우를 알아보고, 그를 피하기 위한 대안책을 알아보자.

리플로우가 발생하는 6가지 경우

  1. 요소의 크기, 위치 변겅
  2. 브라우저 창의 크기 변경
  3. font size 변경
  4. scroll
  5. DOM API를 통한 노드 요소의 추가, 삭제

Layout thrashing cheatsheet

참고로 위의 링크로 들어가면, 리플로우를 발생시키는 CSS 프로퍼티들이 나와있다.

Reflow를 최소화 하는 법

편안한 사용자 환경을 제공하기 위한 리플로우를 최소화 하는 방법이다.

가급적 레이아웃 피하기

width와 height등과 같은 기하학적 속성의 변경은 리플로우가 필요하다.
변경되는 요소 외에 다른 요소들이 많이 존재한다면, 모든 요소들의 위치와 크기를 파악하도록 계산하는데 많은 시간이 걸린다. 따라서 꼭 필요한 경우가 아니라면 width와 height등과 같은 기하학적 속성의 변경은 피하는 것이 좋다.

리플로우를 발생시키는 CSS트리거: https://csstriggers.com/

만약 기하학적 속성 변경이 불가피 하다면, transform 을 사용하거나,
visibility, display보다는 opacity를 사용하는 것이 성능 개선에 더욱 도움이 된다.

이전 레이아웃 모델 대신 Flexbox 사용

float와 같은 이전 레이아웃 모델을 사용할 때의 리플로우 시간은, flexbox를 사용한 경우보다 훨씬 더 오래걸린다. 동일한 시각적 배치를 표현하기 위해서는 float보다는 flexbox를 사용하면 좋다.

하지만 flexbox는 IE 6-9와 Opera 10-11.5 버전은 제공하지 않기 때문에, IE를 고려해야 하는 웹페이지 개발에서는 사용할 수 없는 방법이다.

can i use

애니메이션은 흐름 밖에서 변경

애니메이션과 같이 복잡한 렌더링 변경이 필요한 경우에는 HTML 요소들의 흐름 밖에서 변경해야 성능 개선에 도움이 된다. 즉, 변경할 때는 position을 절대 위치(absolute)또는 고정 위치(fixed)를 사용하여 주변 요소들에게 영향을 주지 않는 요소로 설정해야 한다.

결론

이 포스팅을 통해서, 반드시 리플로우가 발생하지 않도록 웹페이지를 만들어야겠다는 생각은 하지 말아야한다. 리플로우가 발생할 수 밖에 없는 경우도 존재한다. 화려한 애니메이션으로 사용자에게 즐거움을 전달하는 과정은, 반드시 리플로우가 동반될 수 밖에 없다. 하지만 브라우저의 성능을 개선하기 위해서, 리플로우가 최소한으로 발생할 수 있는 방법이 있다면 그 방법을 택할줄 아는 능력이 프론트 엔드 개발자가 필요한 덕목이다.

참고

profile
🎨그림을 좋아하는 FE 개발자👩🏻‍💻

3개의 댓글

comment-user-thumbnail
2023년 2월 7일

그림을 보니까 더욱 이해가 잘되네요ㅎㅎ 정리 잘해주셔서 감사합니다!! 🤩

답글 달기
comment-user-thumbnail
2023년 12월 6일

With the increasing number of international students worldwide, the paper ghostwriting http://www.pnstudy.com/ industry in the United States has been gradually gaining attention. This industry has provided valuable assistance to many international students, bringing several advantages to their academic pursuits and future development.

답글 달기
comment-user-thumbnail
2024년 1월 9일

I spent many hours challenging myself and improving my https://retro-bowl.io/drift-hunters skills in this game.

답글 달기