[기타] 웹 렌더링 순서와 최적화 방법
Swimjiy
—December 19, 2018
웹 렌더링 순서
사용자가 페이지를 요청하고, 서버로부터 전달받은 데이터를 렌더링 하기까지 몇 초 안되는 시간이지만 살펴보면 다음과 같은 과정이 존재한다.
HTML 파싱 및 DOM 트리 구성 -> 렌더링 트리 구성 -> 렌더 트리 배치 -> 렌더 트리 그리기
HTML 파싱 및 DOM 트리 구성
웹을 표시해주는 브라우저들은 각기 고유의 컴포넌트들을 갖고 있다. 그 중에서 웹 페이지의 표시를 담당하는 렌더링 엔진
이 있는데 이 엔진의 작동 순서에 맞춰 웹 화면이 표시된다. 사용자가 페이지를 요청하면 렌더링 엔진이 서버로부터 필요한 데이터를 전달받는데, 이 때 HTML 마크업을 파싱하고 파싱된 요소들은 DOM 트리로 변환한다. 더불어 HTML파싱이 끝나면 스타일 시트 파일 또한 파싱해 CSS 요소를 저장한다.
렌더링 트리 구성
HTML과 CSS 파싱이 완료되면 두 가지를 결합한 렌더링 트리
를 구성한다. 렌더링 트리란 파싱된 HTML과 CSS 컨텐츠를 정확한 순서로 그릴 수 있도록 시각적으로 표현한 것이다. 이 때 엔진은 DOM트리의 루트부터 시작해 각각의 시각적 노드를 순회하며, script태그나 메타 태그와 같이 시각적이지 않은 노드는 생략하며 display:none
속성 또한 트리에서 보이지 않게끔 설정한다.
렌더 트리 배치
렌더 트리에는 위치와 크기값을 가지고 있지 않기 때문에 배치를 통해 각 노드가 표시되어야 할 정확한 값을 계산하고 전달한다. 이 때 HTML은 흐름 기반 모델이기 때문에 배치는 위에서 아래로, 왼쪽에서 오른쪽으로 흐른다. 좌표값은 HTML 요소 중 최상위인 HTML요소를 기준으로 시작한다.
렌더 트리 그리기
그리기 단계에서는 화면에 내용을 표시하기 위해 렌더 트리가 탐색되고, 렌더러의 paint()
메서드를 호출한다.
렌더링 성능 최적화
HTML
태그의 개수를 최소화한다. 전체 태그의 경우 보통 1000개 이하로 간결하게 작업하는 것을 권장하고 있으며, 특히 중첩된 태그를 최소화하는 것이 중요하다. 해당 페이지의 전체 태그 개수를 확인하는 방법으로는 아래와 같은 코드가 있다.javascript:alert(document.getElementsByTagName("*").length);void(0);
CSS & JavaScript
웹은 동기화(Synchronous)의 속성을 가지고 있기 때문에 HTML을 렌더링하는 과정에서 스크립트<script>
나 스타일 시트<link>
를 만나게 되면 즉시 파싱을 멈추고 해당 요소를 실행한다. 이로 인해 이들의 처리 순서에 따라 렌더링 성능에 영향을 줄 수 있다.
css의 경우는 렌더 트리 생성에 필요한 정보를 담고 있기 때문에 빠른 로드가 필요한 반면에, js의 경우는 화면 출력보다는 기능적인 역할을 하는 경우가 많기 때문에 브라우저 렌더링이 마무리된 시점에서 로드되어야 한다. 따라서 CSS는 <head>
사이에 추가하고 Js는 <body>
맨 하단에 추가하는 것이 좋다.
images
웹에서 이미지가 사용될 경우 해당 이미지를 다운받기 위해 브라우저는 서버에 이미지를 요청한다. 하지만 사용된 이미지가 많을 경우 이미지의 개수만큼 반복 요청을 해야하기 때문에 렌더링 시간이 늘어나게 된다. 따라서 아이콘의 경우 여러 이미지를 한 파일에 모아넣은 스프라이트 이미지로 사용하게 되면 한 번의 요청으로도 렌더링이 가능하다.
또한 일반 사진 이미지의 경우는 포토샵 저장 시에 웹 용으로 저장
을 하게 되면 웹 이용에 최적화된 이미지 크기로 변경할 수 있기 때문에 전체 렌더링 시간을 단축할 수 있다.
결론
이번에 처음으로 웹 최적화를 작업하게 되어서 겸사겸사 렌더링 순서도 알아보았는데 렌더링의 과정에 대해 이해하고 나니 자연스럽게 최적화할 수 있는 방법도 정리되는 것 같다. 또한 웹 이용자의 50%가 페이지 로드 중에 이탈한다고 하니 단순히 웹 제작만이 전부가 아니라 사용자가 편리하게 이용할 수 있도록 최적화하는 과정 또한 중요한 작업이라고 생각했다.