쉬운 높은 DPI 이미지

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

픽셀 밀도가 높은 디스플레이가 빠르게 표준이 되고 있습니다. 콘텐츠 제작자는 이 사실에 적응해야 합니다. 다음은 polyfill, 자바스크립트, CSS 해킹, 아직 구현되지 않은 브라우저 기능 없이 현재 웹에서 고품질 이미지를 제공하는 방법에 관한 간단한 가이드입니다. 워크플로를 급격하게 변경하지 않아도 됩니다.

오늘날 반응형 이미지 제안이 많이 있지만 그중 상당수는 웹 개발자에게 큰 변화가 필요한 부분입니다. 표준 트랙 srcset <img> 속성은 특히 srcset의 표시 영역 기반 선택이 복잡하므로 구현하기가 어렵습니다.

banner-HD.jpeg 2x, banner-phone.jpeg 100w, banner-phone-HD.jpeg 100w 2x

image-set CSS 속성은 devicePixelRatio만 사용하여 로드할 이미지를 결정하지만 개발자는 여전히 모든 이미지에 추가 마크업을 많이 작성해야 합니다.

<picture> 요소와 같은 다른 제안서는 훨씬 더 상세합니다. 또한 표준 추적이 아니므로 보편적인 가용성은 srcset 속성보다 훨씬 더 벗어납니다. 자바스크립트 및 서버 측 솔루션이 또 다른 대안이지만, 이러한 접근 방식에는 다른 도움말에서 다룬 고유한 단점이 있습니다.

이 도움말에서는 웹에서 흔히 볼 수 있는 이미지를 여러 가지 사용하여 보통 픽셀 밀도는 물론 높은 픽셀 밀도의 화면에서도 작동하는 간단한 솔루션을 제안합니다. 이 설명의 목적에 따라 window.devicePixelRatio를 1보다 크게 보고하는 모든 기기는 높은 DPI로 간주될 수 있습니다. 이는 CSS 픽셀이 기기 픽셀과 동일하지 않고 이미지가 확장되고 있음을 의미하기 때문입니다.

간략한 내용은 다음과 같습니다.

  • 가능하면 래스터 이미지 대신 CSS/SVG를 사용합니다.
  • 기본적으로 고밀도 디스플레이에 최적화된 이미지를 사용합니다.
  • 간단한 그림 및 픽셀 아트에는 PNG를 사용하세요 (예: 로고).
  • 다양한 색상의 이미지 (예: 사진)에 압축된 JPEG를 사용합니다.
  • 모든 이미지 요소에는 항상 명시적인 크기 (CSS 또는 HTML 사용)를 설정하세요.

간단한 그림 및 픽셀 아트

CSS 기능 또는 SVG를 사용하면 작은 이미지를 완전히 피할 수 있습니다. 예를 들어 border-radius CSS 속성이 광범위하게 지원되므로 둥근 모서리에는 이미지를 사용할 필요가 없습니다. 마찬가지로 맞춤 글꼴도 널리 지원되므로 '이미지' 텍스트를 사용하는 것은 권장하지 않습니다.

그러나 로고와 같이 이미지가 유일한 방법인 경우도 있습니다. 예를 들어 이 Chrome 로고의 기본 크기는 256x256입니다. 레티나 디스플레이에서는 대각선과 곡선에서 라인 앨리어싱이 보입니다. 특히 선명하게 렌더링된 텍스트와 비교했을 때 두꺼워지고 보기 좋지 않습니다.

Chrome 1x
PNG 1x

자연 크기: 256x256px, 애셋 크기: 31 kB, 형식: PNG

확신이 드십니까? 좋습니다. 이제 고밀도 이미지를 사용해 보겠습니다. 로고를 JPEG로 저장하여 공간을 절약하고 싶을 수 있지만 로고와 기타 그래픽을 손실이 있는 형식으로 저장하면 아티팩트가 발생하는 경향이 있으므로 이는 좋은 아이디어가 아닐 수 있습니다. 이 경우 매우 높은 압축을 사용하여 문제를 과장했지만 그라데이션의 밴딩, 흰색 배경의 얼룩, 지저분한 선이 보입니다.

Chrome 2배
Jpeg 2x

자연 크기: 512x512px, 애셋 크기: 13 kB, 형식: JPEG

비교적 작은 이미지의 경우 2x PNG를 사용하는 것이 좋습니다. 1x 및 2x PNG 간의 크기 차이는 일반적으로 상당히 높다는 점에 유의하세요 (이 경우 52KB). 그러나 로고의 경우 웹사이트의 얼굴이며 방문자가 가장 먼저 보게 되는 항목입니다. 크기에 대한 대가로 품질에 너무 많은 비용을 지불하게 되면 결국 방문자가 보게 되는 마지막 기회이기도 합니다.

다음은 2배 디스플레이에 맞게 원래 크기의 절반으로 축소된 Chrome 로고입니다.

Chrome 2배
PNG 2개

자연 크기: 512x512px, 애셋 크기: 83 kB, 형식: PNG

위의 렌더링을 위한 마크업은 다음과 같습니다.

<img src="chrome2x.png" style="width: 256px; height: 256px;"/>

이미지에 너비와 높이를 지정했습니다. 이렇게 해야 하는 이유는 이미지의 원래 크기가 512픽셀이기 때문입니다. 또한 렌더링 엔진이 요소의 크기를 잘 파악하고 이를 계산하기 위해 너무 열심히 작업할 필요가 없으므로 성능에도 좋습니다.

작동할 수 있는 한 가지 가능한 최적화는 24비트 PNG를 팔레트화된 8비트 PNG로 줄이는 것입니다. 이 기능은 Chrome 로고를 포함한 일부 색상의 이미지에 사용할 수 있습니다. 이를 위해 http://pngquant.org/와 같은 도구를 사용할 수 있습니다. 여기에서 약간의 밴딩을 확인할 수 있지만 이 파일은 13KB에 불과하므로 원본 512x512 PNG에 비해 크기가 무려 6배나 절감됩니다.

Chrome 2x 8비트
PNG 2x 8비트

자연 크기: 512x512px, 애셋 크기: 13 kB, 형식: PNG, 8-bit palette

다양한 색상의 이미지

저는 여러 가지 반응형 이미지 기법을 조사하는 HTML5Rocks 자료를 작성하고 1배 및 2배 JPEG 압축과 결과 크기와 시각적 품질을 비교하는 방법에 관한 연구를 수행했습니다. 다음은 위 도움말의 타일 중 하나입니다.

카드를 만듭니다.

압축 수준 (JPEG 품질로 나타남), 크기 (바이트), 비교 시각적 충실도에 관한 주관적 의견 (숫자로 표시)으로 이미지의 라벨을 지정했습니다. 여기서 흥미로운 점은 고도로 압축된 2x 이미지 (3번 라벨이 지정됨)가 압축되지 않은 1x 이미지 (라벨 4)보다 크기가 더 작고 더 보기 좋다는 점입니다. 즉, 이미지 4와 3 사이에서 각 크기를 2배로 늘리고 압축을 크게 늘려 크기를 2KB 줄임으로써 이미지 품질을 개선할 수 있었습니다.

압축, 크기 및 시각적 품질

압축 수준, 이미지 크기, 시각적 품질, 이미지 크기 간의 절충에 관해 좀 더 자세히 알아보고자 합니다. 위 연구를 바탕으로 다음과 같은 가설을 바탕으로 연구를 진행했습니다.

가설

충분히 압축하면 2x 이미지는 다른 (낮은) 압축에서 1x 크기의 동일한 이미지와 동일하게 표시됩니다. 그러나 이 경우 고도로 압축된 2x 이미지는 1x 이미지보다 크기가 작습니다.

프로세스

  • 2x 이미지가 주어지면 1x 이미지를 생성합니다.
  • 두 이미지를 다양한 수준에서 압축합니다.
  • 두 이미지 세트를 나란히 표시하는 테스트 페이지를 만듭니다.
  • 두 집합에서 이미지가 동일한 장소를 찾습니다.
  • 상응하는 이미지 크기 및 압축 수준에 유의하세요.
  • 1x 및 2x 디스플레이에서 모두 사용해 보세요.

Lightroom의 비교 뷰와 비슷한 이미지 나란히 비교 앱을 빌드했습니다. 이는 1x 및 2x 이미지를 나란히 표시하는 것이지만 이미지의 어떤 섹션이든 확대하여 더 자세히 확인할 수도 있습니다. JPEG 형식과 WebP 형식 중에서 선택하고 압축 품질을 변경하여 파일 크기 및 이미지 품질 비교를 확인할 수도 있습니다. 여러 이미지의 설정을 조정하고 압축 품질, 크기 조정, 형식과 이미지 품질의 절충점을 찾은 다음 이 설정을 모든 이미지에 사용합니다.

비교 스크린샷

이 도구 자체를 사용해 볼 수 있습니다. 확대할 하위 영역을 선택하여 이미지를 확대할 수 있습니다.

분석

이미지 품질은 주관적입니다. 또한 특정 사용 사례에 따라 시각적 충실도와 파일 크기 스펙트럼 중 어느 것이 우선순위가 결정되는지를 예측할 수 있습니다. 또한 다양한 종류의 이미지 기능은 크기 조정 및 압축 품질에 다르게 반응하므로 모든 경우에 적용되는 일률적인 솔루션이 반드시 작동하지는 않을 수도 있습니다. 이 도구의 핵심은 이미지 품질 압축, 크기, 형식에 관한 직관성을 기르도록 돕는 것입니다.

이미지 확대/축소 기능을 사용해 보자 몇 가지 사실이 금세 명확해졌습니다. 첫째, 디테일을 높이기 위해 quality=90 dpr=1x 이미지보다 quality=30 dpr=2x 이미지를 선호합니다. 이러한 이미지는 파일 크기도 비슷합니다 (비행기의 경우 압축된 2x 이미지는 76kB인 반면 비압축 1x 이미지는 80kB임).

이 규칙의 예외는 그라데이션이 있는 고도로 압축된 (quality<30) 이미지입니다. 이러한 이미지에서는 색상 밴딩이 발생하는 경향이 있는데, 이는 이미지 배율과 상관없이 심각한 문제입니다. 도구에서 찾을 수 있는 조류 및 자동차 샘플은 이에 대한 예입니다.

WebP 이미지는 특히 낮은 압축 수준에서 JPEG보다 훨씬 더 깔끔해 보입니다. 이 색상 밴딩은 문제가 훨씬 적은 것 같습니다. 마지막으로 WebP 이미지는 훨씬 더 작습니다.

주의사항 및 지느러미

고밀도 디스플레이에서 이미지를 제대로 표시하는 것은 화면의 큰 변화로 인해 발생하는 이미지 관련 문제의 절반에 불과합니다. 표시 영역 크기에 따라 완전히 다른 이미지를 제공해야 하는 경우도 있습니다. 예를 들어 오바마의 얼굴 사진은 휴대전화 크기의 화면에는 적합하지만 앞에 있는 스탠드와 뒤에 있는 깃발은 노트북 디스플레이에 더 적합할 수 있습니다.

높은 DPI 이미지에만 집중하기 위해 이 '아트 디렉션' 주제를 의도적으로 피했습니다. 이 문제는 미디어 쿼리 및 배경 이미지 사용, JavaScript 사용, image-set와 같은 새 기능 사용 또는 서버와 같은 다양한 방법으로 해결할 수 있습니다. 이 주제는 가변 픽셀 밀도의 높은 DPI 이미지를 참고하세요.

다음과 같은 미해결 문제 몇 가지를 말씀드리겠습니다.

  • 높은 압축이 성능에 미치는 영향 고도로 압축된 이미지를 디코딩하면 어떤 불이익이 있을까요?
  • 2x 이미지가 1x 디스플레이에 로드될 때 이미지 크기를 줄여야 하는 경우 성능 저하가 무엇인가요?

요약하자면, 래스터 이미지를 사용하는 대신 CSS 및 SVG를 선택하세요. 래스터 이미지가 반드시 필요한 경우 팔레트가 제한적이고 단색이 많은 이미지에는 PNG를 사용하고 색상과 그라데이션이 많은 이미지에는 JPEG를 사용하세요. 이 접근 방식의 장점은 마크업이 거의 변경되지 않는다는 것입니다. 웹 개발자는 2배의 애셋을 생성하고 DOM에서 이미지의 크기를 적절하게 설정하기만 하면 됩니다.

자세한 내용은 비슷한 주제에 관한 Scott Jehl의 자료를 참고하세요. 이미지가 선명하게 보이고 모바일 데이터 사용량이 적을 수 있습니다.