이번 시간에는 브라우저 성능 최적화에 대해 알아보려고 한다!
이를 알기 위해서 우선 브라우저 렌더링 과정부터 알아보도록 하자 :)
브라우저는 총 5단계에 걸쳐 렌더링 된다.
첫번째 단계는 다시 아래의 세 단계를 거친다.
a. HTML 파일과 CSS 등 화면을 그리는데 필요한 리소스를 다운로드
b. 다운로드한 HTML을 파싱(Parsing)(= 브라우저가 이해할 수 있는 형태로 변환)
c. 트리(Tree)구조로 표현되어 있는 DOM(Document Object Model)을 생성
CSS도 위와 비슷한 과정을 거쳐 브라우저가 이해할 수 있는 형태로 변환된다. 그 결과 CSSOM(CSS Object Model)이라는 트리 구조가 생성된다.
만들어진 DOM과 CSSOM을 결합하여 렌더 트리(render tree)를 만드는 단계
렌더 트리는 화면에 표시되는 각 요소의 레이아웃을 계산하는데 사용됨
cf) display:none
처럼 화면에 표시되지 않는 요소는 렌더 트리에 포함되지 않음
cf) opacity:0
이나 visibility:hidden
처럼 존재는 하지만 유저의 눈에만 보이지 않는 요소는 렌더트리에 포함
브라우저가 객체의 모양과 위치를 생성
= 화면의 레이아웃을 잡는 단계!
아래의 속성들이 본 단계에서 계산됨
ex) color 또는 background-color가 변경되어도 Layout 단계가 실행되지 않음!
<출처> : 출처
다른 단계에 포함되지 않는 다른 속성들도 이 단계에서 계산됨
브라우저는 효율적인 Paint를 위해 구성 요소를 여러 개의 레이어(layer)로 나눠서 작업함
opacity / transform / cursor / z-index
그럼 궁금증이 생긴다!
만약 애니메이션을 이용해 CSS의 각 속성들이 추가, 제거, 변경되면??
Reflow란 Layout
단계에서 담당하는 속성들이 추가, 제거, 변경되었을 때 리렌더링 되는 과정을 일컫는다.
예를 들어 만약 CSS 속성 중
width
를 애니메이션으로 변경한다고 가정해 보자.
그럼 아래와 같은 과정을 거쳐 리렌더링 될 것이다!
① DOM+CSSOM
: CSSOM을 새로 생성
② 렌더 트리
: 변경된 CSSOM을 이용하여 새로운 렌더 트리를 생성
③ Layout
: 요소의 width
를 변경했으니, 요소의 크기와 위치를 다시 고려하여 화면의 레이아웃을 잡음
④ Paint
: 화면에 배치된 요소에 색을 채워 넣음
⑤ Composite
: Paint
단계에서 나눈 각각의 레이어들을 하나로 합성
위의 일련의 과정을 Reflow
라고 한다!
❗️ Reflow
는 주요 렌더링 경로의 모든 단계를 모두 재실행한다. 그래서 브라우저 리소스를 많이 사용한다.
Repaint란 Paint
단계에서 담당하는 속성들이 추가, 제거, 변경되었을 때 리렌더링 되는 과정을 일컫는다.
예를 들어 만약 CSS 속성 중
background-color
를 애니메이션으로 변경한다고 가정해 보자.
그럼 아래와 같은 과정을 거쳐 리렌더링 될 것이다!
① DOM+CSSOM
: CSSOM을 새로 생성
② 렌더 트리
: 변경된 CSSOM을 이용하여 새로운 렌더 트리를 생성
③ Paint
: 화면에 배치된 요소에 색을 채워 넣음
④ Composite
: Paint
단계에서 나눈 각각의 레이어들을 하나로 합성
위의 일련의 과정을 Repaint
라고 한다!
❗️ Repaint
는 Layout
단계에서 담당하는 속성은 그대로인 경우이므로 Layout
단계를 실행하지 않는다!
❗️ 그래서 Reflow
보다는 빠르지만 Repaint
역시 모든 단계를 거치기 때문에 브라우저 리소스를 많이 사용한다.
브라우저가 렌더링 될 때 가장 좋은 성능을 낼 수 있도록( = 브라우저 리소스를 많이 사용하지 않도록) 설계하는 것을 말한다.
공부하다보니 브라우저 성능을 최적화하는 방법은 굉장히 무궁무진하다..!
다른 방면에서의 성능 최적화는 다음 시간에 공부하는 걸로 하고
오늘은 CSS 관련된 브라우저 성능을 최적화하는 방법에 대해서만 알아보도록 하자!
예를 들어 Layout
의 left
, right
속성보다는 Composite
의 속성인 transform
을 이용하여 애니메이션을 주는 게 훨씬 성능면에서 좋다.
왜냐하면 Layout
과 Paint
단계를 거치지 않고 Composite
단계만 리렌더링 되기 때문이다!
위와 같은 구조로 코드를 짰다고 가정하자.
여기서 'Hi'의 폰트 컬러를 바꾸고 싶을 때 outside-class
에서 CSS를 적용하기 보다는 inside-class
에서 CSS를 적용하는 게 더 좋은 방식이다!
HTML을 파싱하다가 인라인 스타일을 사용한 태그를 만나면 그때마다 리렌더링되어 CSSOM 재생성하므로 브라우저 성능이 떨어지기 때문이다!
어쩔 수 없이 Reflow
가 일어나는 속성을 사용하여 애니메이션을 주어야 하는 경우도 분명히 있기 마련이다.
이럴 경우 애니메이션이 들어간 요소에 position : fixed
또는 position : absolute
속성을 적용하자!
position : fixed
와 position : absolute
는 다른 요소의 레이아웃에 영향을 미치지 않으므로 페이지 전체가 아닌, 해당 요소만 Reflow
가 발생한다 :)
Reflow
가 유발시키는 CSS Recalculation
이 될 때 CSS 규칙에 따라 오른쪽에서 왼쪽으로 이동하며 계속 매칭한다.
그러므로 불필요한 선택자를 사용하는 것은 성능을 저하시킬 수 있다!
위와 같은 코드에서 'Hi'라는 글자를 초록색으로 변경하고 싶다고 가정하자.
❌ 위와 같은 CSS는 부모 클래스(outside-class)와 내가 선택하고자 하는 자식 클래스(inside-class) 모두를 선택자로 설정한 나쁜 예이다.
⭕️ 반면 위의 CSS는 불필요한 선택자 없이 내가 선택하고자 하는 클래스(inside-class)만 선택자로 설정한 좋은 예이다.
내가 퍼블리싱을 할 때 생각나는대로 그저 적용했던 CSS들이 잘 적용되어 보여서 아무 문제가 없는 줄 알았었다.
브라우저 성능 최적화에 대해 아예 몰랐기 때문이었다.
이번에 공부하며 성능 최적화의 여러 방법들 중 CSS에 관련된 부분들만 공부해도 이렇게 다양한 방법이 있다는 것에 놀랐다.
게다가 내가 여태껏 적용했던 CSS 중에서도 브라우저 성능을 떨어뜨리는 방식들을 사용했던 것들이 있어 그런 방식들은 앞으로 지양해야겠구나 하는 깨달음을 얻을 수 있었던 좋은 시간이었다!