웹사이트 최적화: 성능 개선

Seoyul Kim·2022년 1월 8일
0

Web

목록 보기
8/8

HTTP 요청 최소화

  • 웹사이트는 주로 마크업, 이미지, 스타일시트, 자바스크립트 등으로 구성되는데 이 요소는 모두 웹서버에 있으며, 사용자의 컴퓨터로 가져오는데 네트워크 비용이 들고 이 비용은 곧 응답시간으로 이어진다. 그렇기 때문에 다운로드해야하는 구성 요소의 개수를 줄이는 것이 가장 크고 효과적이다.

재사용 방문자를 위해 캐시 설정을 진행할 수도 있다.

파일 개수 최소화

  • 웹사이트의 성능을 개선할 때는 파일의 용량보다 개수가 더 중요하다. 아주 용량이 작은 파일이라도 원격 서버에서 가져와야한다면 네트워크 비용이 든다. 파일이 캐시에 있더라도 해당 파일이 유효한지 판단해야하며 병렬로 다운로드 하는데 한계가 있기 때문에 파일의 개수가 늘어나는 것은 성능에 치명적이다.

파일 크기 최소화

쿠키 크기 최소화

필요한 정보를 저장하는 가장 쉬운 방법이 최상위 도메인을 이용해 쿠키를 설정하는 것인데 이렇게 되면 자바스크립트 파일이나 스타일시트 파일, 이미지 등 쿠키 정보가 필요없는 구성 요소를 요청할 때도 헤더 정보에 쿠키가 포함되며 헤더를 전송할 때 데이터 크기가 커진다.

  1. 사용하지 않는 쿠키는 삭제하고, 2. 쿠키를 설정할 때 최상위 도메인은 되도록 사용하지 않는다. 3. 쿠키의 만료 날짜를 최대한 짧게 사용할 만큼만 설정한다. 4. 쿠키 정보가 필요 없는 이미지, 스타일시트, 자바스크립트 파일은 별도의 도메인으로 서비스하여 최상위 도메인이 같지 않으면 쿠키 정보가 공유되지 않는 점을 활용한다.

이미지 최적화

이미지 확장자별 특성을 파알하고 무분별한 압축이 아닌 경우에 따라 적절한 효율의 압축을 함으로써 이미지 손상을 줄이고 궁극적으로 트래픽 절감 및 빠른 로딩 속도를 구현해볼 수 있다.

이미지의 폭을 조절한다.

페이지에서 사용하는 이미지는 보통 가로폭이 1000px을 넘지 않으므로 사이즈가 큰 이미지가 있다면 폭을 조절하여 사이즈를 줄여준다.

최적화된 이미지 포맷을 사용한다.

많이 사용되는 JPG는 카메라로 찍은 실제 사진 이미지에서 최적화 되어있고, PNG 포맷은 만들어진 이미지일 경우 최적화 되어있다.

  • 이미지 특성에 따른 확장자

    1. PNG

      • 이미지에 포함되는 색상이 단순하며 flat 스타일이라면 png를 선택
      • 무손실 포맷으로서, 자체가 스크린 샷 등의 포터블한 이미지에 최적화된 포맷으로 화려한 색상이 담긴 이미지를 뽑아낼 경우 효율이 떨어지고 용량이 쉽게 증가한다.
      1. JPG
        • 이미지에 포함되는 색상이 많은 경우 JPG
        • 이미지에 들어가는 색상이 많은 경우엔 무손실 포맷인 PNG를 사용하면 모든 컬러 하나하나를 담아야하므로 이미지 용량이 급격하게 커진다.
        • 손실 포맷인 JPG를 사용하면 비슷한 색상끼리 엮는 식의 손실 압축을 통해 티는 나지 않지만 용량이 크게 줄어든다.
        • JPG는 손실 포맷의 특성에 따라 수정할 수록 화진이 열화되어 디지털 풍화가 이루어지므로 원본 수정파일을 두고 수정해야 화질 열화를 막을 수 있다.
    2. GIF

      • 투명도가 0 or 1로 단순한 경우, 알파값이 없는 투명이미지일 경우
        • 쓰인 색상이 256 미만이고 알파값이 없는 투명 이미지라면 gif가 png보다 용량을 더 적게 차지한다.
        • 한두가지의 색만 사용할 경우 gif 혹은 png-8 방식이 제일 효율적이다.

    picture, source, img 태그를 이용하여 지원하지 않는 포맷을 파일일 경우 특정 포맷의 파일을 이용하게 할 수 있다.

    <picture>
      <source srcset="image.avif" type="image/avif" />
      <source srcset="image.webp" type="image/webp" />
      <img src="image.jpeg" />
    </picture>

이미지 태그에 width, height값을 선언해서 reflow를 방지한다.

어떤 액션이나 이벤트에 의해 DOM요소의 크기나 위치 등을 변경하면 해당 노드의 하위 노드와 상위의 노드들을 포함하여 레이아웃 단계를 다시 수행하게 되는데, 변경하려는 요소의 위치와 크기 뿐만 아니라 연관된 요소들의 위치와 크기도 재계산을 하기 때문에 브라우저의 퍼포먼스를 저하시킨다.

치수가 없는 이미지들은 reflow를 발생시켜 퍼포먼스를 저하시키기 때문에 이미지 및 비디오 요소에 width와 height 속성을 항상 포함하거나 css를 사용하여 필요한 공간 aspect-ratio를 잡는다. 이렇게 사용하게 되면 이미지가 로드되는 동안 브라우저가 문서의 공간을 올바르게 할당할 수 있다.

반응형일 경우 css 를 사용하여 이미지의 크기를 조정하게 될 수 있는데, 단점은 다운로드가 시작되고 브라우저가 크기를 결정할 수 있는 경우에만 이미지를 위한 공간을 할당할 수 있다. 이미지가 로드되어 화면에 나타나면 reflow 되어 텍스트가 갑자기 화면 아래로 튀어나가는 등의 문제가 발생할 수 있는데 이를 방지하기 위해 aspect-ratio를 사용할 수 있다. 이 속상을 사용하면 복잡한 계산 없이 간단하게 속성으로 레이아웃 이동 방지를 할 수 있다.

여러 버전의 이미지를 제공한다.

여러 이미지 버전을 지정해서 브라우저에서 사용하기 가장 적합한 버전을 선택한다.

<img src="image.jpg" srcset="image-small.jpg 280w, image-large.jpg 1080w" sizes="50w>

브라우저가 srcset과 sizes 속성을 지원하지 않으면 fall back 으로 src 속성이 동작하기 때문에 src 속성은 모든 디바이스 크기에서 동작할 수 있을만큼 충분히 커야한다.

srcset 은 이미지 파일명과 width 또는 density 설명을 쉼표고 구분하며 브라우저에서 그기르르 결정하기 위해 이미지를 다운로드할 필요 없다.

size 속성은 이미지가 표시될 때의 너비를 브라우저에게 말해주지만 display 크기에 영항을 주지 않고 브라우저는 로드할 이미지를 결정하기 위해 유저의 디바이스 정보와 함께 size 속성의 정보를 사용한다.

더 많은 이미지를 제공하는 만큼 성능이 향상 되지만 서버에서 많은 공간을 차지하기 때문에 몇개의 버전을 제공할지는 잘 고려하도록 한다.

이미지 크기 조절 툴을 사용한다.

sharp npm package(이미지 크기 조절 자동화) 혹은 ImageMagick CLI tool(커맨드 라인을 이용한 일회성 이미지 크기 조절)이 있다.

Images CDN을 사용한다.

Image content delivery networks 로 전환하면 이미지 파일 크기를 40~80% 줄일 수 있다.

Image CDN이란 이미지 변환, 최적화 및 전송을 전문으로 하며 사이트에서 사용되는 이미지에 대한 접근이나 조작을 위한 API로 생각할 수 있다. Image CDN에서 로드된 이미지의 경우 URL은 이미지 뿐만 아니라 크기, 포맷, 품질 같은 매개변수도 제공하며 이를 통해 다양한 사용 사례에 대한 이미지를 쉽게 변형할 수 있다.

Image CDN이 사용하는 uri은 이미지 변형 및 최적화와 관련된 중요한 정보를 전송하는데, URL 포맷은 다음과 같다.

  • origin: 도메인
  • Image: 이미지 검색
  • Security key: 다른사람이 이미지의 새 버전을 만드는 것을 방지
  • Transformations: 다양한 이미지 변환 제공

lazy loading을 활용한다.

페이지를 로드할 때 모든 이미지를 로드하지 않고 중요하지 않은 자원 또는 당장 필요하지 않은 자원의 경우 서버에 요청을 미루고 필요한 경우 해당 자원을 요청받는다.

lazy loading 을 사용하면 데이터의 낭비를 막을 수 있고 브라우저의 렌더링 시간을 줄여준다.

  • 사용방법

    • img 태그 내의 속성을 사용한다. 단, 모던 부라우저가 아닐 경우 해당 속성은 무시된다.

      <img loading="lazy">

      loading의 속성은 auto(디폴트 값으로 속성값을 지정하지 않은 것과 동일), lazy(뷰포트 상에서 해당 이미지의 위치를 계산하여 이미지 지원을 요청한다.), eager(어느 위치에 있던지 이미지 자원을 바로 요청받음) 세가지의 값이 있다.

      해당 속성을 사용할 경우 되도록 해당 이미지 영역의 크기를 지정하는 것이 권장되는데, 영역의 크기에 대한 정보가 없으면 해당 영역의 크기를 알 수 없어 해당 영역을 0x0으로 인식하고 해당 이미지 영역으로 스크롤 할 경우 이미지가 로드 되며 layout shift가 일어날 수 있기 때문에 되도록 해당 img 태그에 명시적으로 높이/너비 값을 지정해야한다.

      페이지의 첫 시작부터 보이는 페이지 및 backgorund-image에서는 lazy loading을 사용하지 않도록 한다.

    • Intersection Observer ÅPI (*아래에서 자세히 설명)

      • 비동기적으로 사용자의 이벤트를 관찰하는 방법을 제공하는 웹 API로서 사용자가 웹 페이지를 스크롤 할 떄 어떤 element 이미지가 해당 뷰포트 내에 Intersection 되었는지를 판단할 수 있어서 해당 이미지가 교차되면 이미지를 로딩할 수 있도록 핸들링 한다.

        const io = new IntersectionObserver(callback[, optons])

이미지 용량 더 줄이기

포맷의 특성에 따라 이미지를 저장하지만 저장시 포함되는 메타 정보를 제거해 조금 더 줄일 수 있다.

  1. 이미지 자체의 불필요한 데이터 제거
  2. 무손실 압축
  3. 손실 압축
    • 무손실 압축을 해도 용량이 크게 줄어들지 않으면 손실 압축으로 용량을 줄일 수 있다. (https://tinypng.com/)

이미지의 종류와 특성

래스터 이미지: 우리가 사용하는 대부분의 이미지 유형이며, 각각의 픽셀들이 모여 하나의 큰 이미지를 완성한다. 정보를 담은 픽셀들을 추가해야만 컴퓨터그 정상으로 표현하며 확장성은 떨어진다.

백터 이미지: 좌표, 원, 사각형 등의 형상, 크기 등의 정보를 제공하여 컴퓨터가 그림을 그리듯 화면에 표현한다. SVG 파일이 W3C 표준 포맷으로 많이 사용한다. 메타 정보를 담고 있어서 화면에 따라 정보가 달라지지 않는다. 또한 화면 스케일에 상관 없이 선명한 이미지를 표현한다.

무손실 이미지 형식: 원본 이미지의 정보 손실을 허용하지 않는다.

손실 이미지 형식: 이동할 수 있는 형태를 만들기 위해 정보 손실을 허용한다. 손실 압축으로 이미지를 손실시켜 파일 크기를 줄이고 이미지 색이 비슷한 부분을 하나의 색으로 통일한다. 원하는 만큼의 화질을 얻지못할 수 있으므로 100~75% 사이의 품질을 권장한다.

GIF: 몇개 이미지를 묶어 움직임을 표현한다. 컬러(8bit)로 제한적이다.

PNG: 24 비트 색상을 사용 가능하며 고품질 이미지를 표현할 수 있고, 웹 사이트에는 알파 채널이라고 불리는 투명 기능 때문에 이미지의 백그라운드 투명도를 조절할 수 있다.

JPEG: 사진을 저장하는 표준 형식으로 사람의 눈이 인식할 수 있는 색상만 나믹고 나머지를 제거하는 방식의 기술로 고해상도 이미지를 크게 압축한 파일로 저장할 수 있다.

JPEG 2000: JPEG 단점을 보완하려고 개발 되었고, 새로운 방식으로 이미지 압축률을 높이고 무손실 압축 및 투명기능, 애니메이션 기능을 지원한다. 사파리를 제외한 대부분 브라우저에서 지원하지 않는다.

WebP: 손실 압축 방식을 사용하는 구글의 프로그램이다. JPEG 이미지 형식을 대체하기 위해 웹 사이트 트래픽 감소, 로딩 속도 단축을 목적으로 한다.

이미지 최적화를 통해 얻을 수 있는 이점

  1. 웹 페이지 바이트 절약을 통해 사이트의 성능을 향상할 수 있다.
  2. 브라우저가 다운로드 해야하는 바이트가 줄어들어 클라이언트의 대역폭에 여유가 생긴다.
  3. 컨텐츠를 더 빨리 다운로드 하여 화면에 렌더링하기 때문에 최적의 사용자 경험을 제공할 수 있다.
  4. 서버 저장공간이 적게 필요하기 때문에 비용이 절감된다.
  5. seo 순위를 결정할 때 모바일 응답성을 고려하여 검색 순위에 노출되는데, 이미지 최적화를 통해서 모바일 응답성을 빠르게 한다면 검색 결과의 상위권에 노출될 수 있다.

렌더링 성능 향상

초기 렌더링시 Ajax 요청 최소화

초기 렌더링시에 Ajax 통신으로 받은 데이러를 화면에 그리게 되면 렌더링이 끝난 후 데이터를 받아 다사ㅣ 화면에 그리므로 체감 속도를 느리게 한다. 초기 렌더링 시에 마크업 전체를 서버에서 보내는 방식으로 개발하면 체감 속도를 높일 수 있고 그 후 사용자의 행동이 있을 때 Ajax 요청을 실행해서 데이터를 받은 다음 화면을 그리게한다.

CDN 사용

CDN은 사용자에게 효울적으로 컨텐츠를 제공하기 위해 여러 지역에 걸쳐 분산된 우베 서버의 집합체로 사용자가 요청했을 때 고객의 네트워크에서 가장 가까운 서버를 측정하여 선택하기 때문에 가장 빠른 응답시간의 서버가 선택된다.

마크업 최적화

마크업 최적화의 목표는 빈 페이지가 한참 있다가 전체 화면이 한꺼번에 나타나는 것이 아니라 영역별로 차츰 렌더링 하게 하는 것이다.

특히 인터넷 익스플로러에서는

태그를 렌더링할 떄 표 안에 이쓴ㄴ 텍스트와 이미지 ㅡㄷㅇ을 모두 파싱할 때까지 화면 표를 그리지 않는다. 반면 파이어폭스에서는 해당 태그가 모두 완료되기 전에 표 안에 있는 각 요소가 보이기 때문에 부분적인 렌더링이 가능하다.

또한 태그의 중첩을 최소화 하는 것이 좋다. 전체 태그 개수를 줄이는 것도 중요하지만 중첩된 태그를 최소로 하는 것이 더 중요하다. 전체적으로는 태그의 개수를 줄이고 부분적으로는 중첩된 태그를 최소화해 간결하게 디자인하는 것이 렌더링 속도를 높이는 방법이다.


IntersectionObserver

  • callback: 타겟 element가 교차되었을 때 실행할 함수로 entries(IntersectionObserverEntry 객체의 리스트로 배열 형식으로 반환하기 떄문에 forEach를 사용해서 처리한다.), observer(콜백 함수가 호출되는 IntersectionObserver)를 parameter로 받는다.

    IntersectionObserver의 callback 함수를 통해 생성된 객체의 배열의 속성은 다음과 같다.

    • boundingClientRect: 타겟 엘리먼트의 정보를 반환
    • rootBounds: root 엘리먼트의 정보를 반환합니다.(root를 선언하지 않았을 경우 null)
    • intersectionRect: 교차된 영역의 정보를 반환
    • intersectionRatio: IntersectionObserver 생성자의 options의 threshold와 비슷하고 교차 영역에 타겟 엘리먼트가 얼마나 교차되어 있는지(비율)에 대한 정보를 반환한다. (threshold와 같이 0.0부터 1.0 사이의 값을 반환)
    • isIntersecting: 타겟 엘리먼트가 교차 영역에 있는 동안 true를 반환하고, 그 외의 경우 false를 반환한다.
    • target: 타겟 엘리먼트를 반환
    • time: 교차가 기록된 시간을 반환
  • options

    • root: 브라우저의 viewport로 default 는 null dlek.
    • rootMargin: root element의 margin 값으로 default 는 "0px 0px 0px 0px"이며 rootMargin 값에 따라 교차 영역이 확장 또는 축소된다.
    • threshold: default 값은 0으로 0.0부터 1.0사이의 숫자 혹은 이 숫자들로 이루어진 배열로 타겟 element에 대한 교차 영역 비율을 뜻한다. 0.0은 타켓 element가 교차 영역에 진입했을 시점에 observer를 실행하는 것을 의미하고 1.0의 경우 타켓 element 전체가 교차 영역에 들어왔을 때 obsrver를 실행하는 것을 의미한다.

0개의 댓글