브라우저 렌더링 최적화 방법

하머·2022년 9월 24일
0
post-thumbnail

🤔앞서서..

앞선 시리즈에서 나는 브라우저의 렌더링 과정을 알아보았다. 그 결과 렌더링의 최적화에 있어서는 리플로우와 리페인트를 최소화하는 과정을 가지는 것이 최적화에 있어서 가장 중요한 부분임을 깨닫게 되었다. 리플로우와 리페인트를 다시 정리해보고, 렌더링을 최적화하는 방법을 알아보도록 하자.


1. 리플로우

Reflow: 렌더 트리를 재구성 하기 위한(Layout) 웹 브라우저 프로세스의 이름

사진출처

  • 리플로우는 브라우저에서 사용자를 차단하는 작업이므로, 개발자가 리플로우 시간을 향상하는 방법을 이해하고 다양한 문서 속성(DOM 심도, CSS 규칙 효율성, 다양한 스타일 유형 변경)이 리플로우 시간에 미치는 영향을 이해하는 것이 중요하다.

  • 간혹 문서의 단일 요소를 리플로우 하려면 상위 요소 및 이어지는 모든 요소도 리플로우 해야 할 수 있다.

  • 예로써 브라우저 창의 크기 변경, 계산된 스타일이 수반되는 자바스크립트 메소드 사용, dom에서의 요소 추가 또는 삭제, 요소 클래스 변경 등이 일어날 때 발생함.


2. 리페인트

Repaint: 렌더 트리를 기준으로 다시 화면을 그리는(paint) 웹 브라우저 프로세스의 이름 (리플로우가 일어날 시 함께 일어나나, 리페인트만 될 때도 있음)

  • 리페인트는 리플로우의 부분집합이다(리페인트⊂리플로우) 리플로우가 일어날 때에는 반드시 리페인트가 뒤 따라오지만 스크립트나, 속성의 변화가 레이아웃을 건들지 않는 경우 리페인트만 일어날 수도 있다.

  • 레이아웃을 건들지 않는 예로써 노드의 background-color, visibillty, outline 등의 스타일 변경 시에는 레이아웃 수치가 변경되지 않으므로 Reflow 과정이 생략된 Repaint 과정만 일어나게 된다.


3. 컴포지트

  • 여러 Layer로 나눠지는 Raster 픽셀들을 우리가 실제로 보는 화면처럼 하나의 비트맵으로 합성해주는 단계(리플로우와 리페인트 둘다 거치지 않는다) = 가장 큰 이점을 가진 스타일의 변화 방법

  • 쌓임 맥락(z-index) 순으로 하나의 결과물로 합치는 과정

  • 예로써 transform, opacitiy, cursor, orphans, perspective 등이 해당한다.


4. 렌더링 최적화

기본적으로 앞서 말했던 Reflow, Repaint를 지양하고 같은 기능이라면 Composite로 대체한다.

1. 개발자 도구의 Performance 탭을 활용하자!

우선 왼쪽위의 캡쳐버튼을 누르고 정지하여 원하는 시간동안의 렌더링과정을 확인할 수 있다.
프레임을 클릭하고 보이는 노란색이 Layout과정, 보라색이 Paint과정, 초록색이 Composite 과정이다. 프레임과 과정등을 확인하고 리플로우와 리페인트가 얼마나 일어나는지 확인하자

2. 눈으로 페인트 되는지를 확인하자!

이와 같이 이 옵션을 체크해 줄 경우 페인트 되는 부분(초록색 박스)을 화면상으로 확인할 수 있다.
ex) 애니메이션이나 호버를 했을 때 계속 녹색영역이 유지된다면 지속적으로 페인팅 되는 것이다.
++ transform의 경우 페인팅이 계속해서 일어나지 않는다.

3. 이 외의 방법 들

  • Webpack 사용 - 파일 용량 압축 및 번들링을 통한 파일 개수 감소
  • 이미지 LazyLoading - 화면에 이미지가 보여져야 할 때 이미지를 다운로드하여 CSS, JS를 먼저 다운로드하게 함
  • webp 사용 - 압축율이 좋은 이미지 포맷을 사용하여 파일 용량 압축
  • LazyComponent - 화면에 보이지 않는 컴포넌트는 나중에 다운로드하여 파일개수 감소, 코드가 분리되어 파일 용량 압축
  • Browser Caching - 브라우저에 파일을 캐싱하여 다운로드할 파일 개수 감소
  • css는 비교적 자식노드에게 적용하기
  • useRef, jsSelector 등으로 직접적으로 스타일 할당하지않기(예: xxx.style.width == @@), 인라인으로 스타일 할당하지 않기
  • 애니베이션은 transform 사용, will-change 사용, position:absolute, fixed사용, 애니메이션 동작이 끝난 후 기본상태로 되돌리기
  • 아래의 최적화 점수 사이트에 측정해보고 약점 보완 제안을 적용하기

5. 최적화 점수 올리기

https://pagespeed.web.dev/?utm_source=psi&utm_medium=redirect&hl=ko
https://developer.chrome.com/docs/lighthouse/overview/
구글에서 제공하는 페이지 속도 측정 사이트에서 페이지의 최적화 점수를 알아내고 자신의 점수를 올려보도록 하자.

  • FCP (First Contentful Paint)
    사진출처
    • 페이지가 로드되기 시작한 시점부터 페이지의 콘텐츠의 일부가 렌더링될 때까지 걸린 시간
    • 전체 콘텐츠가 로딩되지 않아도 사용자는 소비할 수 있는 콘텐츠를 보게 되며, 로딩이 진행되고 있음을 인지하도록 한다.
    • 렌더링 되는 첫 요소는 대부분 텍스트 이므로 폰트용량을 줄이고(woff2 타입사용) FOUT 방식(기본폰트로 우선 텍스트가 표시되고, 다운로드 후 폰트 변경되어 적용, font-display: swap)으로 띄워준다.
    • https://web.dev/i18n/ko/fcp/
  • TTI (Time to Interactive)
    • 페이지가 완전히 상호작용할 준비를 마치기까지 걸린 시간(사용자가 어떤 이벤트를 발생시켜도 정상 동작하기까지의 시간)
    • Idle Window 시간 이내에 있는 Last Long-Task가 끝나는 시간을 측정한다.
      • Window = CPU Idle & Network Idle
        • CPU Idle = 메인 스레드에 작업이 없는 짧은 기간
        • Network Idle = 2개 이하의 네트워크 요청이 존재하는 기간
    • 웹에서의 상호작용은 자바스크립트를 통해 이뤄지므로, Last Long-Task가 끝이 나면 상호작용 준비가 되었다고 간주한다.
    • https://web.dev/tti/
  • TBT (Total Blocking Time)
    • 메인 쓰레드가 차단된 시간의 총합
    • FCP와 TTI 사이에서 메인쓰레드가 얼마나 차단되었는지 측정
    • TTI 만으로 측정 불가한 영역을 TBT가 채워주는 상호보완적인 측정지표이다.
      • ex) 51ms 작업 3개가 10초에 걸쳐 진행되는 상황과 10초짜리 통 작업 1개를 비교하면 TTI는 같지만 후자의 경우 TBT가 9950ms인 셈이다.
    • https://web.dev/tbt/
  • SI (Speed Index)
    • 페이지의 콘텐츠가 채워지는 속도
    • 성능 측정 툴은 페이지가 로드되는 과정을 프레임 단위로 캠쳐하고 시각적인 변화를 계산한다.
    • 시각적 변화가 안정되는 시점까지 걸린시간
  • LCP (Largest Contentful Paint)
    • 페이지 로드 시점부터 첫 화면 영역 내의 가장 큰 이미지나 텍스트 블록이 렌더링될 때까지의 시간
    • 페이지 로딩 스냅샷마다 화면 영역에서 가장 큰 블록(사진의 초록색 영역)을 찾아서 LCP의 시점을 조정한다.
    • 구글의 연구 결과로는 주요 콘텐츠 렌더링 시점보다 가장 큰 요소의 렌더링이 사용자 경험에 더 좋았기에 측정하는 점수 라고 한다.
    • https://web.dev/speed-index/
  • CLS (Cumulative Layout Shift)
    • 페이지의 수명 동안 발생하는 모든 예기치 않은 레이아웃 변화에 점수를 매겨서 측정
    • 페이지가 로딩되어 콘텐츠를 소비하는 중간에 광고 배너, API 호출 후 만들어진 DOM, 나중에 로드된 이미지 등이 공간을 차지하여 텍스트가 밀리거나, 레이아웃이 변경되는 것들이 좋지 않은 사용자 경험을 유발한다.
    • 따라서 CLS 지표를 두어 페이지 스냅샷마다 레이아웃이 얼마나 변경되었는지를 측정한다.
    • https://web.dev/cls/

6. 마치며

  • 렌더링 최적화를 위해서는 여러 조건들을 지켜야 하는것을 깨달았다. 이전에 state로 css에서 right나 margin 속성을 조절 하려고 했던 나를 반성했다.

  • styled-components의 작동방식이 문득 궁금해졌다. 찾아보니 선언해주는 컴포넌트 마다 스타일 템플릿을 만들고 랜덤한 문자열로 className을 만들어 해당하는 스타일을 적용 시키는 방식이라고 한다.

  • 이전에 만들었던 캐러셀에서 무의식적으로 transform transition 을 넣었던거 같은데 결과적으론 잘 적용시켰지만 이번 기회로 왜 transform을 적용시키는지를 깨닫게 되었던 것 같다.

참고자료
https://velog.io/@bumsu0211/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EB%A0%8C%EB%8D%94%EB%A7%81-%EA%B3%BC%EC%A0%95%EA%B3%BC-%EC%B5%9C%EC%A0%81%ED%99%94#5-browser-caching
https://www.youtube.com/watch?v=sJ14cWjrNis
https://im-designloper.tistory.com/100
https://wit.nts-corp.com/2017/06/05/4571

0개의 댓글