브라우저는 HTML을 파싱하고 파싱이 완료되면 domContentLoadedEvent가 시작됨.
Load Event는 HTML이 포함하고 있는 이미지등의 리소스가 모두 로딩되었을때 발생하는 이벤트.
브라우저는 웹 페이지를 로드할 때 다음과 같은 순서로 처리하게 됨.
HTML 파일을 읽기 시작.
HTML을 파싱하는 도중 <script>
, <link>
, <img>
등의 태그를 만나면 해당 리소스 (ex : JS, CSS, 이미지)의 로딩 및 실행을 시도.
외부 JavaScript 파일을 만나면 (이 파일이 async
나 defer
속성 없이 로드될 때 ) HTML 파싱을 일시 중지하고 JS 파일을 다운로드하고 실행함.
HTML의 모든 내용이 파싱되었을 때 ( 이때까지 외부 CSS파일이나 이미지가 반드시 로드될 필요는 없음. ) DOMContentLoaded
이벤트가 발생.
나머지 리소스 ( 이미지, CSS, 나중에 실행되는 JS 등 ) 가 로드 및 실행됨.
모든 리소스가 로드되면 load
이벤트가 발생함.
domContentLoadedEventStart
: HTML 문서의 파싱이 완료되고 DOMContentLoad
이벤트가 시작되는 시점을 나타냄
domContentLoadEventEnd
: DOMContentLoad
이벤트의 모든 리스너가 실행된 후의 시점을 나타냄.
즉, domContentLoadedEventStart
는 HTML이 완전히 파싱된 직후 발생하며, domContentLoadEventEnd
는 이 이벤트와 연관된 모든 JavaScript 코드가 실행된 직후 발생함.
loadEventStart
: load 이벤트가 시작되는 시점의 타임스탬프를 나타냄. 이 시점은 모든 리소스, 포함된 스타일, 이미지, JS 파일 등이 로드되고 실행된 후. 즉, 페이지와 관련된 모든 것이 완전히 로드되고 나서 이 이벤트가 시작됨.
loadEventEnd
: load 이벤트가 종료되는 시점의 타임스탬프를 나타냄. 이 시점은 load 이벤트에 연결된 모든 콜백 함수나 이벤트 리스너가 실행된 후.
브라우저 기준의 최적화라고 함은 이 2가지의 이벤트를 보다 시점을 앞당기고 빨리하는데 목표를 둠.
어떠한 웹페이지를 띄웠을 때 흰 화면이 3.88초정도가량 뜨고 그 후에 로딩바가 돌고 4.72초 동안 의미 있는 화면이 나오게 된다.
문제점
1. 흰 화면이 오래 띄워져있으므로 사용자 입장에서는 답답함을 느끼게 됨. (물론 개발자도... )
이것의 원인은?
위 그림을 보면 하단부에 1...2 이러한 부분이 있는데
HTML이 1번줄 부터 2번줄 부터 파싱되었다는 의미.
그리고 파싱을 멈추고 그 다음에 CSS와 JS를 파싱하고 있다는 뜻.
HTML 파싱을 멈추는 것을 블록 리소스 라고 함.
로딩바가 나와야하는데 이 블록 리소스 때문에 흰 화면이 계속 나오게 됨.
이러한 블록 리소스는 웹 페이지의 성능과 사용자 경험에 큰 영향을 줌.
특히, 모바일 환경이나 느린 네트워크에서는 더욱 두드러지게 됨.
따라서, 웹 개발자들은 블록 리소스의 영향을 최소화하기 위한 여러 최적화 기법을 사용하곤 함.
(ex: 스크립트에 async
나 defer
속성 사용, CSS를 문서의 헤드 부분에 배치)
1. 자바스크립트 로드 시점 최적화
위치변경 / async, defer
head 태그 내부에 script 태그가 포함되어있으면 블록 리소스 발생!
=> body 태그 하단에 위치 시키자!
그렇다면 이 script 태그를 만나기 전까지 위의 HTML은 모두 파싱이됨.
또는 head 태그에 두되 async 나 defer를 사용.
HTML을 파싱하다가 async를 만나게 되면 브라우저는 블록을 시키지 않고 계속 렌더링을 이어나감.
이렇게 처리를 하게 되었을때 Processing 속도의 차이는 아래와 같음.
2. 외부 CSS 스타일
번들 CSS 파일 처리시간이 758ms 인데 실제 다운로드 시간은 191ms에 불과함.
TTFB(Time To First Byte)
브라우저가 CSS 다운 요청을 하고 실제로 데이터의 첫 조각(Byte) 를 받는 데까지 걸리는 시간을 TTFB라고 함.
이를 해결하려면?
외부 CSS 파일을 인라인 스타일로 변경하자!
결과는 아래와 같음.
CRP는 웹 페이지가 브라우저에서 최초로 표시되기 위해 필요한 최소한의 단계와 작업을 나타냄. 즉, 웹 페이지가 가능한 한 빠르게 화면에 표시되기 위해서는 CRP를 최적화 해야함.
로딩 과정에서의 지연은 CRP에 의해 발생합니다. 페이지 로딩에 소요되는 시간은 대부분 CRP에서 발생하는 지연 때문입니다. 예를 들면, 스타일시트 로딩이나 JavaScript 실행이 페이지 렌더링을 차단할 수 있습니다.
CRP 최적화는 페이지 로딩 속도를 향상시킵니다. HTML, CSS, 및 JS 파일의 크기 줄이기, 스크립트의 비동기 로딩, 중요 스타일을 인라인으로 적용하는 것 등 여러 방법으로 CRP를 최적화할 수 있습니다.
사용자 경험 개선: CRP를 통해 웹 페이지의 "퍼셉션" 로딩 속도(사용자가 느끼는 로딩 속도)를 최적화하면 사용자에게 빠르게 페이지를 보여줄 수 있습니다.
로딩 성능 : 자바스크립트 최적화 (async, defer)
로딩 성능 : 인라인 스타일 적용 (Resource Timing : TTFB 줄이기)
빠른 DOMContentLoaded
빠른 로딩바
로딩바만 빠르게 뜸. 컨텐츠는 거의 동일하게 뜨게 됨.
First Meaningful Paint : 사용자에게 처음으로 의미 있는 것을 제공.
사용자 기준 최적화에서는 이 First Meaningful Paint 시간을 보다 앞당기는것에 초점을 두자.
요즘에는 SPA를 많이 사용하는데, 이러한 First Meaningful Paint 시간을 앞당기기 위해 SSR을 사용하기도 함.
서버 사이드 렌더링은 런타임 시점에 HTML, CSS 생성 후 브라우저에 응답
프리 렌더러는 빌드타임에 HTML을 생성.
프리 렌더러를 사용하면 기존에 4초가 걸렸던 First Meaningful Paint가 1초대로 줄어든 것을 확인할 수 있음.
First Meaningful Paint 가 브라우저 기준의 최적화보다 더 중요.
PWA 란 다음과 같은 특징을 가지는 웹 어플리케이션
오프라인 에서도 동작 : Service Workers라는 기술을 사용하여 네트워크 연결 없이도 동작할 수 있음.
홈 화면 추가 : 사용자는 PWA를 자신의 기기 홈 화면에 바로가기 아이콘으로 추가할 수 있음.
반응형 디자인 : 다양한 디바이스 크기와 해상도에 맞게 잘 동작
푸시 알림 : 웹 어플리케이션에서도 푸시 알림을 보낼 수 있음. 이를 통해 사용자의 참여와 재방문을 유도.
빠른로딩시간 : 최적화된 캐싱과 데이터 로딩 방식을 사용하여 빠른 로딩을 제공.
즉, PWA는 웹 어플리케이션을 마치 네이티브 모바일 앱처럼 느끼게 해주는 기술. 사용자는 앱스토어나 플레이스토어를 통해 별도의 설치 과정 없이 PWA를 사용할 수 있음.
사례 : BookMyShow 인도의 티켓팅 회사
강제 동기 레이아웃 (강제 리플로우)
웹 페이지 렌더링에서 피해야 하는 성능상의 문제점 중 하나.
웹 페이지 레이아웃은 다음과 같은 단계로 처리됨.
1. Style : 스타일 계산
2. Layout : 각 요소의 위치와 크기 계산
3. Paint : 요소의 외형을 그림
4. Compositie : 여러 계츠을 병합하여 최종 화면에 그림.
이런 단계 중 어떠한 스타일 변경이 레이아웃, 페인트, 또는 합성 단계에 영향을 줄 수 있음. 만약에 자바스크립트에서 스타일 변경을 수행한 후 바로 레이아웃 정보 ( ex : offsetHeight ) 를 조회하면, 브라우저는 최신의 레이아웃 상태를 보장하기 위해 레이아웃을 다시 계산해야함. 이것을 강제 동기 레이아웃 이라고 함.
이런 현상이 반복적으로 발생하면 웹 페이지의 성능에 큰 영향.
성능 최적화를 위해 강제 리플로우를 최소화 하는것이 중요. 스타일 변경을 일괄적으로 처리한 후, 레이아웃 정보를 조회하는 방법 등으로 이를 관리할 수 있음.
따라서! 강제 동기 레이아웃을 발생 시키는 코드는 한번만 쓰고 캐싱!
레이아웃 스래싱(Layout Thrashing) 은 강제 동기 레이아웃과 관련된 성능 문제를 나타내는 용어임.
레이아웃 스래싱은 웹 페이지에서 동일한 요소나 여러 요소에 대해 반복적으로 스타일을 변경하고 레이아웃 정보를 읽는 작업이 빈번하게 발생할 때, 브라우저가 불필요하게 여러 번 레이아웃을 계산하게 되는 현상.
스타일변경 => 레이아웃 정보 읽기 => 스타일 변경 => 레이아웃 정보 읽기 (...반복)
이러한 패턴 때문에 브라우저는 스타일 변경 후 바로 레이아웃 정보를 제공하기 위해 레이아웃을 재계산해야함. => 성능 저하
이를 방지하는 방법으로 스타일 변경과 레이아웃 정보 읽기를 분리.
예를 들어, 먼저 모든 스타일 변경을 한 번에 처리한 후, 레이아웃 정보를 읽는 작업을 수행하면 브라우저의 불필요한 레이아웃 계산을 줄일 수 있음.
가상돔 => DOM 변경을 최소화!
프레임 속도
빠른 렌더링을 달성하기 위해 보통 60FPS
60FPS = 16ms/fr => 브라우저 구동되는 시간 때문에 10ms/fr 정도로 끊어야 함.
무거운 작업을 하게 되면 프레임 누락 현상이 일어나게됨 => 렌더링 성능이 떨어짐.
메인스레드에서 오래걸리는 작업이 있따면 ? => 웹 워커로 작업을 옮기자!
워커가 무거운 작업을 담당!