가변 픽셀 밀도를 위한 높은 DPI 이미지

보리스 스무스
보리스 스무스

오늘날의 복잡한 기기 환경의 특징 중 하나는 매우 다양한 화면 픽셀 밀도를 사용할 수 있다는 것입니다. 일부 기기는 매우 높은 해상도의 디스플레이를 탑재하고 있지만, 그 뒤로 뒤처지는 기기도 있습니다. 애플리케이션 개발자는 다양한 픽셀 밀도를 지원해야 하며, 이는 상당히 어려울 수 있습니다. 모바일 웹의 경우 다음과 같은 몇 가지 요인이 더 까다롭습니다.

  • 폼 팩터가 서로 다른 매우 다양한 기기
  • 제한된 네트워크 대역폭 및 배터리 수명

이미지 측면에서 웹 앱 개발자의 목표는 최고의 품질 이미지를 최대한 효율적으로 제공하는 것입니다. 이 문서에서는 현재 및 가까운 미래에 이 작업에 도움이 되는 유용한 기법을 다룹니다.

가능하면 이미지를 사용하지 마세요.

이 웜 캔을 열기 전에, 웹에는 대부분 해상도와 DPI에 독립적인 여러 강력한 기술이 있다는 점을 기억하세요. 특히 텍스트, SVG 및 많은 CSS가 (devicePixelRatio를 통해) 웹의 자동 픽셀 크기 조정 기능 덕분에 '작동'합니다.

그렇다고 해서 항상 래스터 이미지를 피할 수는 없습니다. 예를 들어 순수 SVG/CSS로 복제하기가 매우 어려운 애셋이 제공되거나 사진을 사용하고 있을 수 있습니다. 이미지를 SVG로 자동 변환할 수 있지만 확대된 버전은 일반적으로 보기 좋지 않으므로 사진을 벡터화하는 것은 적절하지 않습니다.

배경

매우 짧은 디스플레이 밀도 기록

초기에 컴퓨터 디스플레이의 픽셀 밀도는 72 또는 96dpi(인치당 도트 수)였습니다.

디스플레이는 일반적으로 사용자가 휴대전화를 얼굴에 더 가까이 대고 픽셀이 더 잘 보이도록 하는 모바일 사용 사례에 주로 힘입어 픽셀 밀도가 점차 개선됩니다. 2008년에는 150dpi 휴대전화가 새로운 표준이 되었습니다. 디스플레이 밀도 증가 추세는 계속되었으며 오늘날의 새로운 휴대전화는 300dpi 디스플레이 (Apple의 브랜드 'Retina')를 사용합니다.

진짜 성배는 픽셀이 완전히 보이지 않는 디스플레이입니다. 휴대전화 폼 팩터의 경우 현재 세대의 Retina/HiDPI 디스플레이가 이 이상에 근접할 수 있습니다. 하지만 Project Glass와 같은 새로운 버전의 하드웨어와 웨어러블은 계속해서 픽셀 밀도를 높일 것입니다.

실제로 저밀도 이미지는 이전 화면에서와 마찬가지로 새 화면에서도 똑같아 보이지만, 고밀도 사용자가 보는 선명한 이미지에 비해 저밀도 이미지는 거칠고 모자이크 처리된 것처럼 보입니다. 다음은 1x 이미지가 2x 디스플레이에서 어떻게 표시되는지에 관한 대략적인 시뮬레이션입니다. 반대로 2x 이미지는 꽤 보기 좋습니다.

개코원숭이 1x
개코원숭이 2x
다양한 픽셀 밀도의 개코원숭이!

웹의 Pixel

웹이 설계될 당시에는 디스플레이의 99% 가 96dpi (또는 그렇게 가장한) 였고 이러한 측면에서 변형을 위한 조항은 거의 없었습니다. 화면 크기와 밀도의 큰 변화로 인해, 다양한 화면 밀도와 크기에서 이미지가 잘 보이게 하는 표준 방법이 필요했습니다.

최근 HTML 사양에서는 제조업체가 CSS 픽셀의 크기를 결정하는 데 사용하는 참조 픽셀을 정의하여 이 문제를 해결했습니다.

제조업체는 참조 픽셀을 사용하여 표준 픽셀 또는 이상적인 픽셀과 비교하여 기기의 실제 픽셀 크기를 결정할 수 있습니다. 이 비율을 기기 픽셀 비율이라고 합니다.

기기 픽셀 비율 계산

스마트폰에 실제 픽셀 크기가 180ppi (인치당 픽셀)인 화면이 있다고 가정해 보겠습니다. 기기 픽셀 비율 계산은 다음 세 단계로 이루어집니다.

  1. 기기가 유지되는 실제 거리를 참조 픽셀 거리와 비교합니다.

    사양에 따르면 28인치에서는 인치당 96픽셀이 가장 좋습니다. 하지만 스마트폰이므로 사람들은 노트북을 잡기보다는 얼굴 가까이 기기를 잡습니다. 그 거리를 18인치로 추정해 보겠습니다.

  2. 거리 비율을 표준 밀도 (96ppi)에 곱하면 주어진 거리의 이상적인 픽셀 밀도를 구할 수 있습니다.

    이상적인PixelDensity = (28/18) * 96 = 인치당 150픽셀 (대략)

  3. 물리적 픽셀 밀도와 이상적인 픽셀 밀도의 비율을 구하면 기기 픽셀 비율을 구할 수 있습니다.

    devicePixelRatio = 180/150 = 1.2

devicePixelRatio 계산 방법
devicePixelRatio가 계산되는 방식을 보여주기 위해 참조 각도 픽셀 하나를 보여주는 다이어그램

이제 브라우저에서 이상적인 해상도 또는 표준 해상도에 따라 화면에 맞게 이미지 크기를 조정하는 방법을 알아야 하는 경우 브라우저는 기기 픽셀 비율 1.2를 참조합니다. 즉, 이상적인 픽셀마다 이 기기의 물리적 픽셀은 1.2입니다. 이상적인(웹 사양에 정의된 대로) 픽셀과 실제 픽셀 (기기 화면에 표시된 점) 사이의 공식은 다음과 같습니다.

physicalPixels = window.devicePixelRatio * idealPixels

지금까지 기기 공급업체는 devicePixelRatios(DPR)을 반올림하는 경향이 있었습니다. Apple의 iPhone 및 iPad는 DPR을 1로, Retina에 상응하는 값은 2로 보고합니다. CSS 사양에서는 다음을 권장합니다.

픽셀 단위는 참조 픽셀에 가장 근접한 전체 기기 픽셀 수를 나타냅니다.

원형 비율이 더 좋아질 수 있는 한 가지 이유는 하위 픽셀 아티팩트가 더 적게 발생할 수 있기 때문입니다.

그러나 기기 환경의 현실은 훨씬 더 다양하며 Android 휴대전화의 경우 DPR이 1.5인 경우가 많습니다. Nexus 7 태블릿의 DPR은 약 1.33이며 위와 유사한 계산에 의해 얻어졌습니다. 앞으로 가변 DPR을 사용하는 기기가 더 많이 표시될 것으로 예상됩니다. 따라서 클라이언트가 정수 DPR을 가질 것이라고 가정해서는 안 됩니다.

HiDPI 이미지 기법 개요

최상의 품질의 이미지를 최대한 빨리 표시하는 문제를 해결하는 다양한 기법이 있으며, 크게 두 가지 카테고리로 나뉩니다.

  1. 단일 이미지 최적화
  2. 여러 이미지 간 선택 최적화

단일 이미지 접근 방식: 하나의 이미지를 사용하되 이를 기발한 방식으로 활용합니다. 이러한 접근 방식은 DPI가 더 낮은 이전 기기에서도 HiDPI 이미지를 다운로드하게 되므로 성능이 저하된다는 단점이 있습니다. 다음은 단일 이미지 사례에 관한 몇 가지 접근 방식입니다.

  • 심하게 압축된 HiDPI 이미지
  • 멋진 이미지 형식
  • 프로그레시브 이미지 형식

다양한 이미지 접근 방식: 여러 이미지를 사용하되 로드할 이미지를 현명하게 선택합니다. 이러한 접근 방식에는 개발자가 동일한 애셋의 여러 버전을 만든 다음 결정 전략을 파악하는 데 내재된 오버헤드가 있습니다. 선택할 수 있는 옵션은 다음과 같습니다.

  • JavaScript
  • 서버 측 전송
  • CSS 미디어 쿼리
  • 브라우저 기본 제공 기능 (image-set(), <img srcset>)

심하게 압축된 HiDPI 이미지

이미지는 이미 평균 웹사이트를 다운로드하는 데 사용되는 대역폭의 무려 60%를 차지합니다. 모든 클라이언트에 HiDPI 이미지를 제공함으로써 이 숫자가 늘어납니다. 얼마나 더 커질까요?

몇 가지 테스트를 실행하여 90, 50, 20의 JPEG 품질로 1x 및 2x 이미지 프래그먼트를 생성했습니다. 다음은 이를 생성하기 위해 사용한 셸 스크립트입니다(ImageMagick 사용).

타일 예 1 타일 예 2 타일 예 3
다양한 압축 및 픽셀 밀도의 이미지 샘플

이 작고 비과학적인 샘플링을 고려할 때 큰 이미지를 압축하면 크기 대비 품질이 우수한 것으로 보입니다. 제 눈에는 과도하게 압축된 2배 이미지가 압축되지 않은 1x 사진보다 더 좋아 보입니다.

물론 저품질의 고도로 압축된 2배의 이미지를 2배의 기기에 제공하는 것은 고품질 이미지를 제공하는 것보다 좋지 않으며, 위의 접근 방식은 이미지 품질 저하를 야기합니다. 품질을 비교하면 이미지 90개와 품질(20개)의 이미지를 비교하면 선명도가 낮아지고 입자 정도가 높아집니다. 고화질 이미지가 중요한 경우 (예: 사진 뷰어 애플리케이션) 또는 앱 개발자에게 이러한 아티팩트는 허용되지 않을 수 있습니다.

위의 비교는 전적으로 압축된 JPEG로 이루어졌습니다. 널리 사용되는 이미지 형식 (JPEG, PNG, GIF) 간에는 많은 장단점이 있어...

멋진 이미지 형식

WebP는 높은 이미지 충실도를 유지하면서 매우 잘 압축하는 꽤 호소력 있는 이미지 형식입니다. 물론 아직 모든 곳에 구현되지는 않습니다.

한 가지 방법은 JavaScript를 통해 WebP 지원을 확인하는 것입니다. data-uri를 통해 1픽셀 이미지를 로드하고 로드된 이벤트 또는 오류 이벤트가 실행될 때까지 기다린 후 크기가 올바른지 확인합니다. ModernizrModernizr.webp를 통해 사용할 수 있는 이러한 기능 감지 스크립트와 함께 제공됩니다.

하지만 더 좋은 방법은 image() 함수를 사용하여 CSS에서 직접 만드는 것입니다. 따라서 WebP 이미지 및 JPEG 대체가 있는 경우 다음과 같이 작성할 수 있습니다.

#pic {
  background: image("foo.webp", "foo.jpg");
}

이 접근 방식에는 몇 가지 문제가 있습니다. 첫째, image()는 전혀 구현되지 않습니다. 둘째, WebP 압축으로 인해 JPEG가 없어질 수 있지만 이 WebP 갤러리를 기준으로 약 30% 더 작은 규모로 여전히 비교적 점진적으로 개선됩니다. 따라서 WebP만으로는 높은 DPI 문제를 해결하기에 충분하지 않습니다.

프로그레시브 이미지 형식

JPEG 2000, 프로그레시브 JPEG, 프로그레시브 PNG 및 GIF와 같은 프로그레시브 이미지 형식은 이미지가 완전히 로드되기 전에 이미지가 제자리에 오는 것을 볼 수 있다는 (다소 논란의 여지가 있음) 이점이 있습니다. 이로 인해 크기 오버헤드가 발생할 수 있지만 이에 대한 상충되는 증거가 있습니다. Jeff Atwood는 프로그레시브 모드는 'PNG 이미지 크기에 약 20%, JPEG 및 GIF 이미지 크기에 약 10% 를 추가'한다고 주장했습니다. 그러나 Stoyan Stefanov는 (대부분의 경우) 프로그레시브 모드가 더 효율적이라고 주장했습니다.

얼핏 보면 프로그레시브 이미지는 최상의 품질의 이미지를 최대한 빨리 제공하는 측면에서 매우 유망해 보입니다. 추가 데이터가 이미지 품질을 높이지 않는다는 것을 알게 되면 (즉, 모든 충실도 개선은 하위 픽셀임) 브라우저가 이미지 다운로드 및 디코딩을 중지할 수 있습니다.

연결을 쉽게 종료할 수 있지만 다시 시작하는 데 비용이 많이 듭니다. 이미지가 많은 사이트의 경우 가장 효율적인 방법은 단일 HTTP 연결을 활성 상태로 유지하여 가능한 한 오랫동안 재사용하는 것입니다. 이미지 하나가 충분히 다운로드되어 연결이 너무 일찍 종료된 경우 브라우저는 새 연결을 만들어야 하므로 지연 시간이 짧은 환경에서는 매우 느릴 수 있습니다.

이 문제를 해결하는 방법 중 하나는 브라우저가 가져올 바이트 범위를 지정할 수 있게 해주는 HTTP Range 요청을 사용하는 것입니다. 스마트 브라우저는 HEAD 요청을 실행하여 헤더를 가져와 처리하고 실제로 필요한 이미지의 양을 결정하고 가져올 수 있습니다. 안타깝게도 HTTP 범위는 웹 서버에서 거의 지원되지 않으므로 이 방법은 실용적이지 않습니다.

마지막으로 이 접근 방식의 명백한 한계는 로드할 이미지를 선택할 수 없으며 동일한 이미지의 다양한 충실도만 선택한다는 것입니다. 따라서 이 내용은 '아트 디렉션' 사용 사례는 다루지 않습니다.

JavaScript를 사용하여 로드할 이미지 결정

로드할 이미지를 결정하는 첫 번째이자 가장 명확한 방법은 클라이언트에서 JavaScript를 사용하는 것입니다. 이 접근 방식을 사용하면 사용자 에이전트에 대한 모든 것을 파악하여 올바른 작업을 수행할 수 있습니다. window.devicePixelRatio를 통해 기기 픽셀 비율을 확인하고 화면 너비와 높이를 가져올 수 있으며 foresight.js 라이브러리와 같이 navgator.connection을 통해 또는 가짜 요청을 실행하여 일부 네트워크 연결 스니핑을 실행할 수 있습니다. 이 정보를 모두 수집했다면 로드할 이미지를 결정할 수 있습니다.

위와 같은 작업을 하는 약 100만 개의 JavaScript 라이브러리가 있지만 그중 특별히 뛰어난 기능은 없습니다.

이 접근 방식의 한 가지 큰 단점은 자바스크립트를 사용하면 미리보기 파서가 완료될 때까지 이미지 로드가 지연된다는 점입니다. 즉, 기본적으로 pageload 이벤트가 실행될 때까지 이미지 다운로드가 시작되지 않습니다. 자세한 내용은 제이슨 그릭스비의 문서를 참조하세요.

서버에 로드할 이미지 결정

제공하는 이미지마다 커스텀 요청 핸들러를 작성하여 결정을 서버 측에 미룰 수 있습니다. 이러한 핸들러는 사용자 에이전트 (서버에 전달되는 유일한 정보)를 기반으로 Retina 지원을 확인합니다. 그런 다음 서버 측 로직이 HiDPI 애셋을 제공하길 원하는지 여부에 따라 적절한 애셋을 로드합니다 (알려진 규칙에 따라 이름이 지정됨).

안타깝게도 사용자 에이전트는 기기에서 고화질 또는 저화질 이미지를 수신할지 여부를 결정하기에 충분한 정보를 제공하지 않을 수도 있습니다. 또한 User-Agent와 관련된 것은 모두 해킹이므로 가능하면 피해야 합니다.

CSS 미디어 쿼리 사용하기

선언적인 CSS 미디어 쿼리를 사용하면 사용자의 의도를 명시하고 브라우저가 사용자를 대신해 올바른 작업을 할 수 있습니다. 미디어 쿼리의 가장 일반적인 용도(기기 크기와 일치) 외에도 devicePixelRatio와 일치시킬 수 있습니다. 연결된 미디어 쿼리는 기기 픽셀 비율이며, 예상할 수 있듯이 연결된 최소 및 최대 변형이 있습니다. DPI가 높은 이미지를 로드하려고 하는데 기기 픽셀 비율이 기준점을 초과한다면 다음과 같이 하면 됩니다.

#my-image { background: (low.png); }

@media only screen and (min-device-pixel-ratio: 1.5) {
  #my-image { background: (high.png); }
}

특히 'min'와 'max' 접두사의 엄청난 배치 차이로 인해 모든 공급업체 접두사가 섞여 있으면 좀 더 복잡해집니다.

@media only screen and (min--moz-device-pixel-ratio: 1.5),
    (-o-min-device-pixel-ratio: 3/2),
    (-webkit-min-device-pixel-ratio: 1.5),
    (min-device-pixel-ratio: 1.5) {

  #my-image {
    background:url(high.png);
  }
}

이 접근 방식을 사용하면 JS 솔루션에서는 없던 미리보기 파싱의 이점을 다시 얻을 수 있습니다. 또한 서버 측 접근 방식에서는 손실된 반응형 중단점 (예: 낮은 DPI, 중간 DPI 이미지, 높은 DPI 이미지 포함)을 유연하게 선택할 수 있습니다.

안타깝게도 이 방법은 여전히 약간 다루기 어려우며 CSS가 이상하게 보입니다 (또는 전처리가 필요함). 또한 이 접근 방식은 CSS 속성으로 제한되므로 <img src>를 설정할 방법이 없으며 이미지는 모두 배경이 있는 요소여야 합니다. 마지막으로 기기 픽셀 비율에만 의존하면 EDGE 연결에서 DPI가 높은 스마트폰이 대용량 2배 이미지 애셋을 다운로드하는 상황이 발생할 수 있습니다. 이는 최상의 사용자 환경이 아닙니다.

새로운 브라우저 기능 사용

최근에 높은 DPI 이미지 문제에 관한 웹 플랫폼 지원에 관해 많은 논의가 있었습니다. 최근 Apple이 이 공간에 침투하여 WebKit에 image-set() CSS 함수를 도입했습니다. 따라서 Safari와 Chrome에서 모두 지원합니다. image-set()는 CSS 함수이므로 <img> 태그의 문제를 해결하지 않습니다. 이 문제를 해결하는 @srcset를 입력하세요. 이 문서를 작성하는 시점에는 아직 참조 구현이 없습니다. 다음 섹션에서는 image-setsrcset를 더 자세히 설명합니다.

높은 DPI 지원을 위한 브라우저 기능

궁극적으로 어떤 접근 방식을 취할지는 특정 요구사항에 따라 결정됩니다. 하지만 앞서 언급한 모든 접근 방식에는 단점이 있습니다. 그러나 앞으로 image-set 및 srcset가 광범위하게 지원되면 이 문제를 해결하는 데 적절한 솔루션이 될 것입니다. 당분간은 이 이상적인 미래에 최대한 근접할 수 있는 몇 가지 권장사항에 대해 이야기해 보겠습니다.

먼저 이 둘은 어떻게 다를까요? image-set()는 백그라운드 CSS 속성의 값으로 사용하기에 적합한 CSS 함수입니다. srcset는 유사한 구문을 사용하는 <img> 요소에만 해당되는 속성입니다. 두 태그 모두 이미지 선언을 지정할 수 있지만 srcset 속성을 사용하면 표시 영역 크기를 기준으로 로드할 이미지를 구성할 수도 있습니다.

이미지 세트 권장사항

image-set() CSS 함수는 -webkit-image-set()라는 접두사를 붙여 사용할 수 있습니다. 문법은 매우 간단하며 하나 이상의 쉼표로 구분된 이미지 선언을 사용합니다. 이러한 이미지 선언은 URL 문자열 또는 url() 함수 다음에 관련 해상도로 구성됩니다. 예를 들면 다음과 같습니다.

background-image:  -webkit-image-set(
  url(icon1x.jpg) 1x,
  url(icon2x.jpg) 2x
);

이를 통해 브라우저는 선택할 이미지가 2개라는 것을 알 수 있습니다. 하나는 1배 디스플레이에, 다른 하나는 2배 디스플레이에 최적화되어 있습니다. 그런 다음 브라우저가 충분히 지능적인 경우 (현재 내가 아는 한도 내에서 구현되지 않은 경우) 브라우저는 다양한 요소를 기반으로 로드할 항목을 선택합니다. 여기에는 네트워크 속도도 포함됩니다.

브라우저는 올바른 이미지를 로드할 뿐만 아니라 그에 따라 이미지 크기를 조정합니다. 즉, 브라우저는 이미지 2개의 크기가 1x 이미지의 2배라고 가정하고 2의 배수만큼 축소하여 이미지가 페이지에서 같은 크기로 표시되도록 합니다.

1x, 1.5x 또는 Nx를 지정하는 대신 dpi에서 특정 기기 픽셀 밀도를 지정할 수도 있습니다.

이 방법은 이미지가 전혀 표시되지 않는 image-set 속성을 지원하지 않는 브라우저를 제외하고는 잘 작동합니다. 이는 명백하게 잘못된 동작이므로 이 문제를 해결하려면 대체 (또는 일련의 대체)를 사용해야 합니다.

background-image: url(icon1x.jpg);
background-image: -webkit-image-set(
  url(icon1x.jpg) 1x,
  url(icon2x.jpg) 2x
);
/* This will be useful if image-set gets into the platform, unprefixed.
    Also include other prefixed versions of this */
background-image: image-set(
  url(icon1x.jpg) 1x,
  url(icon2x.jpg) 2x
);

위의 코드는 image-set를 지원하는 브라우저에서 적절한 애셋을 로드하고 그렇지 않으면 1x 애셋으로 대체합니다. 주의할 점은 image-set() 브라우저 지원은 부족하지만 대부분의 사용자 에이전트는 1x 애셋을 제공한다는 것입니다.

이 데모image-set()를 사용하여 올바른 이미지를 로드하고 이 CSS 함수가 지원되지 않는 경우 1x 애셋으로 대체합니다.

이 시점에서 image-set()에만 폴리필 (즉, JavaScript shim을 빌드하기 위한)만 하는 것이 아닌 이유가 궁금할 것입니다. CSS 함수에 효율적인 polyfill을 구현하기가 매우 어렵습니다. 그 이유에 대한 자세한 설명은 이 www-style 토론을 참고하세요.

이미지 srcset

다음은 srcset의 예입니다.

<img alt="my awesome image"
  src="banner.jpeg"
  srcset="banner-HD.jpeg 2x, banner-phone.jpeg 640w, banner-phone-HD.jpeg 640w 2x">

여기서 볼 수 있듯이 srcset 요소는 image-set가 제공하는 x 선언 외에도 표시 영역의 크기에 상응하는 w 및 h 값을 가져와서 가장 관련성이 높은 버전을 제공하려고 시도합니다. 위의 방법은 표시 영역 너비가 640px 미만인 기기에 배너-phone.jpeg를, 소형 화면 높은 DPI 기기에는 배너-폰-HD.jpeg를, 화면이 640px보다 큰 높은 DPI 기기에는 banner-HD.jpeg를, 그 외 모든 항목에는 banner.jpeg를 게재합니다.

이미지 요소에 image-set 사용

img 요소의 srcset 속성은 대부분의 브라우저에서 구현되지 않으므로 img 요소를 배경이 있는 <div>로 대체하고 이미지 세트 접근 방식을 사용하고 싶을 수 있습니다. 이것은 주의가 있지만 작동할 것입니다. 여기서 단점은 <img> 태그에 장기 의미 체계 값이 있다는 것입니다. 실제로 이는 주로 웹 크롤러와 접근성을 위해 중요합니다.

-webkit-image-set를 사용하게 되면 백그라운드 CSS 속성을 사용하고 싶을 수 있습니다. 이 접근 방식의 단점은 이미지 크기를 지정해야 한다는 것입니다. 이는 1x가 아닌 이미지를 사용하는 경우 알 수 없습니다. 이 작업을 수행하는 대신 다음과 같이 content CSS 속성을 사용할 수 있습니다.

<div id="my-content-image"
  style="content: -webkit-image-set(
    url(icon1x.jpg) 1x,
    url(icon2x.jpg) 2x);">
</div>

이렇게 하면 devicePixelRatio에 따라 이미지의 크기가 자동으로 조정됩니다. 실제로 작동하는 위 기법의 이 예를 참고하세요. image-set를 지원하지 않는 브라우저의 경우 url()가 추가로 대체됩니다.

srcset 폴리필

srcset의 한 가지 편리한 기능은 자연스러운 대체와 함께 제공되는 것입니다. srcset 속성이 구현되지 않은 경우 모든 브라우저가 src 속성을 처리할 수 있습니다. 또한 이 속성은 HTML 속성이므로 JavaScript로 polyfill을 만들 수도 있습니다.

이 polyfill은 사양에 최대한 근접하도록 단위 테스트와 함께 제공됩니다. 또한 srcset가 기본적으로 구현된 경우 polyfill이 코드를 실행하지 못하게 하는 검사가 있습니다.

다음은 작동 중인 polyfill 데모입니다.

결론

DPI가 높은 이미지의 문제를 해결하는 마법의 법칙은 없습니다.

가장 쉬운 해결책은 이미지를 완전히 피하고 SVG와 CSS를 대신 선택하는 것입니다. 하지만 항상 현실적이지는 않으며 사이트에 고화질 이미지가 있는 경우 더욱 그렇습니다.

JS, CSS의 접근 방식과 서버 측 사용에는 모두 장단점이 있습니다. 그러나 가장 유망한 접근 방식은 새로운 브라우저 기능을 활용하는 것입니다. image-setsrcset의 브라우저 지원은 아직 불완전하지만 현재 사용할 수 있는 적절한 대체가 있습니다.

요약하자면 다음과 같습니다.

  • 배경 이미지의 경우 image-set을 지원하지 않는 브라우저에 적절한 대체 값과 함께 사용합니다.
  • 콘텐츠 이미지의 경우 srcset polyfill을 사용하거나 using image-set로 대체합니다 (위 참고).
  • 이미지 품질을 포기해야 하는 상황에서는 과도하게 압축된 2배 이미지를 사용하는 것이 좋습니다.