JavaScript | Reflow 란 (feat. 브라우저 렌더링)
들어가며...
프론트 엔드 개발자라면 브라우저 렌더링 과정을 알아야한다. 그리고 브라우저 렌더링 과정에서 핵심은 reflow이다. DOM 요소를 다룰 때, reflow가 최대한 발생하지 않도록 조심해야 한다. 따라서 이 글을 작성하며 브라우저 렌더링과정과 리플로우에 대해서 알아보고자 한다.
브라우저 렌더링
브라우저는 다음과 같은 방식으로 화면에 렌더링을 한다.
-
Load: 브라우저는 HTML, CSS, JS, 이미지, 폰트 파일 등 렌더링에 필요한 리소스를 서버에게 요청하고 응답을 받는다.
-
HTML과 CSS는 렌더링 엔진에 의해 파싱되고 트리구조가 생성되며, 자바스크립트는 자바스크립트 엔진에 의해 파싱되고 AST를 생성된다.
-
렌더링 엔진은 HTML과 CSS 파일을 로드받은 다음, 파싱하여 DOM과 CSSOM을 생성하고, 그를 결합하여 렌더 트리를 생성한다.
-
자바스크립트 엔진은 JS 파일을 로드 받은 다음, 파싱하여 AST(Abstract Syntax Tree)를 생성하고, 바이트 코드로 변환하여 실행한다. 자바스크립트는 인터프리터 언어이므로 문 단위로 해석되고 실행된다. 이때 자바스크립트는 DOM API를 통해서 DOM이나 CSSOM을 변경할 수 있다. 변경된 DOM과 CSSOM은 다시 렌더 트리로 결합된다.
-
렌더 트리를 기반으로 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가지 경우
- 요소의 크기, 위치 변겅
- 브라우저 창의 크기 변경
- font size 변경
- scroll
- DOM API를 통한 노드 요소의 추가, 삭제
참고로 위의 링크로 들어가면, 리플로우를 발생시키는 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를 고려해야 하는 웹페이지 개발에서는 사용할 수 없는 방법이다.
애니메이션은 흐름 밖에서 변경
애니메이션과 같이 복잡한 렌더링 변경이 필요한 경우에는 HTML 요소들의 흐름 밖에서 변경해야 성능 개선에 도움이 된다. 즉, 변경할 때는 position
을 절대 위치(absolute
)또는 고정 위치(fixed
)를 사용하여 주변 요소들에게 영향을 주지 않는 요소로 설정해야 한다.
결론
이 포스팅을 통해서, 반드시 리플로우가 발생하지 않도록 웹페이지를 만들어야겠다는 생각은 하지 말아야한다. 리플로우가 발생할 수 밖에 없는 경우도 존재한다. 화려한 애니메이션으로 사용자에게 즐거움을 전달하는 과정은, 반드시 리플로우가 동반될 수 밖에 없다. 하지만 브라우저의 성능을 개선하기 위해서, 리플로우가 최소한으로 발생할 수 있는 방법이 있다면 그 방법을 택할줄 아는 능력이 프론트 엔드 개발자가 필요한 덕목이다.
참고
Author And Source
이 문제에 관하여(JavaScript | Reflow 란 (feat. 브라우저 렌더링)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@heelieben/JavaScript-Reflow-란-feat.-브라우저-렌더링저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)