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

어디서나 빠른 사이트를 개발하는 것은 까다로운 작업일 수 있습니다. 기기 기능의 다양성과 기기가 연결되는 네트워크의 품질로 인해 이 작업은 극복할 수 없는 과제처럼 보일 수 있습니다. 브라우저 기능을 활용하여 로드 성능을 개선할 수 있지만, 사용자의 기기 기능이나 네트워크 연결 품질을 어떻게 알 수 있을까요? 해결 방법은 클라이언트 힌트입니다.

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

콘텐츠 협상이 핵심입니다

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

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

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

모든 브라우저가 JPEG, PNG, GIF와 같은 이미지 형식을 지원하지만, 이 경우 Accept는 브라우저가 WebP 및 APNG도 지원함을 알려줍니다. 이 정보를 사용하여 각 브라우저에 가장 적합한 이미지 유형을 협상할 수 있습니다.

<?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-Width 및 Downlink 클라이언트 힌트를 원한다'는 메시지가 표시됩니다. 구체적인 힌트 자체에 대해서는 걱정하지 마세요. 잠시 후에 살펴보겠습니다.

이러한 선택 헤더는 모든 백엔드 언어로 설정할 수 있습니다. 예를 들어 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인 기기 (예: Retina 화면)에 설치된 클라이언트가 이 마크업을 파싱하면 2x 이미지가 요청됩니다. 2x 이미지의 밀도 보정 고유 크기는 320x240입니다. 640x480을 2로 나누면 320x240이기 때문입니다.

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

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

몇 가지 용어를 살펴봤으니 이제 사용할 수 있는 기기별 클라이언트 힌트 목록을 살펴보겠습니다.

Viewport-Width

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

Viewport-Width: 320

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

DPR

DPR는 기기 픽셀 비율의 약어로, 사용자 화면의 물리적 픽셀과 CSS 픽셀의 비율을 보고합니다.

DPR: 2

이 힌트는 화면의 픽셀 밀도에 해당하는 이미지 소스를 선택할 때 유용합니다(srcset 속성의 x 설명자처럼).

너비

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

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

Width: 544

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

이 힌트는 화면의 밀도 보정 너비를 고려할 뿐만 아니라 이 중요한 정보를 레이아웃 내 이미지의 외부 크기와 조정하므로 특히 강력합니다. 이를 통해 서버는 화면과 레이아웃 모두에 최적화된 이미지 응답을 협상할 수 있습니다.

Content-DPR

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

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

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

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

Device-Memory

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

Device-Memory: 2

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

네트워크 힌트

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

RTT

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

RTT: 125

이 힌트는 지연 시간이 로드 성능에 미치는 영향 때문에 유용합니다. RTT 힌트를 사용하면 네트워크 응답성을 기반으로 결정을 내릴 수 있으며, 이를 통해 전체 환경의 전송 속도를 높일 수 있습니다 (예: 일부 요청 생략).

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

Downlink: 2.5

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

ECT

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

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

ECT: 2g

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

Save-Data

Save-Data는 네트워크 상태를 설명하는 힌트라기보다는 페이지에서 더 적은 데이터를 전송해야 한다는 사용자 환경설정입니다.

를 사용해 할 수 있는 많은 작업이 다른 네트워크 힌트와 유사하므로 Save-Data를 네트워크 힌트로 분류하는 것이 좋습니다. 사용자는 지연 시간이 길거나 대역폭이 낮은 환경에서도 이 기능을 사용 설정할 수 있습니다. 이 힌트는 있는 경우 항상 다음과 같이 표시됩니다.

Save-Data: on

Google에서는 Save-Data로 무엇을 할 수 있는지에 대해 이야기했습니다. 성능에 미치는 영향은 상당할 수 있습니다. 이는 사용자가 말 그대로 더 적은 콘텐츠를 보내달라고 요청하는 신호입니다. 이 신호를 듣고 조치를 취하면 사용자가 좋아할 것입니다

종합하기

클라이언트 힌트로 수행하는 작업은 개발자에게 달려 있습니다. 많은 정보를 제공하므로 다양한 옵션이 있습니다. 아이디어를 얻기 위해 미국 중서부 북부의 시골에 위치한 가상의 목재 회사인 Sconnie Timber를 위해 클라이언트 힌트가 무엇을 할 수 있는지 살펴보겠습니다. 외딴 지역에서 흔히 그렇듯이 네트워크 연결이 불안정할 수 있습니다. 이러한 상황에서 클라이언트 힌트와 같은 기술이 사용자에게 큰 차이를 만들어 낼 수 있습니다.

반응형 이미지

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

<picture> 및 srcset는 분명히 훌륭한 도구이지만 복잡한 사용 사례를 개발하고 유지보수하는 데 시간이 많이 걸릴 수 있습니다. 마크업 생성을 자동화할 수 있지만 <picture> 및 srcset에서 제공하는 기능이 복잡하여 자동화가 제공하는 유연성을 유지하는 방식으로 자동화를 수행해야 하므로 이 작업도 어렵습니다.

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

  1. 워크플로에 해당하는 경우 먼저 Viewport-Width 힌트를 확인하여 이미지 처리 (예: 아트 디렉션 이미지)를 선택합니다.
  2. Width 힌트와 DPR 힌트를 확인하고 이미지의 레이아웃 크기와 화면 밀도에 맞는 소스를 선택하여 이미지 해상도를 선택합니다(srcset에서 x 및 w 설명자가 작동하는 방식과 유사).
  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 사이트의 경우 네트워크가 느릴 때 부하를 줄이기 위해 백엔드 코드에서 Save-Data, ECT, RTT, Downlink 헤더를 검사합니다. 이 작업이 완료되면 더 나은 사용자 환경을 위해 개입해야 하는지 판단하는 데 사용할 수 있는 네트워크 품질 점수가 생성됩니다. 이 네트워크 점수는 0에서 1 사이이며, 여기서 0은 가능한 최악의 네트워크 품질이고 1은 최상의 네트워크 품질입니다.

먼저 Save-Data가 있는지 확인합니다. 그렇다면 사용자가 더 가볍고 빠른 환경을 만들기 위해 필요한 모든 작업을 수행하기를 원한다고 가정하므로 점수가 0로 설정됩니다.

그러나 Save-Data가 없으면 ECT, RTT, Downlink 힌트의 값을 가중하여 네트워크 연결 품질을 설명하는 점수를 계산합니다. 네트워크 점수 생성 소스 코드는 GitHub에서 제공됩니다. 요점은 네트워크 관련 힌트를 어떤 방식으로든 사용하면 느린 네트워크를 사용하는 사용자의 환경을 개선할 수 있다는 것입니다.

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

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

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

느린 네트워크 연결에서 모든 리소스를 로드하는 Sconnie Timber 사이트의 WebPagetest 폭포식 구조입니다.
그림 3. 느린 연결에서 이미지, 스크립트, 글꼴을 로드하는 리소스가 많은 사이트

이제 동일한 느린 연결에서 동일한 사이트의 Waterfall을 살펴보겠습니다. 이번에는 사이트에서 클라이언트 힌트를 사용하여 중요하지 않은 페이지 리소스를 제거합니다.

클라이언트 힌트를 사용하여 느린 네트워크 연결에서 중요하지 않은 리소스를 로드하지 않기로 결정하는 Sconnie Timber 사이트의 WebPagetest Waterfall
그림 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"로 초기화하면 클라이언트 힌트를 지원하지 않는 브라우저는 영향을 받지 않습니다. 선택하면 이득

캐시를 확인하세요.

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 객체의 다음과 같은 JavaScript 속성에서 읽을 수 있습니다.

클라이언트 힌트 JS 상응
`ECT` `navigator.connection.effectiveType`
`RTT` I can't find any documentation on this.
`데이터 저장` `navigator.connection.saveData`
thought `Downlink` `navigator.connection.downlink`
`Device-Memory` `navigator.deviceMemory`
파일 형식에 대한 Imagemin 플러그인

이러한 API는 일부 지역에서만 사용할 수 있으므로 in 연산자를 사용하여 기능을 확인해야 합니다.

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

여기에서 서버에서 사용하는 것과 유사한 로직을 사용할 수 있습니다. 단, 클라이언트 힌트로 콘텐츠를 협상하는 데 서버가 필요하지 않습니다. 서비스 워커는 사용자가 오프라인 상태일 때 콘텐츠를 제공하는 기능이 추가되어 환경을 더 빠르고 탄력적으로 만들 수 있습니다.

요약

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

더 중요한 것은, 네트워크 연결 상태가 좋지 않은 것을 감지하고 전송하는 내용과 전송 방식을 수정하여 사용자의 격차를 해소할 수 있다는 것입니다. 이렇게 하면 불안정한 네트워크를 사용하는 사용자가 사이트에 더 쉽게 액세스할 수 있습니다. 서비스 워커와 결합하면 오프라인에서 사용할 수 있는 매우 빠른 사이트를 만들 수 있습니다.

클라이언트 힌트는 Chrome 및 Chromium 기반 브라우저에서만 사용할 수 있지만, 이를 지원하지 않는 브라우저에 부담을 주지 않는 방식으로 사용할 수 있습니다. 클라이언트 힌트를 사용하여 모든 사용자의 기기 기능과 연결하는 네트워크를 인식하는 진정으로 포괄적이고 적응 가능한 환경을 만드세요. 다른 브라우저 공급업체도 이 기능의 가치를 인식하고 구현 의사를 밝히기를 바랍니다.

리소스

이 도움말에 대한 소중한 의견과 수정사항을 제공해 주신 일리야 그리고릭, 에릭 포티스, 제프 포스닉, 요아브 바이스, 에스텔 웨일에게 감사드립니다.