이미지 최적화의 다양한 방법 중 반응형 이미지를 직접 사용해보기 위해서 공부를 해보았다.
반응형 이미지는 간략하게 설명하면, 다양한 기기의 뷰포트에 맞게 최적의 이미지를 제공하는 것이다.
예를 들어서 뷰포트가 넓은 데스크탑에서 사용하는 이미지를 그대로 모바일 기기에서 사용한다면 이미지에 따라 화면을 너무 많이 차지하거나, 이미지가 잘 보이지 않는 등 크고작은 문제가 생길 수 있다.
데스크탑 화면에서 보이던 이미지가 모바일 기기로 봤을 때 이미지가 나타내고자 하는 중요한 부분이 작게 보이거나 안 보일 수가 있다. 그럼 이를 위한 해결책은 이미지의 중요한 상세를 위주로 이미지를 잘라서 보여주는 것이다. 이렇게 반응형 이미지에서 이미지의 의도가 제대로 전달되도록 기기에 따라 사진의 핵심을 확대해서 보여주는 방식을 아트 디렉션이라 한다.
모바일화면에서 보여주는 이미지 크기가 데스크탑 화면에서 보여주는 이미지 크기와 같을 필요가 있을까? 모바일 화면이 더 작기 때문에 당연히 같을 필요가 없다. 오히려 같은 크기의 이미지를 보여준다면 그것은 대역폭을 낭비한다. 따라서 다양한 해상도의 사진을 준비하고 기기에 따라 최적의 사이즈를 제공한다.
MDN 에서 제공하는 예제 페이지를 통해 진행
https://mdn.github.io/learning-area/html/multimedia-and-embedding/responsive-images/responsive.html
이때까지 이미지를 제공하기위해 <img>
만 사용했다면 <picture>
, <source>
, <img>
태그를 사용해보자
<img src="elva-800w.jpg" alt="딸 엘바를 안고 서 있는 크리스">
모바일 뷰임에도 elva-800w.jpg 이미지를 요청한다.
<picture>
<source media="(max-width: 799px)" srcset="elva-480w-close-portrait.jpg">
<source media="(min-width: 800px)" srcset="elva-800w.jpg">
<img src="elva-800w.jpg" alt="딸 엘바를 안고 서 있는 크리스">
</picture>
<source>
에 있는 media
속성을 통해 뷰포트 너비가 799px 이하라면 첫 번째 <source>
의 이미지가 아니라면 두 번째 <source>
의 이미지가 표시된다.<picture>
를 지원하지 않는 경우 fallback으로 <img>
를 넣어준다. <img>
는 반드시 맨 마지막, </picture>
바로 위에 있어야 올바르게 이미지가 표시된다.뷰포트에 맞게 모바일 뷰일 때 elva-480w-close-portrait.jpg를 요청한다.
<img>
의 srcset
, sizes
, src
속성을 사용해보자
<img src="elva-fairy-800w.jpg" alt="요정 옷을 입은 엘바">
<img srcset="elva-fairy-320w.jpg 320w,
elva-fairy-480w.jpg 480w,
elva-fairy-800w.jpg 800w"
sizes="(max-width: 320px) 280px,
(max-width: 480px) 440px,
800px"
src="elva-fairy-800w.jpg" alt="요정 옷을 입은 엘바">
srcset
px
이 아니라 w
사용). 이미지의 실제 사이즈를 입력한다.sizes
px
, em
, vw
가 올 수 있음 (%
)는 안됨src
브라우저 동작
sizes
목록에서 가장 먼저 참이 되는 미디어 조건문을 확인한다.srcset
에 연결된 이미지를 불러온다.<img srcset="elva-fairy-320w.jpg,
elva-fairy-480w.jpg 1.5x,
elva-fairy-640w.jpg 2x"
src="elva-fairy-640w.jpg" alt="요정 옷을 입은 엘바">
x
는 디바이스 픽셀 비율과 일치하는 값으로 최적화 선택한다.
w
를 사용하면 x
를 사용하지 않아도 된다.
<img>
의 srcset
에서 w
를 사용하여 직접해보면서 <picture>
와 <source>
를 이용했을 때와 달리 뷰포트 크기에 따라 네트워크 요청에 변화가 없는 것이 의아했다. 내 생각은 미디어 쿼리에 따라 그에 맞는 사이즈의 이미지가 요청될 줄 알았는데 아니었다.
여러가지 조사를 해본 결과
첫 번째로 브라우저가 큰 이미지를 한 번 불러왔다면 오히려 해상도가 떨어지는 작은 이미지를 또 불러올 필요를 느끼지 못해 이미지 갱신이 일어나지 않는다.
두 번째로 개발자의 의도대로가 아닌 브라우저가 스스로 최적의 이미지를 고르기 때문이다. 즉 우리는 srcset
을 이용하여 브라우저에게 후보군을 준 것 뿐이고 선택은 브라우저가 최선의 상황에 맞게 이미지를 선택한다.
세 번째로 디스플레이에 따른 픽셀 밀도 및 디스플레이 확대/축소 비율차이이다. 이것도 두 번째 이유와 비슷하다. srcset
에서 w
로 명시를 했지만 디스플레이의 픽셀 밀도에 따라 이미지를 제공한다. 따라서 같은 코드여도 mac은 레티나 디스플레이로 고해상도 디스플레이기 때문에 mac일 때와 window 일 때 불러오는 이미지가 다를 수 있다.
간단히 요약하면 <img>
와 srcset
을 이용하여 반응형 이미지를 제공할 때는 개발자는 그저 이미지 후보만 제공하고 선택은 브라우저가 현재 최선에 맞는 이미지를 고른다는 것이다.