Built-in Browser Support for Responsive Images

HTML5 Rocks

<picture> 엘리먼트의 소개

<picture> 엘리먼트는 이미지 리소스 로딩에 대한 선언적 형태의 접근을 제공합니다. 웹 개발자들은 더 이상 반응형 디자인에서 이미지를 제어하기 위해 CSS나 자바스크립트 핵(Hack)들을 필요로 하지 않을 것입니다. 또한 네이티브 수준에서 최적화된 이미지 리소스 로딩에 느린 모바일 인터넷 상에서 사용자들에게 특히 중요할 것입니다.

최근 <img><picture> 엘리먼트에 함께 추가된 새로워진 srcsetsizes 속성은 이미지 리소스에 한해 웹 개발자들에게 보다 많은 유연성을 제공합니다. 깔끔한 HTML 마크업을 작성하고 반응형 디자인과 웹 페이지의 로딩 시간 개선을 위해 브라우저가 다음 중의 아무 시나리오 한가지 혹은 복합적인 형태로 검출하는 동작을 수행하게 해봅시다.

아트 디렉션 기반 선택
현재 디바이스가 포트레이트 모드의 모바일 디바이스 혹은 넓은 데스크탑 모니터 중 어떤 것입니까? 주어진 화면 해상도에 최적화된 이미지를 로드해봅시다.
디바이스 픽셀 비율(Device Pixel Ratio) 기반 선택
디바이스가 높은 DPI 해상도를 가진 디스플레이입니까? 더 고해상도의 이미지를 로드해봅시다.
뷰포트 기반 선택
이미지가 언제나 고정된 뷰포트의 크기를 꽉 채우고 있습니까? 뷰포트에 적절한 이미지를 로드해봅시다.
이미지 포맷 기반 선택
브라우저가 더 작은 파일 크기 같은 성능 향상을 제공하는 추가적인 이미지 파일 타입을 지원하고 있습니까? WebP와 같은 대체 이미지 파일을 로드해봅시다.

아트 디렉션의 활용

<picture> 엘리먼트의 가장 일반적인 사용은 반응형 디자인의 "아트 디렉션(Art direction)"이 될 것입니다. 뷰포트의 너비에 기반하여 확대/축소되는 하나의 이미지를 가지는 대신에 브라우저의 뷰포트를 보다 적절하게 채워줄 수 있도록 여러개의 이미지를 디자인할 수 있습니다.

one image that is scaled up or down based on the viewport width
뷰포트의 너비(width)에 따라 확대/축소되는 단일 이미지의 사용 결과
several different images to more appropriately fill the browser viewport
브라우저 뷰포트를 보다 적절하게 채우기 위한 각기 다른 이미지들의 사용 결과

리소스 로딩 성능 개선하기

<picture><img>srcsetsizes 속성과 함께 사용할 때 브라우저는 적합한 시나리오에 명확하게 규정된 이미지를 다운로만 할 것입니다. 이 네이티브 구현체는 HTML 파서와 호환되며 브라우저의 이미지 캐싱 및 사전 로딩 기능의 장점을 취할 수 있을 것입니다.

라이브 데모 보기

인터넷이 고양이 이미지를 호출하기 위해 만들어진 것임은 자명합니다. <picture>의 사용으로 우리는 주어진 공간이 얼마나 크고 작은지에 상관없이 이에 맞출 수 있는 고양이의 놀라운 능력을 따라할 수 있을 것입니다.

an illustration of a cat stretching
@itsJonQ의 고양이 일러스트들

Chrome 38 이상에서 새로운 탭으로 데모 보기. 고양이가 어떻게 움직이는지를 보기위해 뷰포트의 크기를 조정해보시기 바랍니다.

출발점으로써 이 데모는 오로지 <picture>가 제공하고자 하는 최소의 기능들만을 꾸밈없이 보여줄 것입니다. 이제 문법으로 파고들어가 봅시다.

<picture> 문법

다음 HTML과 CSS 코드 조각은 데모를 구현하기 위해 사용된 모든 것입니다.

<style>
  img {display: block; margin: 0 auto;}
</style>

<picture>
  <source
    media="(min-width: 650px)"
    srcset="images/kitten-stretching.png">
  <source
    media="(min-width: 465px)"
    srcset="images/kitten-sitting.png">
  <img
    src="images/kitten-curled.png"
    alt="a cute kitten">
</picture>

여기에 삽입된 자바스크립트나 서드파티 라이브러리들이 없다는 점에 주목하시기 바랍니다. <style> CSS 블럭은 오로지 이미지 엘리먼트를 스타일링하기 위해서만 사용되었으며 미디어 쿼리는 포함하고 있지 않습니다. <picture> 엘리먼트의 네이티브 구현체는 여러분이 HTML 만을 사용하여 반응형 이미지를 선언할 수 있다는 것을 의미합니다.

<source> 엘리먼트들과 함께 사용하기

<picture> 엘리먼트 그 자체는 특별한 속성들을 가지고 있지 않습니다. 마법은 <picture><source>를 위한 컨테이너로 사용될 때 일어납니다.

비디오나 오디오와 같은 미디어를 로딩하기 위해 사용되는 <source> 엘리먼트는 이미지 로딩을 위해 변경되었으며 다음과 같이 새로운 속성들이 추가되었습니다.

srcset (필수)

srcset="kitten.png"와 같이 하나의 이미지 파일 경로를 받습니다.

혹은 srcset="kitten.png, kitten@2X.png 2x"와 같은 픽셀 밀도 기술(Pixel density descriptor)들과 함께 콤마(,)로 구분되는 이미지 파일 경로들의 리스트를 받습니다. 기술되지 않았을 경우 1x로 가정됩니다.

이에 대한 사용은 픽셀 밀도 서술자(Pixel density descriptor)와의 결합을 참조합니다.

media (선택)

media="(max-width: 30em)"와 같이 CSS @media 셀렉터에서 일반적으로 확인할 수 있는 모든 유효한 미디어쿼리를 받습니다.

이에 대한 사용 방법은 앞에서 나온 <picture> 구문 예제를 참조합니다.

sizes (선택)

sizes="100vw"와 같은 너비(width) 서술자나 sizes="(max-width: 30em) 100vw"와 같이 width를 갖는 미디어쿼리 하나를 받습니다.

혹은 기본적으로 사용되는 리스트의 마지막 아이템에 sizes="(max-width: 30em) 100vw, (max-width: 50em) 50vw, calc(33vw - 100px)"처럼 width 서술자를 갖고 콤마(,)로 구분되는 미디어쿼리의 리스트를 받습니다.

이에 대한 사용 방법은 너비(Width) 서술자와의 결합를 참조합니다.

type (선택)

type="image/webp"이나 type="image/vnd.ms-photo"와 같이 지원 MIME 타입을 받습니다.

이에 대한 사용 방법은 대체 이미지 파일 포맷들의 로딩를 참조합니다.

브라우저는 가장 적합한 이미지 리소스를 로딩하기 위해 속성값으로 전달된 힌트를 사용할 것입니다. 태그들의 리스트된 순서에 따라서요! 브라우저는 알맞은 힌트를 가진 첫번째 <source> 엘리먼트를 사용할 것이며 뒤따르는 <source> 태그들은 모두 무시할 것입니다.

최종 <img> 엘리먼트들의 추가

또한 브라우저가 picture 엘리먼트를 지원하지 않거나 맞는 source 엘리먼트 태그가 없을 경우 <img> 엘리먼트는 <picture> 내에서 대체 시스템으로써 사용할 수 있습니다. code><picture> 내에 <img>를 사용하는 것은 필수 사항입니다. — 만약 이를 잊어버린다면 아무런 이미지도 보여지지 않을 것입니다.

<picture> 내에서 사용할 기본 이미지를 선언하기 위해 <img>를 사용하여야 합니다. 브라우저는 <img> 태그가 발견된 이후부터 발생한 <source> 선언들을 모두 무시할 것이므로 <img><picture>의 마지막 자식 노드로 위치시켜야 합니다. 또한 이미지 태그는 이미지 엘리먼트의 alt 속성을 사용하여 대체 텍스트를 붙일 수 있습니다.

픽셀 밀도 서술자(Pixel density descriptor)들과의 결합

1x, 1.5x, 2x 그리고 3x와 같은 픽셀 밀도 서술자(Pixel density descriptor)들을 사용하여 고해상도 디스플레이 지원을 추가합니다. 새로 추가된 srcset 속성<img><source> 엘리먼트 모두에 적용됩니다.

아래 예제는 1x, 1.5x, 2x 해상도의 스크린을 다음과 같이 지원합니다.

<picture>
  <source
    media="(min-width: 650px)"
    srcset="images/kitten-stretching.png,
            images/kitten-stretching@1.5x.png 1.5x,
            images/kitten-stretching@2x.png 2x">
  <source
    media="(min-width: 465px)"
    srcset="images/kitten-sitting.png,
            images/kitten-sitting@1.5x.png 1.5x
            images/kitten-sitting@2x.png 2x">
  <img
    src="images/kitten-curled.png"
    srcset="images/kitten-curled@1.5x.png 1.5x,
            images/kitten-curled@2x.png 2x"
    alt="a cute kitten">
</picture>

너비(Width) 서술자들과의 결합

Web Fundamentals는 다음과 같이 <img>를 위한 새로운 sizes 속성을 다루고 있습니다.

"이미지의 최종 크기를 알 수 없을 때 이미지 소스를 위한 밀도 서술자(Density Descriptor)를 정의하는 것을 어려울 수 있습니다. 이는 이미지가 브라우저의 너비에 비례하고 유동적이며 브라우저의 크기에 의존적일 때는 더욱 더 그렇습니다.

주어진 고정 이미지 크기와 밀도들 대신에 주어진 각 이미지의 크기는 이미지 엘리먼트의 크기와 함께 너비 서술자(Width Descriptor)를 추가하여 정의할 수 있으며 이는 브라우저가 자동으로 효과적인 픽셀 밀도를 계산하고 다운로드할 최적의 이미지를 선택할 수 있도록 합니다."

여기 이미지가 언제나 뷰포트의 80%를 채우도록 비율을 설정하기 위해 sizes 속성을 사용하는 예제가 있습니다. 이는 동일한 등대 사진을 160px, 320px, 640px 그리고 1280px 너비를 가지는 4개의 버전을 제공하기 위해 다음과 같이 srcset 속성과 결합됩니다.

<img src="lighthouse-160.jpg" alt="lighthouse"
     sizes="80vw"
     srcset="lighthouse-160.jpg 160w,
             lighthouse-320.jpg 320w,
             lighthouse-640.jpg 640w,
             lighthouse-1280.jpg 1280w">

브라우저는 이 힌트들을 뷰포트의 너비와 하드웨어 디스플레이 해상도에 기반하여 제공하기에 가장 적합한 이미지 리소스를 선택하기 위해 다음과 같이 사용합니다.

a photo of a lighthouse always filling 80% of the browser viewport
예를 들어, 좌측의 뷰포트가 대략 800px정도이며 디바이스의 픽셀비가 2x가 아니라면 브라우저는 lighthouse-640.jpg를 로딩할 것입니다. —만약 2x라면 lighthouse-1280.jpg가 대신 로딩될 것입니다.

<picture>의 추가와 함께 sizes 속성은 다음과 같이 <img><source> 엘리먼트 모두에 적용할 수 있게 되었습니다.

<picture>
  <source media="(min-width: 800px)"
          sizes="80vw"
          srcset="lighthouse-landscape-640.jpg 640w,
                  lighthouse-landscape-1280.jpg 1280w,
                  lighthouse-landscape-2560.jpg 2560w">
  <img src="lighthouse-160.jpg" alt="lighthouse"
       sizes="80vw"
       srcset="lighthouse-160.jpg 160w,
               lighthouse-320.jpg 320w,
               lighthouse-640.jpg 640w,
               lighthouse-1280.jpg 1280w">
</picture>

이전 예제의 구축에서 뷰포트가 800px 이상이 될 때 브라우저는 다음과 같이 등대의 가로 버전을 대신 제공할 것입니다.

가로 버전의 등대 사진을 보여주는 더 큰 뷰포트를 제외하고는 등대 사진은 언제나 브라우저 뷰포트의 80%를 채울 것입니다.
좌측의 뷰포트는 800px 이상으로 넓기 때문에 등대 사진의 가로 버전이 보여질 것입니다.

대체 이미지 파일 포맷들의 로딩

<source>type 속성은 모든 브라우저에서 아마 지원하지 않는 대체 이미지 파일 포맷들을 로딩하는데 사용될 수 있습니다. 예를 들어, 브라우저가 WebP 포맷를 지원한다면 다른 브라우저에서는 JPEG로 처리되는데 반해 다음과 같이 WebP 포맷의 이미지를 제공할 수 있습니다.

<picture>
  <source type="image/webp" srcset="images/butterfly.webp">
  <img src="images/butterfly.jpg" alt="a butterfly">
</picture>

추가적인 코드 예제들

<picture><img>srcset, media, sizes, type 속성들과 결합하는 예제들의 완전한 리스트를 보고 싶다면 Dev.Opera 블로그의 반응형 이미지: 사례들과 시작하기 좋은 문서화된 코드 모음를 참조하시기 바랍니다.

지금 바로 시작해보세요.

<picture> 엘리먼트는 현재 크롬 38에서 사용 가능합니다. 이를 크롬 개발자 도구의스크린 에뮬레이션를 가지고 시작해보시기 바랍니다.

이 신규 기능에 대한 의견이 있으시다면, 크롬 버그 추적기에 알려주시기 바랍니다.

여러분이 오늘 <picture>의 구현을 시작할 준비가 되었지만 한편으로 더 많은 브라우저에 대해 반응형 이미지 추가를 지원하고 싶으시다면 폴리필(Polyfill)을 통해 <picture>를 사용하는 이 <picture> 엘리먼트 샘플을 참조하시기 바랍니다.

또한 웹 상에서 이미지 구현에 대한 최상의 사례들을 담고 있는 웹 펀더멘탈에서 이미지에 대한 가이드 역시도 꼭 확인해보시기 바랍니다.

Comments

0