[HTML] 브라우저의 렌더링 과정및 최적화작업

Muru·2024년 8월 9일
0
post-thumbnail

본격적으로 들어가기 전에 '브라우저의 렌더링'중 이 렌더링의 뜻을 얼핏 '눈으로 보이게 되는 과정' 이라고 생각 할 수 있다. 설명이 반쯤 모자란것같다.

  • 렌더링이란 HTML, CSS, JS로 작성된 문서를 파싱해서 브라우저를 유저가 눈으로 직접 볼 수 있게 시각적으로 출력하는 것을 말한다.

파싱이 뭔데?

  • 파싱이란 프로그래밍 언어에 작성된 문서의 문자열들을 분해하고 구조를 생성하는 일련의 과정을 의미한다. 브라우저의 렌더링 과정에서 이 파싱은 DOM트리를 생성한다.


브라우저가 실제 화면 까지 렌더링하기까지는 크게 5단계로 볼 수 있다.


브라우저의 렌더링 과정

1. DOM (Document Object Model) 및 CSSOM(CSS Object Model) 생성

  • 브라우저가 HTML 문서를 파싱하여 DOM 트리를 생성한다.
  • 각 HTML 태그들은 바로 DOM 트리의 노드들로 표현이 된다.
  • CSS가 포함되어 있다면 이것 또한 파싱을 통해 CSSOM 트리를 생성한다.

이때 DOM 트리란 브라우저가 이해할 수 있는 노드들로 구성된 트리 자료구조를 의미한다.

2. 렌더 트리 생성

  • 생성된 DOM 트리와 CSSOM 트리의 결합을 통해 렌더 트리를 구성한다.

이 과정에서 브라우저가 화면에 그려야 하는 요소들만 나타낸다.
그렇다면 visibilty : hiddendisplay : none 속성을 적용한다면 렌더트리에는 어떻게 적용되는것일까?
visibility : hidden 속성은 공간은 차지하지만 보이지만 않는것이기 때문에 렌더트리에서 포함된다.
display:none 속성은 공간조차 차지 하지 않기 때문에 렌더 트리에서 제외된다.

3. 레이아웃

  • 렌더 트리의 각 요소에 대한 정확한 위치와 크기를 계산한다.

4. 페인팅

  • 레이아웃 단계에서 계산된것을 기반으로 렌더 트리의 각 요소들을 화면 상의 픽셀로 변환한다.
  • 이때 픽셀로 변환된 것은 하나의 레이어가 아니라 여러 개의 레이어로 관리가 된다.

5. 합성

합성 단계에서는 페인팅 단계에서 생성된 레이어들을 합쳐서 실제화면에 나타낸다.




브라우저 렌더링이 반복적으로 실행된다??

브라우저가 한번 렌더링하고 나서는 한번만 실행되는것이 아니다. 사용자의 어떠한 클릭이나 그외 어떠한 상호작용을 일으키는 무언가를 한다면 브라우저의 렌더링 작업이 또 발생 할 수 있다.

렌더링은 어떨때 또 발생 할 수 있을까?

  1. 자바스크립트로 인한 특정 요소를 추가하거나 삭제할경우

  2. 뷰포트 크기변경시

  3. HTML 요소의 CSS 스타일 변경

  4. 애니메이션이나 트랜지션이 진행중일때

그외 다양한 상황에서 렌더링 작업이 반복적으로 발생 할 수 있다.
다만 모든 상황이 동일한 과정을 거치는것이 아니다.
상황에 따라 Reflow 과정과 Repaint 과정 둘중 하나가 발생된다.

Reflow : 레이아웃의 위치와 크기를 다시 계산해야 할 때 발생하는 과정이다.
즉 렌더링 5단계중 레이아웃 단계에서 다시 시작하여 레이아웃 단계 => 페인팅 => 합성의 단계를 거쳐야한다.
Reflow는 값비싼 비용을 지불해야 하기 때문에 성능에 큰 영향을 미칠 수 있으므로 최적화 작업시 해당 부분에 많은 신경을 써야한다.

Refaint : 레이아웃의 변화는 없는 요소의 변경이 있을때 발생하는 과정이다.
즉 렌더링 5단계중 페인트 단계에서 부터 시작하므로 페인팅 => 합성의 단계 두단계 만 다시 거친다.
Refaint는 레이아웃 단계를 안거치기 때문에 Reflow보다는 성능적 영향이 덜 한 부분이 있다.

Reflow와 Refaint를 최소화 하는것이 성능적으로 최적화에 도움이 된다는 결론에 도달한다. 어떻게 Reflow와 Refaint를 최소화 할 수 있을까?

Reflow와 ReFaint 최소화하여 최적화하기

그래서 넌 최적화 작업에 뭘 할 수있는데???????

  1. 레이아웃 변경하는 속성 피하기
    'width', 'height', 'padding', 'margin', 'top', 'left', 'right', 'bottom', 'border' 등의 속성은 Reflow를 유발 할 수 있으므로 이러한 속성들은 피해야한다.
    그 대신 'left' , 'right'같은 속성은 transform 속성을 이용하고,
    visibility, display같은 속성은 opacity 속성을 사용하면 reflow와 repaint 발생을 최소화 할 수 있다.
    다만 repaint 발생이 일어날 수는 있지만 이 과정 역시 GPU 가속이 적용되면 성능에 미치는 영향이 최소화 될 수 있다.

  1. 쓰로틀링과 디바운스 적극 활용
    쓰로틀링 : 사용자가 이벤트 작업을 수행하는 동안 지정된 시간 간격으로 함수를 호출
    디바운스 : 사용자가 특정 시간동안 이벤트 작업을 수행하지 않았을 때 함수를 호출

왜 저 두개를 사용해야 할까?

쓰로틀링이 필요한 예시를 만들어보자.
홈페이지에서 사용자가 마우스 스크롤이 발생할때 레이아웃 변경이나 애니메이션이 동작한다고 가정해보자.

쓰로틀링을 통한 제한을 걸지 않는다면 사용자가 마우스 스크롤 한번만 트리거 시켰을 뿐인데 요청되는 함수 호출을 적게는 몇십번 많게는 몇백번까지도 호출이 될 수 있다. 이는 곧 쓸데없는 Reflow 또는 Refaint 작업이 이루어져 성능 최적화에 악영향을 끼친다.

쓰로틀링을 통한 제한을 걸어보자. 제한 조건은 스크롤 이벤트가 발생하더라도 지정한 시간 간격(100ms) 마다 한 번씩만 함수가 실행되게 한다.
사용자가 100ms안에 초인적인 힘으로 마우스 스크롤을 1억번한다고 해도 함수호출은 한번만 이루어지게 된다. 이는 곧 Reflow 또는 Refaint 요청의 최소화로 성능 최적화에 이바지 하게된다.


디바운스가 필요한 예시를 만들어보자. 홈페이지에서 이메일과 비밀번호 입력시 사용자가 입력조건을 만족했는지 서버에 요청을 보내 확인한다.

디바운스를 통한 제한을 걸지 않는다면 사용자가 키보드로 입력할때마다 서버에 요청을 보낸다. 이는 사용자 관점에도 매우 불쾌한 경험이고 성능적으로도 좋지 않다. 일단 사용자가 연속적인 타이핑이 모두 끝난것 같을때 요청을 보낸다면 어떨까?

디바운스를 통한 제한을 걸어보자. 제한 조건은 키보드 입력을 모두 마치고나서 시간(500ms)이 지났을 경우에만 서버에 요청 함수를 보내게 한다.
사용자는 키보드 타이핑을 연속적으로 타이핑 하고 나서 모두 끝마쳤을경우(500ms 시간동안 타이핑이 없을때) 그제서야 함수를 한번 보낸다.
결국 디바운스를 통해 성능 최적화에 이바지 했다고 볼 수 있다.

그 외 다른 방법으로도 성능 최적화를 할 수 있다. 개인의 프로젝트에 맞게 적합한 방법의 성능 최적화를 적용하는것이 개발자의 역량 인 것같다.

profile
Developer

0개의 댓글