최적화 할 수 있는 부분을 크게 두가지로 나누면 파싱 단계에서 리소스의 요청 수를 줄이는 것과 스타일, 레이아웃, 페인트 단계를 최소화하여 렌더링 과정을 최적화하는 방법이 있다.
로딩 최적화
HTML문서를 다운로드 하여 문서를 해석하고 DOM트리를 구성하는(파싱) 단계에서 리소스를 요청하고 다운로드 받는 과정이 존재한다. 이 때 서버에 요청하고 다운받는 시간을 네트워크 패널에서 확인할 수 있는데 생각보다 많은 시간이 소요되므로 해당 로직을 최소화 할 필요가 있다.
이미지 스프라이트
웹 페이지에서 아이콘마다 다른 이미지를 사용할 경우 아이콘의 갯수만큼 리소스 요청이 발생한다. 이러한 경우 이미지 스프라이트 기법을 사용하여 요청을 한번으로 줄일 수 있다. 이미지 스프라이트는 여러개의 이미지를 하나로 만들고 css의 background-position 속성을 사용하여 이미지를 부분적으로 활용하는 것이다.
Base64 image
외부 경로에서 이미지를 가져오던 부분을 Base64로 변환된 URI로 대체하여 사용할 수 있다. 이렇게 하면 외부이미지를 사용하기 위해 발생하는 요청 횟수를 줄일 수 있다.
만능 유틸 라이브러리
lodash와 같은 만능 유틸 라이브러리를 사용할 경우 일반적인 방식으로 가져와 사용하면 유틸 함수 전체가 포함되므로 자바스크립트 파일 용량이 커지게 된다. 이 경우에는 필요한 기능만 부분적으로 가져올 수 있으며 되도록 기능이 많이 포함된 라이브러리 사용은 지양하는 것이 좋다.
렌더링 최적화
레이아웃 과정에서 자바스크립트의 코드를 통해 DOM이 변경되거나 스타일이 변경될 경우 변경된 스타일을 반영하고 다시 레이아웃을 해야 화면에 렌더링 할 수 있다. 이 때 각각의 크기를 계산하고 요소간의 관계를 파악하면서 시간이 오래 걸리게 된다. 따라서 레이아웃을 최대한 적게하여 리페인트를 최소화할 수 있는 최적화 방법을 정리해본다.
강제 동기 레이아웃 피하기
스타일을 변경한 다음 offsetHeight
, offsetTop
과 같은 계산된 값을 속성으로 읽을 때 강제로 동기 레이아웃을 수행해야 한다. 계산된 값을 반환하기 전에 변경된 스타일이 계산 결과에 적용되어 있지 않으면 변경 이전 값을 반환하기 때문에 브라우저는 동기로 레이아웃을 해야만 한다. 최신 브라우저에도 동일하게 발생하는 부분이므로 강제 동기 레이아웃을 발생할 수 있는 코드를 최대한 사용하지 않도록 주의해야 한다.
숨겨진 엘리먼트 수정
엘리먼트가 display: none
스타일을 가지고 있으면 DOM 조작과 스타일을 변경하더라도 레이아웃과 리페인트가 발생하지 않는다. 많은 수의 엘리먼트를 변경해야 할 경우 숨겨진 상태에서 엘리먼트를 변경하고 다시 보이도록 하여 레이아웃 발생을 최대한 줄인다. visibility: hidden
은 보이지 않아 리페인트는 발생하지 않지만, 공간을 차지하기 때문에 레이아웃은 발생하게 된다.
지금까지 웹 브라우저의 동작과정과 로딩 및 렌더링에서 최적화 할 수 있는 방법 몇가지를 정리해보았다.
참고 자료