얼마전 면접을 봤는데 웹 성능 최적화에 대해 질문이 있었다. 비록 면접은 탈탈 털렸지만 실패를 딛고 재정비 하자!

웹 성능이란?

웹사이트의 콘텐츠가 신속하게 전달되어 사용자가 원하는 서비스를 빠르게 전달받을 수 있도록 하는 시스템들의 성능을 말한다.

웹 성능 최적화란?

웹 성능 최적화란? 말 그대로 웹 사이트를 사용자에게 빠르게 보여주기 위해 웹 사이트를 효율적으로 동작하게 하는 작업이다. 웹 성능 최적화가 우리에게 미치는 영향은 크다.

웹 성능 최적화를 하는 이유

웹 성능 최적화를 통해 비지니스 효과를 볼 수 있다. 예시로 핀터레스트는 사용성 개선으로 인해 매출이 44% 증가 했다고 한다. 그리고 굳이 비지니스 측면이 아니더라도 사용자 UX에도 많은 영향을 끼친다. 우리가 어떤 사이트를 들어갔는데 빈 화면, 혹은 로딩이 3초 이상이 걸리면 느리다고 생각이 든다. 조사에 따르면 사용자의 관심을 3초 안에 끌어야 사이트 이탈률을 줄일 수 있다고 한다. 21년 5월부터는 구글 검색 순위에도 영향을 미친다고 하니 얼마나 중요한가?

웹 성능에 영향을 주는 요소들

웹 성능에 영향을 주는 요소들은 다향하지만 크게 사용자의 환경, 전달 환경, 공급자의 환경으로 나눌 수 있다. 사용자가 와이파이를 사용하는지, LTE 서비스를 사용하는지에 따라 사용자의 환경이 달라진다. 전달 환경은 단독 서버를 사용하는지, 유선망과 모바일망 각각의 서버를 배포했는지에 따라서 동일한 컨텐츠를 전달할 때 품질이 달라진다. 공급자의 환경에는 웹사이트의 백엔드 처리 속도, 웹서버 응답 속도, 프론트엔드의 최적화 여부가 영향을 끼친다.

프론트엔드에서 웹 성능을 최적화 할 수 있는 방법

  1. HTTP요청을 줄인다.
  2. 스타일 시트는 상단에, JS는 하단에 넣는다.
  3. CSS 표현식은 피한다.
  4. JS와 CSS는 외부 파일에 넣는다.
  5. JS는 작게 하고 중복 스크립트를 제거한다.
  6. 콘텐츠 전송 네트워크(CDN)를 사용한다.
  7. AJAX는 캐시가 가능하게 한다.
  8. GET 메소드로 XHR을 사용한다.
  9. DOM 개체 수를 줄인다.
  10. 404 Not found를 없앤다.
  11. 쿠키 크기를 줄이고 쿠키와 상관 없는 정적 콘텐츠를 만든다.
  12. HTML에 이미지 크기를 설정하지 않는다.
  13. 파비콘은 작게, 캐시할 수 있게 한다.
  14. AlphaImageLoader를 사용하지 않는다.

적용하기

실제 내가 예전에 진행했던 프로젝트를 가지고 웹 최적화를 해보았다.

테스트한 페이지

웹 성능 요약 WPT 웹 성능 요약 LH

이미지가 많은 목록형 페이지여서 이미지 관련 개선점이 많이보였다. 이미지 컴포넌트에 loading 속성과 width, height 속성을 추가해주었다.

// CocktailCard.tsx

  <img 
    className='card-img' 
    src={strDrinkThumb}
    alt={strDrink}
    loading='lazy'
    width={imgWidth}
    height={imgHeight}
  />
// imgCache.ts
// 이미지 url에 시간을 붙여 캐싱을 해주는  유틸 함수를 만들어 데이터를 가공해 사용해주었다.

export const imgCache = (data: ICocktailData[]) => {
  const imgCacheData = data.map(drink => ({ ...drink, strDrinkThumb: `${drink.strDrinkThumb}?${new Date().getTime()}` }))
  return imgCacheData
}

웹 성능 요약 LH - 와 나 라이트하우스 100점 처음본다~~

세상에 LightHouse 성능 요약 점수에서 올백을 맞았다. 이미지 캐싱 말고 http 캐싱을 통해서도 성능을 높일 수 있다. 참고

더 자세하게 나오는 WebPageTest도 확인을 해보자 웹 성능 요약 LH - 와 나 라이트하우스 100점 처음본다~~

아직 LCP(핵심 요소의 콘텐츠 로딩 속도)에서는 크게 성능을 올리지 못했지만, CLS(페이지 방문자의 시각적인 안정성)에서 시간을 많이 줄일수 있었다. 하지만 LCP는 사용자가 접하는 가장 중요한 첫 요소의 성능 측정인 만큼 해당 영역이 느리게 나타나면 다른게 다 빨라도 성능이 좋아보이지 않는다. 게다가 LCP는 Core Web Vital의 중요한 지표로 다루고 있기도 하다. 그러면 LCP는 어떻게 성능을 올릴 수 있을까?

웹 성능 요약 WPT

WebPageTest에서는 가장 핵심 요소 컨텐츠를 header의 div로 잡았다. 그러면 이 header가 핵심 요소로 뽑혔을까? 이유는 LCP의 이름에 있다. 구글에서 연구한 결과, 페이지의 가장 유의미한 컨텐츠의 로딩 시간을 파악하는 방법은 페이지에서 가장 큰 요소의 로딩 시간을 체크하는것이 이라고 한다. LCP는 Largest Contentful Paint의 약자이다. WebPageTest 에서는 필자의 페이지 중 가장 큰 컨텐츠가 header라고 판단한 것이다. 그러면 LCP의 성능을 높이려면 어떤 방법이 있을까?

LCP가 고려하는 요소들

  1. 이미지 태그(svg, img, vidio… HTML tag)
  2. css 에서 URL로 불러오는 이미지
  3. 기타 다른 텍스트 블록들
    1. css를 통한 모든 요소들의 여백은 고려되지 않는다.

LCP 개선하기

LCP의 성능이 떨어지는 이유는 4가지이다 LCP는 주로 4가지 요인에 의해 영향을 받습니다.

  • 느린 서버 응답 시간
  • 렌더링 차단 JavaScript 및 CSS
  • 리소스 로드 시간
  • 클라이언트 측 렌더링
느린 서버 응답시간

느린 서버의 응답시간을 단축시키기 위해서는 서버의 최적화가 필요하다. 무거운 쿼리를 돌리거나 복잡한 동작이 있다면 효율성이 좋은 코드로 바꾸는 것이 좋다.

렌더링 차단 JavaScript 및 CSS

브라우저가 페이지를 렌더링 렌더트리가 만들어져야 한다. 렌더트리는 DOM트리와 CSSOM트리가 필요하다. DOM트리는 파싱중에 HTML 태그를 만나면 순서대로 트리를 그려나가지만, CSSOM트리는 CSS를 모두 해석해야만 트리를 그릴 수 있다. 하려면 HTML을 파싱해서 렌더 돔트리를 만들어야 돔을 빌드해야한다. 하지만 JS나, CSS를 발견할 때마다 파싱을 중지하고 스크립트를 실행하는데 이것이 HTML의 렌더링을 지연시킨다. 렌더링이 차단 되는 것을 막으려면 적절한 미디어쿼리 사용이나, 스타일시트의 위치 조정이 필요하다. 또 차단을 유발하는 소스를 압축 (map) 하는 것도 방법이 될 수 있겠다.

웹 성능 요약 WPT

내가 만든 페이지의 성능 분석표에도 나와있는 css blocking! 내가 외부에서 가지고 오는 글꼴이 블록킹을 유발하고 있었다. 그래서 폰트를 url에서 인라인으로 변경시켜주었다.

reference