이미지 크기에 따른 렌더링 최적화 기법 소개

ChoiYongHyeun·2024년 12월 11일
2

프로그래밍 공부

목록 보기
18/18

이미지가 브라우저에 렌더링 되기 까지의 흐름

브라우저는 화면을 렌더링 하던 중 <img src = {어떤 주소}> 태그를 만나게 되면 명시된 주소로 비동기적으로 HTTP 요청을 보내 이미지 파일을 응답 받는다.

이 때 주고 받는 이미지 파일은 정말 우리 눈에 보이는 이미지 파일 자체가 아니라 RGB 채널의 이진수들로 구성된 데이터이다.

HTTP/1.1 200 OK
Content-Type: image/jpeg
Content-Length: 102345

(binary image data here)

다음과 같은 이미지 태그에 대한 응답을 받게 되었다면 브라우저는 Content-Type 에 명시된 이미지 파일의 타입에 맞춰 텍스트 데이터를 적절하게 브라우저에 페인트 한다.

이미지 크기가 크면 렌더링 속도가 왜 느려질까 ?

브라우저에 도착하기까지의 시간

이더넷을 사용하는 HTTP 통신에서 평균적으로 하나의 패킷이 담을 수 있는 데이터의 용량은 1.5KB 정도 된다. [1]

이미지의 크기가 커져 이미지 파일의 byte, 즉 Content-Length 가 커질 수록 받아야 하는 패킷의 수가 늘어나기에 네트워크 요청 시간이 길어질 수 밖에 없다.

TCP 통신을 이용하는 브라우저 HTTP 특성 상 패킷이 많아 질 수록 유실 될 패킷의 수가 늘어날 가능성이 있고 그럴 수록 재전송이 걸리는 시간도 유의미하게 길어지기 때문이다.

브라우저에 도착 한 후 페인트 까지 걸리는 시간

  • 이진수 데이터로 된 이미지가 브라우저에 도달 했다고 가정해보자. 이미지 크기가 크다는 것은 디코딩 해야 할 이진수 데이터가 많다는 것을 의미한다.

  • 제한적인 브라우저 메모리에서 용량이 큰 이미지를 렌더링 하는 것은 이미지 렌더링 뿐 아니라 전체적인 브라우저 성능에 영향을 미칠 수 있다.

  • 브라우저에선 원본 이미지를 원본 이미지 크기에 맞춰 렌더링 하는 일이 적다. 따라서 원본 크기의 이미지를 브라우저 상에서 렌더링 할 이미지의 크기로 변환하는 과정이 필요하다.

이처럼 이미지 크기가 렌더링 성능에 미치는 영향들이 존재 한다. 그렇다면 렌더링 성능 향상을 위한 방법들을 알아보자

브라우저에 도착하기 까지의 시간을 줄이는 방법

이미지 크기 압축

가장 단순한 솔루션이면서 효과가 좋은 방법으로 이미지 크기를 줄이는 것이다.

위에서 언급했듯 브라우저에선 이미지를 대부분 원본 크기에 맞춰 렌더링 하지 않는다.

위 이미지는 실제 크기가 약 4000 x 3000 쯤 되는 4K 이미지이다.

저희 집 고양이 귀엽죠

하지만 기기에 따라 다르겠지만 벨로그에선 커봐야 1000 x 600 쯤 될 것이다. 모바일 환경에선 더더욱 크기가 작을 것이다.

그렇다면 브라우저에서 사용 할 만큼의 사이즈로 이미지를 압축하여 저장 한 후 브라우저 상에서 적절한 크기에 맞춰 HTTP 통신을 통해 이미지를 받아오는 편이 훨씬 효과적이다.

이미지 크기를 효과적으로 압축하는 방법은 절대적인 크기 자체를 줄이는 방법과 이미지의 포맷을 변경하여 바이너리 데이터의 수를 줄이는 방법이 있다.

이에 대한 포스팅은 예전에 작성했던 게시글로 대체한다.[2]

반응형 이미지

이미지 압축과 함께 자주 사용되는 방법은 바로 반응형 이미지이다.

반응형 이미지란 디바이스의 뷰포트 크기에 맞춰 적절한 이미지를 제공하는 방식을 의미한다.

예를 들어 위의 귀여운 고양이 이미지를 압축한다고 모바일 이미지 크기에 맞춰 압축해두었다고 가정해보자.

그 이미지는 모바일에서는 문제 없이 마치 원본처럼 보일 것이다.

하지만 뷰포트 크기가 더 큰 피시 화면의 유저에게는 작은 이미지를 확대하여 렌더링 하기 때문에 이미지의 화질이 저하 되어 보일 수 있다.

가장 이상적인 방법으로는 디바이스 화면 크기에 따라 로드 할 최적의 해상도 이미지를 결정하는 것으로 이를 해상도 전환 문제(resolution switching problem) 라고 한다.[3]

겸사 겸사 포스팅하며 보니 MDN 에서 오타가 나있더군요 호호

srcset , sizes 를 이용한 반응형 디자인

반응형 디자인은 img 태그를 이용하여 불러올 이미지의 크기를 선택하거나 , 불러올 이미지의 해상도를 선택하는 방식으로 구현 할 수 있다.

 <body>
    <h1>반응형 이미지 구현</h1>
    <img
      srcset="
        https://via.placeholder.com/300 300w,
        https://via.placeholder.com/400 400w,
        https://via.placeholder.com/500 500w
      "
      sizes="
        (max-width: 500px) 300px,
        (max-width: 600px) 400px,
        500px
      "
    />
    <p></p>
  </body>

sizes 속성은 미디어 쿼리 조건을 이용하여 작성한다.

위에서 작성한 (max-width : 500px) 300px 은 뷰포트의 크기가 500px 이하면 이미지가 채워야 할 슬롯을 300px 로 만들어라를 의미한다.

브라우저는 뷰포트의 크기를 감지하고 해당 사이즈에 맞는 슬롯을 생성한다.

이후 슬롯의 크기 300px 과 동일한 크기를 가진 이미지를 srcset 에서 찾아 해당 이미지로 슬롯을 모두 채운다.

srcset 에선 픽셀단위가 아닌 w 단위가 사용된다.

만약 srcset 에서 슬롯의 크기와 같은 이미지를 찾지 못한다면 슬롯보다 사이즈가 첫 번째로 큰 이미지를 선택한다.

이렇게 하게 되면 다양한 뷰포트 크기에 맞춰 적절하게 압축된 사진을 제공 할 수 있게 된다.

CDN 사용하기

Content Dilivery Network 의 약자인 CDN은 다양한 지역에 분산된 서버들의 그룹을 의미한다.[4]

이를 이용하면 이미지에 대한 요청 자체를 요청하는 장소로부터 지역적으로 가까운 서버로부터 받을 수 있기 때문에 더욱 빠르게 응답을 받을 수 있다.

출처 : 위키피디아

CDN 은 이미지 파일 뿐 아니라 다양한 정적 데이터를 캐싱해두는 서버로 예를 들어 해당 사이트에 들어가면[5] 리액트 라이브러리를 저장하고 있는 CDN 서버의 주소를 다음과 같이 살펴 볼 수 있다.

브라우저 캐시 이용하기

CDN 같은 네트워크 서버를 이용하지 않더라도 브라우저 단에서 이미지를 캐싱해두는 방법도 존재한다.

브라우저에 도착 한 후의 이미지 최적화

위예시에서는 브라우저에 도착하기 전 까지의 단계로 렌더링 관련 이미지 최적화에 대해 알아보았다.

이번에는 브라우저에 이미지가 도착 한 후를 가정하여 최적화를 알아보자

정적 크기 설정

이미지를 브라우저에 그리는 것은 비용이 큰 작업이다.

액츄얼 돔을 그리기 위해 돔 노드들의 위치를 계산하고 그래픽 상으로 그려야 하기 때문이다.

이 때 만약 이미지가 로드 되기 전과 후의 돔 노드들의 레이아웃이 변경되게 된다면 이미 그려졌던 노드들의 위치를 모두 재계산 해야 할 것이다.

출처 : HTML의 이미지 - MDN. [6]

그 뿐 아니라 이렇게 레이아웃 쉬프트가 일어나게 되는 것은 웹의 성능을 평가하는 척도인 Core Web Vital 에서 평가하는 누적 레이아웃 쉬프트에 악영향을 미쳐 SEO 에도 영향을 미칠 수 있다.

당연히 사용자 경험에도 부정적인 영향을 미친다.

이러한 일을 방지하기 위해 이미지를 로드 할 때 이미지의 크기를 정적으로 설정해둬 레이아웃 쉬프트를 방지하여 사용자 경험을 향상 시킬 수 있다.

이미지의 크기를 정적인 단위로 할 수 없을 때엔 aspect-ratio 를 이용하여 이미지의 크기를 반응형으로 만들어줄 수 있다.

lazy loading

lazy loading 은 말 그대로 이미지를 늦게 로딩 하는 것이다.

이러한 레이지 로딩은 웹 페이지가 로드 될 때 모든 데이터를 렌더링 하는 것이 아닌, 스크롤과 같은 상호작용에 맞춰 이미지를 불러오는 것이다.

사용자에게 당장 드러나지 않을 부분을 렌더링 하지 않고 사용자에게 당장 드러날 부분만 우선적으로 로드함으로서 중요 렌더링 경로의 길이를 단축 시킬 수 있다. [8]

이미지의 레이지 로딩은 loading='lazy' 속성을 통해 일어난다.

이에 대한 설명은 잘 설명해준 우테코 비디오 영상으로 대체한다. [9]

출처

1. 패킷분해 #1 한 패킷의 크기(MTU)는 얼마나 될까?
2. 프론트엔드 이미지 최적화에 관하여
3. 반응형 이미지 - Web 개발 학습하기 | MDN
4. CDN - MDN Web Docs 용어 사전: 웹 용어 정의 | MDN
5. cdnjs - The #1 free and open source CDN built to make life easier for developers
6. HTML의 이미지 - Web 개발 학습하기 | MDN
7. Cumulative Layout Shift (CLS) - MDN Web Docs Glossary: Definitions of Web-related terms | MDN
8. 지연 로딩 - 웹 성능 | MDN
9. (1) [10분 테코톡] 록바의 웹 성능 개선하기 - 이미지 - YouTube

profile
빨리 가는 유일한 방법은 제대로 가는 것이다

0개의 댓글