Jun 개발노트

웹 성능 최적화 - 리소스

2022-02-06

왜 작성해야 하는가?

  • 프론트엔드 개발자을 위한, 실전 웹 성능 최적화(링크)를 보고...
  • 웹성능은 정말로 중요하기 때문이다. (월마트는 1초 개선해서 매출 2% 증가)
  • 회사 프로젝트 lighthouse 점수를 1점이라도 올리기 위해...

TL;DR

1. 이미지, 동영상

  • 문제 : 리소스(이미지, 동영상)를 다운받는데 시간과 리소스가 걸린다.
  • 해결방법 : 손실없이 압축해서 보내자 (WebP, WebM => web에 최적화된 포맷)

2. 폰트

  • 문제
    • 폰트를 다운받는다 -> 적용하는데 시간이 걸린다 (UX 좋지 않음)
    • CSSOM를 만들때, 해당 폰트가 없다면, 다운로드가 완료될때가지 렌더링 차단(Render Tree 생성 중단 ㅠㅠ)
      • 폰트는 렌더링 차단 리소스(물론, HTML, CSS, JS 또한 렌더링 차단 리소스)
  • 해결방법 - 폰트의 적용시점을 바꾸자(FOUT / FOIT) - 폰트의 사이즈를 줄이자(WOFF2)

이미지 최적화

  • 문제 : 이미지 다운로드 -> 용량(사이즈)이 크다 -> 네트워크 리소스 소모
  • 해결방법
    1. 콘텐츠 사이즈에 맞게 이미지 사이즈를 줄이자 (단, 레티나 디스플레이를 대비해서 (ex. 300 x 300 ⇒ 600 x 600)으로 줄이자)
    2. 이미지 포멧을 변경하자(파일크기 : PNG > JPG > WEBP, 같은 이미지 경우) webp 비교
    3. webp를 지원하지 않는 브라우저도 있을수 있기 때문에, <picture> <source>태그를 활용하자
      • 지원하는 type(포맷)에 맞쳐 브라우저가 노출된다.
      function App() {
            return (
              <div>
                <picture>
                  <source srcSet={webpSrc} type="image/webp"/>
                  <img src={jpgSrc} alt="img"/>
                </picture>
              </div>
            );
      }
      

동영상 최적화

  • 문제 : 이미지 사이즈 문제와 동일
  • 해결방법 : 동영상 압축하자(압축사이트)
    • 압축하기전,(중요!!) 압축 비율은 콘텐츠의 성향에 따라 디자이너와 논의하면 좋을것 같다(이미지 화질 영향)
    • webm(web 최적포멧)를 지원하지 않는 브라우저도 있을수 있기 때문에, <video> <source>태그를 활용하자
      • 지원하는 type(포맷)에 맞쳐 브라우저가 노출된다.(이미지와 동일)
      function App() {
                return (
                  <div>
                    <video autoPlay muted>
                      <source src={earthWebM} type="video/webm"/>
                      <source src={earthMp4} type="video/mp4"/>
                    </video>
                  </div>
                );
          }
      

폰트 최적화

1. 폰트 적용 시점 컨트롤러

  • FOUT(Flash of Unstyled Text) : 기본폰트 → 다운로드 완료 → 폰트 적용(깜빡임)
    • IE / Edge 웹폰트 적용 방식
  • FOIT(Flash of Invisible Text) : 폰트를 완전히 다운로드 되기 전까지 보이지 않음
    • Chrome / Safari 웹폰트 적용 방식
  • font-display 속성을 가지고 폰트 적용시점 컨트롤러
    font-display: auto; // 브라우저 방식을 따름
    font-display: block; // FOIT (default 3s가 지나면 시스템 폰트 노출 후 swap 형태로 변경)
    font-display: swap; // FOUT
    font-display: fallback; // default 3s가 지나면 시스템 폰트로 계속해서 사용 => 캐시
    font-display: optional; // fallback가 차이점(font-download 우선순위를 낮춘거나 중단)
    

2. 폰트 사이즈 줄이기

  1. Format에 따른 파일 크기 (EOT > TTF/OTF > WOFF > WOFF2) 브라우저별 폰트 포맷 지원 포맷별 사이즈

  2. src 순서에 따라 우선순위 적용

    @font-face {
        font-family: NanumSqureWeb,
        src: local('NanumSqureWeb'), // 로컬폰트(클라이언트 컴퓨터)
                 url(NanumSquareR.woff2) format('woff2'),
                 url(NanumSquareR.woff) format('woff'),
                 url(NanumSquareR.ttf) format('truetype');
    }
    
  • subset font : font파일에서 필요한 글자들만 가져오자 (사이트 : Transfonter)

  • unicode-range : 지정된 글자가 있다면 폰트를 다운로드 하고, 안하면 다운로드 하지 않는다.(trigger)

    @font-face {
        font-family: NanumSqureWeb,
      src: url(NanumSquareR.woff2) format('woff2');
        unicode-range: 적용할 글자의 유니코드의 값이나 범위 예) u+0041; << A의 유니코드
    }
    
  • data-url 로 변경하자

    • font를 파일로 저장하지 않는다(별도의 네트워크 리소스 X)
    • base 64기반으로 data-url로 바꿔서 이용한다. (사이트 : Transfonter)
  • preload 옵션 사용하기(React)

    • 특정 리소스(Style, Script, Video, font 등) 미리 다운로드를 실행하게 한다.
      • 적용 전
        • JS를 다운받고, font파일을 다운로드 하기 시작한다. before-preload
      • 적용 후
        • 그전보다 빠르게 font파일을 다운로드 하기 시작한다.
      <link rel="preload" href="https://fonts.gstatic.com/s/notosanskr/v25/Pby7FmXiEBPT4ITbgNA5CgmOelzI7bgWsWdx3Ch_M9uykRdOOoSdBjU92zqHxA.0.woff2" as="font" type="font/woff2" crossorigin="anonymous">
      
      after-preload

참고