클라이언트 힌트를 사용하여 사용자에 맞게 조정

어디서나 빠른 속도를 제공하는 사이트를 개발하는 것은 까다로울 수 있습니다. 기기의 과다한 기능과 연결된 네트워크의 품질로 인해 해결하기 어려운 작업처럼 보일 수 있습니다. 브라우저 기능을 활용하여 로드 성능을 개선할 수 있지만 사용자 기기에서 사용할 수 있는 기능이나 네트워크 연결 품질은 어떻게 알 수 있을까요? 해결책은 클라이언트 힌트입니다.

클라이언트 힌트는 선택 HTTP 요청 헤더의 집합으로, 사용자 기기 및 사용자가 연결된 네트워크의 이러한 측면에 관한 정보를 제공합니다. 이 정보 서버 측을 활용하면 기기 또는 네트워크 상태에 따라 콘텐츠를 제공하는 방법을 변경할 수 있습니다. 이를 통해 더 포용적인 사용자 환경을 만들 수 있습니다

콘텐츠 협상의 중요성

클라이언트 힌트는 콘텐츠 협상의 또 다른 방법으로, 브라우저 요청 헤더에 따라 콘텐츠 응답을 변경합니다.

콘텐츠 협상의 한 가지 예로 Accept 요청 헤더가 있습니다. 브라우저가 응답을 협상하는 데 사용할 수 있는 콘텐츠 유형을 설명합니다. 이미지 요청의 경우 Chrome의 Accept 헤더 콘텐츠는 다음과 같습니다.

Accept: image/webp,image/apng,image/*,*/*;q=0.8

모든 브라우저가 JPEG, PNG, GIF와 같은 이미지 형식을 지원하지만 이 경우 수락은 브라우저가 WebPAPNG 지원한다고 알립니다. 이 정보를 사용하여 각 브라우저에 가장 적합한 이미지 유형을 협상할 수 있습니다.

<?php
// Check Accept for an "image/webp" substring.
$webp = stristr($_SERVER["HTTP_ACCEPT"], "image/webp") !== false ? true : false;

// Set the image URL based on the browser's WebP support status.
$imageFile = $webp ? "whats-up.webp" : "whats-up.jpg";
?>
<img src="<?php echo($imageFile); ?>" alt="I'm an image!">

Accept와 마찬가지로 클라이언트 힌트는 기기 기능 및 네트워크 조건의 맥락에서 콘텐츠를 협상하는 또 다른 방법입니다. 클라이언트 힌트를 사용하면 네트워크 상태가 좋지 않은 사용자에게 중요하지 않은 리소스를 제공해야 하는지 결정하는 등 사용자의 개별 환경에 따라 서버 측 성능을 결정할 수 있습니다. 이 가이드에서는 제공되는 모든 힌트와 이를 사용하여 사용자에게 더 적합한 콘텐츠를 제공하는 방법을 설명합니다.

서비스 선택하기

Accept 헤더와 달리 클라이언트 힌트는 마법처럼 표시되지 않습니다(Save-Data는 예외임(나중에 설명함). 요청 헤더를 최소한으로 유지하려면 사용자가 리소스를 요청할 때 Accept-CH 헤더를 전송하여 수신할 클라이언트 힌트를 선택해야 합니다.

Accept-CH: Viewport-Width, Downlink

Accept-CH 값은 사이트에서 후속 리소스 요청의 결과를 결정하는 데 사용할 요청 힌트를 쉼표로 구분한 목록입니다. 클라이언트가 이 헤더를 읽으면 '이 사이트에서 Viewport-WidthDownlink 클라이언트 힌트를 원합니다'라는 메시지가 표시됩니다. 특정 힌트 자체는 걱정하지 마세요. 이에 대해서는 잠시 후에 살펴보겠습니다.

이러한 수신 동의 헤더는 모든 백엔드 언어로 설정할 수 있습니다. 예를 들어 PHP의 header 함수를 사용할 수 있습니다. <meta> 태그에 http-equiv 속성을 사용하여 이러한 수신 동의 헤더를 설정할 수도 있습니다.

<meta http-equiv="Accept-CH" content="Viewport-Width, Downlink" />

모든 클라이언트 힌트

클라이언트 힌트는 사용자가 사용하는 기기와 사이트에 액세스하는 데 사용하는 네트워크 중 하나를 설명합니다. 사용할 수 있는 모든 힌트를 간단히 살펴보겠습니다

기기 힌트

일부 클라이언트 힌트는 사용자 기기의 특성(일반적으로 화면 특성)을 설명합니다. 일부는 특정 사용자의 화면에 가장 적합한 미디어 리소스를 선택하는 데 도움이 될 수 있지만 모든 리소스가 반드시 미디어 중심적인 것은 아닙니다.

이 목록을 살펴보기 전에 먼저 화면과 미디어 해상도를 설명하는 데 사용되는 몇 가지 주요 용어를 알아두는 것이 좋습니다.

고유 크기: 미디어 리소스의 실제 크기입니다. 예를 들어 Photoshop에서 이미지를 열면 이미지 크기 대화상자에 표시된 크기가 기본 크기를 설명합니다.

밀도 보정 고유 크기: 픽셀 밀도에 맞게 미디어가 수정된 후 미디어 리소스의 크기입니다. 이미지의 기본 크기기기 픽셀 비율로 나눈 값입니다. 예를 들어 다음 마크업을 살펴보겠습니다.

<img
  src="whats-up-1x.png"
  srcset="whats-up-2x.png 2x, whats-up-1x.png 1x"
  alt="I'm that image you wanted."
/>

이 경우 1x 이미지의 고유 크기는 320x240이고 2x 이미지의 고유 크기가 640x480이라고 가정해 보겠습니다. 이 마크업이 화면 기기 픽셀 비율이 2인 기기 (예: 레티나 화면)에 설치된 클라이언트가 파싱하는 경우 2x 이미지가 요청됩니다. 2x 이미지의 밀도 보정 고유 크기는 320x240입니다. 640x480을 2로 나눈 값은 320x240이기 때문입니다.

외부 크기: CSS 및 기타 레이아웃 요소 (예: widthheight 속성)가 적용된 후 미디어 리소스의 크기입니다. 밀도 수정 기본 크기가 320x240인 이미지를 로드하는 <img> 요소가 있다고 가정해 보겠습니다. 이 요소에는 각각 256px192px 값이 적용된 CSS widthheight 속성도 있습니다. 이 예에서 <img> 요소의 외부 크기는 256x192가 됩니다.

고유 크기와 외재 크기를 비교하여 보여주는 그림 320x240픽셀 크기의 상자가 실제 크기 라벨과 함께 표시됩니다. 그 안에는 256x192픽셀 크기의 작은 상자가 있으며, 이는 CSS가 적용된 HTML img 요소를 나타냅니다. 이 상자에는 외부 크기가 지정되어 있습니다. 오른쪽에는 요소에 적용된 CSS가 포함된 상자가 있습니다. 이 상자는 외부 크기가 고유 크기와 다르게 img 요소의 레이아웃을 수정합니다.
그림 1. 내재적 크기와 외재적 크기를 비교하여 보여주는 그림 이미지는 레이아웃 요소를 적용한 후에 외부 크기가 커집니다. 이 경우 width: 256px;height: 192px;의 CSS 규칙을 적용하면 320x240 고유 크기의 이미지가 256x192 외부 크기로 변환됩니다.

몇 가지 용어를 사용하며, 기기별 클라이언트 힌트 목록을 살펴보겠습니다.

표시 영역 너비

Viewport-Width는 사용자 표시 영역의 너비입니다(CSS 픽셀).

Viewport-Width: 320

이 힌트는 다른 화면별 힌트와 함께 사용되어 특정 화면 크기 (예: 아트 디렉션)에 최적화된 다양한 이미지 처리(예: 자르기)를 제공하거나 현재 화면 너비에 불필요한 리소스를 생략할 수 있습니다.

북한

기기 픽셀 비율의 약자인 DPR는 사용자 화면의 실제 픽셀 대 CSS 픽셀의 비율을 보고합니다.

DPR: 2

이 힌트는 x 설명자가 srcset 속성에서 실행하는 것처럼 화면의 픽셀 밀도에 상응하는 이미지 소스를 선택할 때 유용합니다.

너비

Width 힌트는 sizes 속성을 사용하여 <img> 또는 <source> 태그에 의해 실행된 이미지 리소스 요청에 표시됩니다. sizes는 브라우저의 외부 크기를 브라우저에 알려줍니다. Width는 이 외부 크기를 사용하여 현재 레이아웃에 최적화된 고유 크기를 가진 이미지를 요청합니다.

예를 들어 사용자가 DPR이 2이고 320 CSS 픽셀 너비의 화면이 포함된 페이지를 요청한다고 가정해 보겠습니다. 기기는 85vwsizes 속성 값 (즉,<img> 모든 화면 크기에서 표시 영역 너비의 85%). Width 힌트가 선택되면 클라이언트는 <img>src 요청과 함께 이 Width 힌트를 서버에 전송합니다.

Width: 544

이 경우 클라이언트는 요청된 이미지의 최적 고유 너비가 표시 영역 너비의 85%(272픽셀)에 화면의 DPR (2)을 곱한 값인 544픽셀이라고 서버에 알립니다.

이 힌트는 밀도가 수정된 화면의 너비를 고려할 뿐만 아니라 이 중요한 정보를 레이아웃 내 이미지의 외재 크기와 조정하기 때문에 특히 유용합니다. 이렇게 하면 서버는 화면 레이아웃에 최적화된 이미지 응답을 협상할 수 있습니다.

콘텐츠-DPR

화면에 기기 픽셀 비율이 있다는 것을 이미 알고 있지만 리소스에는 고유한 픽셀 비율이 있습니다. 가장 간단한 리소스 선택 사용 사례에서는 기기와 리소스 간의 픽셀 비율이 동일할 수 있습니다. 하지만! DPR 헤더와 Width 헤더가 모두 적용되는 경우 리소스의 외부 크기로 인해 둘이 다른 시나리오를 생성할 수 있습니다. 여기서 Content-DPR 힌트가 사용됩니다.

다른 클라이언트 힌트와 달리 Content-DPR는 서버에서 사용하는 요청 헤더가 아니라 리소스를 선택하는 데 DPRWidth 힌트가 사용될 때마다 응답 헤더 서버가 전송해야 합니다. Content-DPR의 값은 다음 방정식의 결과여야 합니다.

Content-DPR = [선택한 이미지 리소스 크기] / ([Width] / [DPR])

Content-DPR 요청 헤더가 전송되면 브라우저에서 화면의 기기 픽셀 비율과 레이아웃에 맞게 지정된 이미지를 조정하는 방법을 인식합니다. 이 태그가 없으면 이미지가 제대로 확장되지 않을 수 있습니다.

기기 메모리

기술적으로 Device Memory API의 일부인 Device-Memory는 현재 기기에 있는 대략적인 메모리 양을 GiB 단위로 표시합니다.

Device-Memory: 2

이 힌트의 가능한 사용 사례는 자바스크립트가 리소스 사용이 가장 많은 콘텐츠 유형 브라우저가 일반적으로 로드하기 때문에 메모리가 제한된 기기에서 브라우저로 전송되는 JavaScript의 양을 줄이는 것입니다. 또는 디코딩에 더 적은 메모리를 사용하므로 더 낮은 DPR 이미지를 보낼 수 있습니다.

네트워크 힌트

Network Information API는 사용자의 네트워크 연결 성능을 설명하는 또 다른 클라이언트 힌트 카테고리를 제공합니다. 제 생각에는 가장 유용한 힌트입니다. 이를 통해 느린 연결에서 클라이언트에 리소스를 제공하는 방식을 변경하여 사용자 환경을 맞춤설정할 수 있습니다.

RTT

RTT 힌트는 애플리케이션 레이어의 대략적인 왕복 시간(밀리초)을 제공합니다. RTT 힌트에는 전송 계층 RTT와 달리 서버 처리 시간이 포함됩니다.

RTT: 125

로드 성능에서 지연 시간이 중요한 역할을 하기 때문에 이 힌트가 유용합니다. RTT 힌트를 사용하면 네트워크 응답성을 기준으로 결정을 내릴 수 있으므로 전체 환경 (예: 일부 요청 생략)의 제공 속도를 높이는 데 도움이 될 수 있습니다.

지연 시간은 로드 성능에 중요하지만 대역폭도 영향을 미칩니다. 초당 메가비트 (Mbps)로 표시되는 Downlink 힌트는 사용자 연결의 대략적인 다운스트림 속도를 보여줍니다.

Downlink: 2.5

RTT와 함께 Downlink를 사용하면 네트워크 연결 품질에 따라 콘텐츠가 사용자에게 전송되는 방식을 변경하는 데 유용할 수 있습니다.

ECT

ECT 힌트는 유효 연결 유형을 나타냅니다. 값은 열거된 연결 유형 목록 중 하나이며, 각 목록은 RTTDownlink 값의 지정된 범위 내의 연결을 설명합니다.

이 헤더는 실제 연결 유형을 설명하지 않습니다. 예를 들어 게이트웨이가 휴대폰 기지국인지 Wi-Fi 액세스 포인트인지를 보고하지 않습니다. 대신 현재 연결의 지연 시간과 대역폭을 분석하여 가장 유사한 네트워크 프로필을 결정합니다. 예를 들어 Wi-Fi를 통해 느린 네트워크에 연결하면 ECT유효한 연결에 가장 가까운 2g 값으로 채워질 수 있습니다.

ECT: 2g

유효한 ECT 값은 4g, 3g, 2g, slow-2g입니다. 이 힌트를 연결 품질 평가의 시작점으로 사용한 후 RTTDownlink 힌트를 사용하여 미세 조정할 수 있습니다.

데이터 저장

Save-Data은 페이지에서 전송하는 데이터를 더 적게 해야 한다고 명시하는 사용자 환경설정이므로 네트워크 조건을 설명하는 힌트가 아닙니다.

Save-Data를 네트워크 힌트로 분류하는 것을 선호합니다. 왜냐하면 이 힌트로 실행하는 많은 작업이 다른 네트워크 힌트와 비슷하기 때문입니다. 또한 사용자는 지연 시간이 길거나 대역폭이 낮은 환경에서 이 기능을 사용 설정할 수도 있습니다. 이 힌트가 존재하면 이 힌트는 항상 다음과 같습니다.

Save-Data: on

Google에서 Save-Data로 할 수 있는 작업을 알아보았습니다. 실적에는 막대한 영향을 미칠 수 있습니다. 이는 사용자가 말 그대로 전송을 더 적게 해달라고 요청하는 신호입니다 그 신호를 듣고 행동하면 사용자가 고마워할 것입니다.

종합하기

클라이언트 힌트로 수행하는 작업은 사용자에 따라 다릅니다. 방대한 양의 정보를 제공하므로 선택할 수 있는 옵션도 다양합니다. 아이디어를 얻을 수 있도록 어퍼 중서부의 시골 지역에 위치한 가상의 목재 회사인 Sconnie Timber가 클라이언트 힌트를 사용하여 무엇을 할 수 있는지 알아보겠습니다. 원격 지역에서 흔히 그렇듯이 네트워크 연결은 취약할 수 있습니다. 클라이언트 힌트와 같은 기술이 사용자에게 실제로 차이를 가져다줄 수 있는 부분입니다.

반응형 이미지

가장 간단한 반응형 이미지를 제외한 모든 사용 사례는 복잡해질 수 있습니다. 서로 다른 화면 크기 서로 다른 형식에 대해 여러 처리 동일한 이미지의 변형이 있는 경우 어떻게 해야 할까요? 이 마크업은 매우 복잡해지고 매우 빠르게 됩니다. 오해하기 쉬우며 중요한 개념 (예: sizes)을 잊거나 잘못 이해하기도 합니다.

<picture>srcset은 매우 멋진 도구이지만 복잡한 사용 사례를 위해 개발하고 유지하는 데 시간이 오래 걸릴 수 있습니다. 마크업 생성을 자동화할 수도 있지만, <picture>srcset가 제공하는 기능이 상당히 복잡하여 유연성을 제공하는 방식으로 자동화를 실행해야 하기 때문에 그렇게 하기가 어렵습니다.

클라이언트 힌트를 사용하면 이를 간소화할 수 있습니다. 클라이언트 힌트와 이미지 응답을 협상하는 과정은 다음과 같습니다.

  1. 워크플로에 해당하는 경우 먼저 Viewport-Width 힌트를 확인하여 이미지 처리 (예: 아트 디렉팅 이미지)를 선택합니다.
  2. Width 힌트와 DPR 힌트를 확인하고 이미지의 레이아웃 크기와 화면 밀도에 맞는 소스를 선택하여 이미지 해상도를 선택합니다 (srcset에서 xw 설명어가 작동하는 방식과 유사함).
  3. 브라우저에서 지원하는 최적의 파일 형식을 선택합니다 (대부분의 브라우저에서 Accept를 사용하면 도움이 됨).

가상의 목재 회사 고객이 우려하는 곳에 클라이언트 힌트를 사용하는 간단한 반응형 이미지 선택 루틴을 PHP로 개발했습니다. 이는 모든 사용자에게 이 마크업을 보내는 것이 아니라는 의미입니다.

<picture>
  <source
    srcset="
      company-photo-256w.webp   256w,
      company-photo-512w.webp   512w,
      company-photo-768w.webp   768w,
      company-photo-1024w.webp 1024w,
      company-photo-1280w.webp 1280w
    "
    type="image/webp"
  />
  <img
    srcset="
      company-photo-256w.jpg   256w,
      company-photo-512w.jpg   512w,
      company-photo-768w.jpg   768w,
      company-photo-1024w.jpg 1024w,
      company-photo-1280w.jpg 1280w
    "
    src="company-photo-256w.jpg"
    sizes="(min-width: 560px) 251px, 88.43vw"
    alt="The Sconnie Timber Staff!"
  />
</picture>

개별 브라우저 지원에 따라 다음과 같이 줄일 수 있었습니다.

<img
  src="/image/sizes:true/company-photo.jpg"
  sizes="(min-width: 560px) 251px, 88.43vw"
  alt="SAY CHEESY PICKLES."
/>

이 예에서 /image URL은 PHP 스크립트이고 mod_rewrite로 재작성된 매개변수가 뒤따릅니다. 백엔드 스크립트가 지정된 조건에서 최적의 이미지를 선택하는 데 도움이 되도록 이미지 파일 이름과 추가 매개변수를 가져옵니다.

첫 번째 질문인데요, '그런데 백엔드에서 <picture>srcset를 단순히 재구현하는 것 아닌가요?'라는 생각이 듭니다.

여러 면에서 그렇습니다. 하지만 한 가지 중요한 차이점이 있습니다. 애플리케이션이 클라이언트 힌트를 사용하여 미디어 응답을 작성하는 경우 작업의 대부분 (전부는 아니지만)을 훨씬 쉽게 자동화할 수 있습니다. 여기에는 사용자를 대신하여 이 작업을 수행할 수 있는 서비스 (예: CDN)가 포함될 수 있습니다. 반면 HTML 솔루션의 경우 모든 사용 사례에 제공할 수 있도록 새 마크업을 작성해야 합니다. 예, 마크업 생성을 자동화할 수 있습니다. 그러나 설계나 요구사항이 변경되면 향후 자동화 전략을 재검토해야 할 가능성이 높습니다.

클라이언트 힌트를 사용하면 무손실 고해상도 이미지로 시작할 수 있으며, 그런 다음 화면과 레이아웃의 모든 조합에 맞게 동적으로 크기를 조절할 수 있습니다. 브라우저에서 선택할 수 있는 이미지 조합의 고정된 목록을 열거해야 하는 srcset와 달리 이 방법은 더 유연할 수 있습니다. srcset를 사용하면 브라우저에 대략적인 변형 집합(예: 256w, 512w, 768w, 1024w)을 제공해야 하지만, 클라이언트 힌트 기반 솔루션은 대규모 마크업 더미 없이 모든 너비를 제공할 수 있습니다.

물론 이미지 선택 로직을 직접 작성할 필요는 없습니다. Cloudinary는 w_auto 매개변수를 사용할 때 클라이언트 힌트를 사용하여 이미지 응답을 생성하며 클라이언트 힌트를 지원하는 브라우저를 사용할 때 사용자 다운로드 바이트 중앙값이 42% 감소하는 것을 관찰했습니다.

하지만 주의하세요. Chrome 67 데스크톱 버전의 변경사항으로 인해 교차 출처 클라이언트 힌트 지원이 삭제되었습니다. 다행히 이러한 제한사항은 Chrome의 모바일 버전에 영향을 미치지 않으며 기능 정책 작업이 완료되면 모든 플랫폼에서 이 제한이 완전히 해제됩니다.

네트워크 속도가 느린 사용자 지원

적응형 성능이란 클라이언트 힌트가 사용할 수 있는 정보, 특히 사용자 네트워크 연결의 현재 상태에 관한 정보를 기반으로 리소스를 제공하는 방식을 조정할 수 있는 개념입니다.

Sconnie Timber의 사이트와 관련하여 Google은 네트워크가 느릴 때 부하를 줄이기 위한 조치를 취합니다. 이때 백엔드 코드에서 Save-Data, ECT, RTT, Downlink 헤더를 검사합니다. 이 과정에서 Google은 더 나은 사용자 환경을 위해 개입해야 할지 결정하는 데 사용할 수 있는 네트워크 품질 점수를 생성합니다. 이 네트워크 점수는 0에서 1 사이이며, 여기서 0은 네트워크 품질이 가장 낮고 1이 최고입니다.

처음에는 Save-Data가 있는지 확인합니다. 이 경우 점수는 0로 설정됩니다. 사용자가 환경을 더 가볍고 빠르게 만드는 데 필요한 작업을 하기를 원한다고 가정하기 때문입니다.

그러나 Save-Data가 없으면 ECT, RTT, Downlink 힌트 값으로 이동하여 네트워크 연결 품질을 설명하는 점수를 계산합니다. 네트워크 점수 생성 소스 코드는 GitHub에서 확인할 수 있습니다. 핵심은 일부 방식으로 네트워크 관련 힌트를 사용하면 네트워크 속도가 느린 사용자에게 더 나은 환경을 제공할 수 있다는 것입니다.

클라이언트 힌트를 사용하여 느린 네트워크 연결에 적응하지 않는 사이트 (왼쪽)와 느린 네트워크 연결에 적응하는 사이트(오른쪽)를 비교합니다.
그림 2. 지역 비즈니스 사이트의 '회사 소개' 페이지. 기준 환경에는 웹 글꼴, 캐러셀과 아코디언 동작을 구동하는 자바스크립트, 콘텐츠 이미지가 포함됩니다. 네트워크 상태가 너무 느려 빠르게 로드할 수 없는 경우에는 생략할 수 있습니다.

사이트가 클라이언트 힌트가 제공하는 정보에 맞게 조정되면 '전부 아니면 전무' 방식을 채택할 필요가 없습니다. 어떤 리소스를 보낼지 지능적으로 결정할 수 있습니다. 네트워크 품질이 좋지 않을 때 로드 성능을 높이기 위해 특정 디스플레이에 더 낮은 화질의 이미지를 전송하도록 반응형 이미지 선택 로직을 수정할 수 있습니다.

이 예에서는 느린 네트워크에서 사이트의 성능을 향상시키는 데 클라이언트 힌트가 미치는 영향을 확인할 수 있습니다. 다음은 속도가 느린 네트워크 사이트에서 클라이언트 힌트에 맞지 않는 WebPagetest의 폭포식 구조입니다.

느린 네트워크 연결로 모든 리소스를 로드하는 Sconnie Timber 사이트의 WebPagetest 워터폴
그림 3. 인터넷 연결이 느릴 때 이미지, 스크립트, 글꼴을 로드하는 리소스가 많은 사이트

이제 동일한 느린 연결의 동일한 사이트에 대한 폭포식 구조가 표시됩니다. 단, 이번에는 이 경우에 사이트에서 클라이언트 힌트를 사용하여 중요하지 않은 페이지 리소스를 제거합니다.

클라이언트 힌트를 사용하여 네트워크 연결이 느릴 때 중요하지 않은 리소스를 로드하지 않기로 결정하는 Sconnie Timber 사이트의 WebPagetest 워터폴
그림 4. 동일한 연결에 있는 동일한 사이트. 더 빠른 로드를 위해 '있으면 좋은' 리소스만 제외됩니다.

클라이언트 힌트가 페이지 로드 시간을 45초에서 10분의 1 미만으로 줄였습니다. 이 시나리오에서 클라이언트 힌트의 이점은 아무리 강조해도 지나치지 않으며 느린 네트워크에서 중요한 정보를 찾는 사용자에게 큰 도움이 될 수 있습니다.

또한 클라이언트 힌트를 지원하지 않는 브라우저의 환경을 방해하지 않고 클라이언트 힌트를 사용할 수 있습니다. 예를 들어 지원되지 않는 브라우저에 전체 환경을 제공하면서 ECT 힌트 값에 따라 리소스 제공을 조정하려면 다음과 같이 기본값으로 대체할 수 있습니다.

// Set the ECT value to "4g" by default.
$ect = isset($_SERVER["HTTP_ECT"]) ? $_SERVER["HTTP_ECT"] : "4g";

여기서 "4g"ECT 헤더가 설명하는 최고 품질의 네트워크 연결을 나타냅니다. $ect"4g"로 초기화해도 클라이언트 힌트를 지원하지 않는 브라우저는 영향을 받지 않습니다. FTW 선택

캐시를 조심하세요!

HTTP 헤더를 기반으로 응답을 변경할 때마다 캐시가 해당 리소스의 향후 가져오기를 처리하는 방법을 알아야 합니다. Vary 헤더는 제공된 요청 헤더의 값에 항목을 캐시하기 때문에 이 경우에 필수적입니다. 간단히 말해, 지정된 HTTP 요청 헤더를 기반으로 응답을 수정하는 경우 다음과 같이 거의 항상 해당 헤더를 Vary에 포함해야 합니다.

Vary: DPR, Width

하지만 이 경우 주의가 있습니다. 자주 변경되는 헤더 (예: Cookie)에서는 캐시 가능한 응답을 Vary하면 안 됩니다. 이러한 리소스는 사실상 캐시할 수 없게 되기 때문입니다. 이 사실을 알고 있으면 RTT 또는 Downlink와 같은 클라이언트 힌트 헤더에서 Vary를 사용하지 않는 것이 좋습니다. 이러한 헤더는 연결 요소가 매우 자주 변경될 수 있기 때문입니다. 이러한 헤더의 응답을 수정하려면 캐시 부적중을 최소화하는 ECT 헤더만 키 지정해 보세요.

물론, 이는 애초에 응답을 캐시하는 경우에만 적용됩니다. 예를 들어 콘텐츠가 동적인 경우 HTML 애셋을 캐시하지 않습니다. 이 경우 재방문 시 사용자 환경이 손상될 수 있습니다. 이러한 경우 Vary에 신경 쓰지 않고 필요하다고 생각되는 대로 자유롭게 응답을 수정하세요.

서비스 워커의 클라이언트 힌트

콘텐츠 협상은 더 이상 서버에만 국한되지 않습니다. 서비스 워커는 클라이언트와 서버 사이에서 프록시 역할을 하므로 JavaScript를 통해 리소스가 전달되는 방식을 제어할 수 있습니다. 여기에는 클라이언트 힌트가 포함됩니다. 서비스 워커 fetch 이벤트에서 다음과 같이 event 객체의 request.headers.get 메서드를 사용하여 리소스의 요청 헤더를 읽을 수 있습니다.

self.addEventListener('fetch', (event) => {
  let dpr = event.request.headers.get('DPR');
  let viewportWidth = event.request.headers.get('Viewport-Width');
  let width = event.request.headers.get('Width');

  event.respondWith(
    (async function () {
      // Do what you will with these hints!
    })(),
  );
});

선택한 모든 클라이언트 힌트 헤더를 이 방식으로 읽을 수 있습니다. 다른 방법으로도 이러한 정보를 얻을 수 있는 것은 아닙니다. 네트워크별 힌트는 navigator 객체의 상응하는 자바스크립트 속성에서 읽을 수 있습니다.

클라이언트 힌트 JS 상응
'ECT' `navigator.connection.effectiveType`
'RTT' `navigator.connection.rtt`
'데이터 저장' `navigator.connection.saveData`
'다운링크' `navigator.connection.downlink`
`기기-메모리` `navigator.deviceMemory`
파일 형식용 Imagemin 플러그인입니다.

이러한 API는 in 연산자로 기능 확인이 필요한 모든 곳에서 사용할 수 없으므로

if ('connection' in navigator) {
  // Work with netinfo API properties in JavaScript!
}

여기에서 클라이언트 힌트로 콘텐츠를 협상하기 위해 서버가 필요하지 않다는 점을 제외하고 서버에서 사용하는 것과 유사한 로직을 사용할 수 있습니다. 서비스 워커만으로도 사용자가 오프라인 상태일 때 콘텐츠를 제공할 수 있는 추가 기능 덕분에 더 빠르고 복원력이 우수한 환경을 만들 수 있습니다.

요약

클라이언트 힌트를 사용하면 완전히 진보적인 방식으로 사용자의 환경을 더 빠르게 개선할 수 있습니다. 특히 복잡한 사용 사례의 경우 <picture>srcset에 의존하는 것보다 더 쉽게 반응형 이미지를 제공할 수 있는 방식으로 사용자의 기기 기능을 기반으로 미디어를 제공할 수 있습니다. 이를 통해 개발 측면의 시간과 노력을 줄일 수 있을 뿐만 아니라 및 srcset가 할 수 있는 것보다 더 세밀하게 사용자의 화면을 타겟팅하는 방식으로 리소스(특히 이미지)를 최적화할 수 있습니다.

아마도 더 중요한 것은 우리가 보내는 항목과 보내는 방식을 수정하여 불량한 네트워크 연결을 찾아내고 사용자의 간극을 메울 수 있다는 것입니다. 이는 취약한 네트워크를 사용하는 사용자가 사이트에 더 쉽게 액세스할 수 있도록 하는 데 효과를 볼 수 있습니다. 서비스 워커와 함께 사용하면 매우 빠른 속도로 오프라인에서 사용할 수 있는 사이트를 만들 수 있습니다.

클라이언트 힌트는 Chrome 및 Chromium 기반 브라우저에서만 사용할 수 있지만, 클라이언트 힌트를 지원하지 않는 브라우저를 방해하지 않는 방식으로 사용할 수도 있습니다. 클라이언트 힌트를 사용하여 모든 사용자의 기기 기능과 연결된 네트워크를 인식하는 진정으로 포용적이고 적응형 환경을 만드는 것이 좋습니다. 다른 브라우저 공급업체도 이 가치를 이해하고 구현할 의도를 보여 줄 것입니다.

자료

이 기사에 대한 소중한 의견과 수정사항인 일리야 그리고릭, 에릭 포티스, 제프 포스닉, 요아브 바이스, 에스텔 웨일에게 감사의 말씀을 전합니다.