NHN Forward [2018] 프런트엔드 성능 최적화 강연 정리

낙서·2021년 8월 27일

NHN Forward 기술 컨퍼런스 [2018] 프런트엔드 성능 최적화 강연 정리 - 유동식

강연 링크: https://www.youtube.com/watch?v=G1IWq2blu8c

강연 요약

  • 프론트엔드 성능 최적화 = 리소스 로딩 최적화 + 렌더링 최적화
  • 리소스 로딩 최적화
    • 로딩 성능 최적화: 브라우저 기준
      • DOMContentLoaded 시간 단축
        • 방법1 : 자바스크립트 async, defer 사용
        • 방법2 : 인라인 스타일 사용
        • DOMContentLoaded는 이미지 등 다른 리소스 로드를 포함하지 않기 때문에 성능 변화 체감이 덜 할 수 있음 → 사용자 기준의 최적화가 더 중요
    • 로딩 성능 최적화: 사용자 기준
      • 사용자에게 의미있는 콘텐츠를 로딩하는 순간(FMP)을 앞당김으로 사용자 기준 로딩 최적화
      • 방법1 : 서버 사이드 렌더링
      • 방법2 : 프리 렌더링 → Webpack을 bundler로 사용 시 prerender-loader 사용
    • 로딩 성능 최적화: PWA 사용
      • PWA: 웹이 앱과 같은 성능을 낼 수 있도록하는 개발 패턴, 초기 로딩 시 불필요 한 것들은 제거를 하고 뒤로 이동시켜서 로딩 성능을 끌어 올림
      • PWA 앱 사용시 안드로이드, iOS 앱보다 앱 사이즈가 수십배 이상 감소, 로딩 타임 감소
  • 렌더링 최적화
    • 레이아웃 스래싱 줄이기
      • 방법1 : DOM element를 읽는 것을 캐싱으로 줄여 layout 과정 발생 빈도를 감소시킴
    • 가상 돔
      • 가상돔 사용으로 특정 엘리먼트만 부분적으로 변경 → 불필요 DOM 변경 최소화
    • 웹 워커 사용
      • 무거운 작업을 웹 워커로 옮겨서 렌더링 성능 개선 (성능 많이 개선 가능)
      • 방법1 : 웹팩에서 worker-loader 사용으로 웹 워커 사용

강연 정리 노트
프론트엔드 성능 최적화 설명

  • 프론트엔드 성능 최적화 = 리소스 로딩 최적화 + 렌더링 최적화
  • 리소스를 빠르게 로드하고 렌더링(화면에 표시)을 부드럽게 하는 것이 중요
  • 예전 웹사이트들에 비해 현대 웹사이트는 UI가 복잡 화려해지고 기능도 많아짐 → 성능 문제 발생 (속도)
  • 소비자 입장에서 긴 로딩 시간은 서비스 이용 불편함을 느끼게 할 수 있음
  • 성능 개선 기대 효과 → 빠른 로딩 속도, 사업지표 향상, 사용성 개선
  • 성능 최적화 성공 사례: Pinterest → 기존 로딩 속도 23초로 느렸음 → 3개월 동안 성능 최적화 작업 → 사용자 서비스 이용시간 증가, 매출 44% 증가, 클릭 수 +50% 증가

로딩 최적화: 브라우저

  • 브라우저는 HTML을 parsing(분석) 함 → HTML 분석 완료 후, domContentLoadedEvent 이벤트 발생 → domContentLoadedEvent 완료 후, loadEvent 이벤트 발생

  • 순서: HTML parsing → domContentLoadedEvent → loadEvent

  • domContentLoadedEvent: HTML 문서를 완전히 불러오고 분석했을 때 발생하는 이벤트 (스타일 시트, 이미지 등의 로딩은 포함 안됨)

  • loadEvent: HTML이 포함하고 있는 자바스크립트, 스타일 시트, 이미지 등 리소스까지 모두 로드되었을 때 발생하는 이벤트

  • 브라우저 로딩 최적화는 이 2가지 이벤트 시점을 앞당기고 빠르게 하는 것이 목표 (domContentLoadedEvent, loadEvent)

  • 로딩 과정에서 흰 화면이 지속되면 답답함을 줄 수 있음

  • 브라우저는 HTML, CSS, JavaScript를 각각 파싱

  • HTML 파싱을 하다가 CSS를 만나면 HTML 파싱을 멈추고 CSS, JavaScript 파싱을 수행

  • HTML 파싱을 멈추는 이 CSS, JavaScript 리소스들을 '블록 리소스' 라고 부름

  • 블록 리소스 때문에 HTML 파싱을 멈춰서 브라우저에 계속 흰 화면이 나오는 것

  • 브라우저 렌더링 과정: HTML 파싱해서 DOM Tree를 만듦 + 스타일 정보 파싱해서 CSSOM Tree를 만듦 → DOM Tree, CSSOM Tree 이 두 Tree로 Render Tree를 만듦 → Render Tree를 가지고 layout 과정을 거치게 됨 (layout 과정: 각 요소들의 위치와 크기를 계산하는 과정) → painting 과정(화면에 뿌려주는 과정)

  • 블록 리소스: 자바스크립트, 스타일

  • 흰 화면 지속 시간을 줄이기 위해 블록 리소스 처리 최적화 필요

  • 블록 리소스 처리 최적화 = 자바스크립트 로드 시점 최적화 + 스타일 로드 시점 최적화

  • 자바스크릡트 로드 시점 최적화

  • script 태그는 자바스크립트를 실행함으로 HTML 파싱을 잠시 멈추는 블록 리소스 임

  • script 태그가 head 태그에 있으면 밑에 있는 HTML들은 파싱되기도 전에 파싱을 잠시 멈춤 → 흰 화면 지속 → 이러한 상황을 방지하기 위해 script 태그를 보통 body 태그 하단에 위치시킴, 혹은 head 태그에 위치시키면서 script 태그에 async나 defer를 사용

  • 브라우저는 HTML 파싱 중 async를 만나면 블록을 시키지 않고 HTML 파싱을 지속함 → async를 사용하면 HTML 파싱이 블록되지 않기 때문에 DOMContentLoaded 시간을 단축시킬 수 있음

  • 스타일 로드 시점 최적화

  • 브라우저가 CSS 다운로드 요청(Request sent)을 하고 다운로드를 하기까지 Waiting 시간이 있음(TTFB: 첫 바이트를 받아서 처리하기까지 걸리는 시간) → 요청 후 waiting 시간을 줄임으로 최적화

  • Waiting 시간 개선 방법 → HTML 파일에 스타일을 inline으로 직접 포함 시킴 (CSS 다운로드 요청 줄임으로써 Waiting 타임을 없앨 수 있음) → DOMContentLoaded 시간을 단축시킬 수 있음

  • 요약

  • 브라우저 로딩 최적화 방법은 DOMContentLoaded 단축

  • 방법1: 자바스크립트 async, defer 사용

  • 방법2: 인라인 스타일 사용

  • 브라우저 로딩 최적화 한계점: DOMContentLoaded 를 앞당겨도 DOMContentLoaded는 이미지 등 다른 리소스 로드를 포함하지 않기 때문에 크게 성능 변화를 느끼지 못 할 수 있음 → 따라서 사용자 기준의 최적화가 더 중요

로딩 최적화: 사용자 기준

  • 사용자 기준 로딩 최적화의 핵심은 First Meaningful Paint 시점을 앞당기는 것

  • First Paint: 빈 화면에 처음으로 무언가 그려지는 순간

  • First Contentful Paint: 처음으로 텍스트나 이미지가 표현되는 순간

  • First Meaningful Paint: 처음으로 사용자에게 의미있는 콘텐츠를 로딩하는 순간 (의미있는 콘텐츠 기준은 아직 모호, 개발자 주관적 기준)

  • Time to interactive: 모든 리소스가 로딩되서 사용자와 인터렉션 할 수 있는 순간

  • SPA(React, Vue, Angular frameworks)에서 First Meaningful Paint 시점을 앞당기는 방법 → 서버 사이드 렌더링, 프리 렌더링

  • 서버 사이드 렌더링, 프리 렌더링 방식 모두 First Meaningful Paint를 하기 위해 HTML, CSS 를 생성

  • 프리 렌더링: 빌드 타임에 HTML, CSS를 생성

  • 서버 사이드 렌더링 방식의 HTML, CSS 생성 시점 → 서버 런타임 (서버 쪽에 요청 온 시점)

  • 프리 렌더링 방식의 HTML, CSS 생성 시점 → 소스 빌드 타임

  • Webpack을 번들러로 사용한다면 Webpack에서 프리 렌더링 방식을 적용 할 수 있는 도구: prerender-loader

  • prerender-loader 사용시 빌드 타임에 컨텐츠를 만들어 내서 First Meaningful Paint를 앞 당길 수 있음

  • DomContentLoad 완료되기 전 paint를 할 수 있음 → HTML 컨텐츠가 약간 늘어나지만 훨씬 효과적

  • 사용자 기준에서 의미 있는 First Meaningful Paint 시점을 앞 당겼다면 DOMContentLoaded 속도는 덜 중요 할 수 있음

  • 요약

  • 사용자에게 의미있는 콘텐츠를 로딩하는 순간을 앞당기는 것으로 사용자 기준 로딩 최적화를 할 수 있다

  • 방법1 : 서버 사이드 렌더링

  • 방법2 : 프리 렌더링 → Webpack을 bundler로 사용 시 prerender-loader 사용

로딩 성능 최적화: PWA

  • PWA: 웹이 앱과 같은 성능을 낼 수 있도록하는 개발 패턴
  • PWA에서 로딩 성능 최적화 방법 → 블록 리소스 처리 최적화(자바스크립트, 스타일 로드 시점 최적화)
  • PWA 빠른 로딩 속도: 초기 로딩에서 불필요 한 것들은 제거를 하고 뒤로 이동시켜서 로딩 성능을 끌어 올림
  • PWA 앱 사용시 안드로이드, iOS 앱보다 앱사이즈가 수십배 이상 비약적으로 줄어듦, 로딩 타임 줄어듦 → 사업지표 향상

렌더링 최적화: 레이아웃 스래싱 줄이기

  • Layout 과정: HTML, CSS를 파싱해서 요소의 위치 크기를 계산하는 작업, 비용이 상대적으로 크고 오래걸림

  • Paint 과정: 화면에 뿌리는 작업

  • 자바스크립트 DOM 조작 시 변경사항이 생겼음으로 Layout → Paint 과정이 다시 발생

  • 강제 동기 레이아웃: DOM을 변경하지 않았음에도 Layout → Paint 과정을 발생시킴

  • 어떠한 DOM Element는 읽기만해도 강제 동기 레이아웃 과정이 발생 (예: let offsetLeft = this.element.offsetLeft;) → 이러한 DOM을 읽을 때마다 Layout 과정 발생이 빈번히 발생 → 캐싱으로 개선 시 강제 동기 레이아웃 발생을 줄여 성능 많이 개선됨

  • 강제 동기 레이아웃이 매우 빈번하게 발생 하는 것을 레이아웃 스래싱이라고 함 → 렌더링 성능을 많이 떨어트리는 원인

  • 요약

  • DOM element를 읽는 것을 캐싱으로 줄여서 레이아웃 과정 발생 빈도를 줄이자

렌더링 최적화: 가상돔

  • 가상돔 사용으로 특정 엘리먼트만 부분적으로 변경 → 불필요 DOM 변경 최소화

렌더링 최적화: 웹 워커

  • 무거운 작업을 웹 워커로 옮겨서 성능 개선
  • 웹팩에서 worker-loader 사용으로 웹 워커 사용
  • 무거운 작업이 있다면 워커 스레드 사용으로 비약적 성능 개선 가능
profile
Deprecated

0개의 댓글