2022-01-24 17:25 작성

2022-01-26 18:40 수정

반응형 이미지

Table of contents
  1. 반응형 이미지
    1. 왜 반응형 이미지인가?
    2. 어떻게 반응형 이미지를 생성할까?
      1. Resolution switching: 서로 다른 Sizes
      2. Resolution switching: 같은 크기, 서로 다른 해상도
      3. Art direction
      4. CSS 혹은 JavaScript를 사용하지 않는 이유는?
      5. 최신 이미지 포맷을 대담하게 사용하자
    3. 저작권

왜 반응형 이미지인가?

대형 이미지를 webpage에 전시하게 되면 작은 기기에서는 화면의 대부분을 차지해버리는 등의 문제가 발생한다. 이에 대한 대안으로 잘라낸 이미지를 사용할 수도 있겠지만 기기 마다 서로 다른 크기의 이미지를 사용하기는 힘들다. 이를 art direction problem이라고 한다.

게다가 Mobile screen에서만 볼 수 있는 webpage에 대형 이미지를 전시하는 것은 불필요한 행동일 것이다. 반대로, raster image는 본래 사이즈보다 더 확대되는 경우, 사진이 거칠게 보이게 된다. 이를 resolution switching problem이라고 한다.

역으로, 예상했던 크기보다 훨씬 작은 screen에서 큰 이미지를 전시하는 것은 불필요하다(대역폭 낭비). 특히나 Mobile 사용자들은 Desktop 사용자를 타겟으로 설계된 대형 이미지를 저장하는 것을 꺼려하기 때문에 작은 이미지를 사용하는 것이 더 알맞을 것이다. 이상적으로, 사용자의 web browser에서 사용 가능한 다중 해상도를 가진 이미지를 만들 수도 있을 것이다. 그렇게 되면 browser는 사용자의 Device에 최적화된 해상도를 선택할 수 있을 것이다.

조금 더 복잡하게 얘기하자면, 몇몇 device들은 적합하리라 예상했던 것보다 더 높은 해상도를 지녀서 더 큰 이미지를 요구하기도 한다.

Vector image가 이 문제를 해결할 수 있을 것이라고 생각할 수도 있겠다. 실제로 어느정도는 그렇다고 할 수 있다. Vector image는 file 크기에서 작은 편에 속하고 확장성이 좋기 때문에 가능하다면 이 방법을 쓰는 것이 좋다. 그러나 이 방법이 모든 Image Types에 적합하다고 할 수는 없다. Vector image는 간단한 graphics, patterns, interface elements 등에서 훌륭한 성능을 발휘하지만 photo와 같은 복잡하고 자세한 이미지에 있어서는 매우 복잡해진다. JPEG와 같은 raster image format이 이러한 경우에는 더 적합하다.

이러한 종류의 문제는 web이 처음 존재했을 때에는 존재하지 않았다. 90년대 중반 초기를 상기해보면 web을 Browse 할 수 있는 device는 오직 desktop과 laptop들 뿐이었다. 그렇기에 Browser engineer들이나 기술명세서를 작성하는 사람들도 이 문제에 대해 생각해보지 않은 것이다. 반응형 이미지 기술은 최근에 이러한 문제를 해결하기 위해 ‘몇 가지 이미지 files를 browser에 제공하는 형태’, ‘모두 같은 것을 보지만 서로 다른 Pixels를 포함하는 형태(resolution switching)’ 또는 ‘서로 다른 공간 할당량에 걸맞는 서로 다른 이미지를 제공하는 형태(art direction)’로 실행되었다.

Note: 여기에서 다룰 srcset/sizes/<picture>은 모두 최신 Desktop과 mobile browsers에서 지원한다(Microsoft Edge 지원, Internet explorer 미지원).

어떻게 반응형 이미지를 생성할까?

HTML보다 반응형 디자인에 있어 더 나은 도구 CSS를 통해 반응형 디자인을 생성할 수도 있지만 이번에는 <img>를 이용하는 방법에 대해 먼저 알아볼 것이다.

Resolution switching: 서로 다른 Sizes

Resolution switching을 통해 무슨 문제를 해결할 것인가? 우리는 Device의 크고 작음에 따라 동일한 이미지 content를 보여주길 원한다. <img> element는 전통적으로 하나의 Source file을 지목한다:

<img src="elva-fairy-800w.jpg" alt="Elva dressed as a fairy">

그러나 우리는 두 가지 새로운 속성을 사용할 수 있다. srcsetsizes를 통해 몇 가지 추가 source 이미지들을 제공하고 browser에게 적합한 것을 선택할 수 있는 hint를 제공한다.

<img srcset="elva-fairy-480w.jpg 480w,
             elva-fairy-800w.jpg 800w"
     sizes="(max-width: 600px) 480px,
            800px"
     src="elva-fairy-800w.jpg"
     alt="Elva dressed as a fairy">

srcset에 browser가 선택할 수 있는 이미지 Set을 정의하고 각각의 이미지 size를 적는다. 각각의 이미지 set 정보는 이전의 것과 comma로 구분된다. 하나를 집어 살펴보자:

  1. 이미지 filename(elva-fairy-480w.jpg 480w)
  2. 공간
  3. pixels에서의 고유한 이미지 너비(480w) - 이 부분에서 px를 쓰는 것이 아니라 w를 쓴다는 점을 주목하자. 이것은 컴퓨터에서 이미지 file을 조사하는 방법을 통해 발견할 수 있는 이미지의 진짜 크기다.

sizes는 하나의 미디어 조건 Set(e.g. screen width)을 정의하고, 그 조건 중 True를 반환하는 가장 적합한 미디어를 가리키게 한다.

  1. 미디어 조건문(Media condition) ((max-width:600px))에 대해서는 CSS에서 더 자세하게 배울 수 있다. 여기에서는 미디어 조건문이 Screen이 있을 수 있는 적합한 state를 기술한다고 이해하자. 이 경우에는, “600 Pixels 혹은 그 이하의 viewport width일 때”를 말한다.
  2. 공간
  3. Width가 표기된 Slot은 미디어 조건문이 True일 때 채울 이미지(480Px)를 말한다.

Note: slot width에서 px, em과 같은 절대 길이를 제공하거나 viewport의 상대적 길이를 제공할 수 있다. 그러나 percentages는 제공할 수 없다. 어쩌면 마지막 slot width에 미디어 조건문이 없다는 것을 눈치챘을 수 있다. 이 부분은 미디어 조건문 중 만족하는 부분이 없을 경우 기본적으로 반환될 기본값이라고 볼 수 있다. Browser는 처음 매칭되는 조건을 제외하고 모두 무시하기 때문에 순서에 있어 주의해서 할당하도록 한다.

그래서 이러한 속성들이 각자의 자리에 있다면 browser는 다음과 같이 작동할 것이다:

  1. Device의 너비를 측정한다.
  2. sizes list에 있는 미디어 조건들 중 가장 첫번째로 true를 반환하는 조건을 계산한다.
  3. Media query에 주어진 slot size를 측정한다.
  4. srcset list에서 주어진 것과 똑같은 size를 load 하거나, 만약 해당하는 size가 없을 경우 선택된 slot size보다 큰 것 중 첫번째 이미지를 선택해 load 한다.

만약, 480px의 Viewport width를 가진 위의 기능을 지원하는 browser가 Page를 Load 하면, (max-width: 600px) 미디어 조건은 true를 반환하고 browser는 480px Slot을 선택할 것이다. 그리고 고유 너비 480w가 이 Slot size에 가장 가까우므로 elva-fairty-480w.jpg를 Load 하게 된다. 800px 사진은 128KB의 공간을 차지하는데 반해 480px version은 63KB만을 차지한다(65KB를 절약). 자, 여기서 더 많은 이미지가 한 page 안에 있다면 이 방법을 통해 mobile 사용자들의 대역폭을 줄일 수 있게 된다는 것을 알 수 있을 것이다.

Note: Desktop browser에서 이것을 테스트하게 될 때, 가장 좁은 너비로 설정되어 있음에도 browser가 더 좁은 이미지들을 load 하는데 실패 한다면, viewport가 무엇인지 확인해보도록 한다(Browser의 JavaScript console에서 document.querySelector('html').clientWidth를 입력해 근사치를 알 수 있음). 서로 다른 browser들은 줄일 수 있는 최소의 window width sizes가 있는데 생각하는 것보다 더 클 수 있다. Mobile browser에서 테스트 할 때는 Firefox의 about:debugging page와 같은 도구를 사용해 mobile에서 load 되는 page를 조사할 수 있다.

오래된 browser들은 이 기능을 지원하지 않기 때문에 이 부분을 무시할 것이다. 대신에 그러한 browser들은 src 속성에 참조된 이미지를 load 한다.

Note: 예시<head>에서 <meta name="viewport" content="width=device-width"> 부분을 찾을 수 있다: 이것은 mobile browser들이 web page들을 loading 하는데 있어 진짜 viewport width를 채택하도록 강제한다. 그러나 어떤 mobile browser들은 viewport width를 속이기도 하는데 이로 인해 더 큰 viewport를 가졌음에도 load 되는 page의 크기를 줄이는 결과가 초래된다, 그리고 이것은 반응형 이미지나 디자인에 있어 그다지 도움되지 않는다.

Resolution switching: 같은 크기, 서로 다른 해상도

모든 사람들이 screen에서 현실 세계와 같은 크기의 이미지를 보지만, 만약 당신이 복수의 디스플레이 해상도를 지원한다면 sizes 없이 srcset과 x-dscriptors를 통해 browser에 적절한 해상도 이미지를 선택하게 허용할 수 있다.

<img srcset="elva-fairy-320w.jpg,
             elva-fairy-480w.jpg 1.5x,
             elva-fairy-640w.jpg 2x"
     src="elva-fairy-640w.jpg"
     alt="Elva dressed as a fairy">

예시에서는 이미지에 320 pixels의 너비가 적용되었다.

img {
  width: 320px;
}

이 경우에, sizes는 필요하지 않다. Browser는 보여지고 있는 디스플레이의 해상도를 계산해 srcset에 참조된 이미지 중 가장 적합한 것을 제공한다. 그래서 만약 Device가 각각의 CSS pixel을 대표하는 하나의 device pixel과 함께 표준/낮은 해상도 디스플레이를 가진 page에 접근하게 되면 elva-fairy-320w.jpg 이미지가 load 될 것이다(1x는 암시적으로 적용되어 있기에 포함할 필요 없음). 만약 device가 CSS pixel 당 두 개의 device pixels 혹은 그 이상을 가질 경우, elva-fairy-640w.jpg 이미지가 load 될 것이다. 640px 이미지는 93KB인데 반해, 320px 이미지는 39KB에 불과하다. 즉, 해상도가 달라지더라도 이미지의 너비가 시각적으로 고정 되기 위해서는 그만큼 pixels의 수가 증가 혹은 감소 되어야 하는데 이 방법을 통해 이미지의 크기를 고정할 수 있게 되는 것이다.

Art direction

다시 상기하자면 art direction problem은 서로 다른 이미지 display 크기에 맞춰 전시될 이미지를 바꾸는 것을 포함한다. 예를 들어, Desktop browser에서 큰 배경과 그 가운데 서있는 한 사람이 배치 돼 있는 web page가 있다고 해보자. Mobile browser에서 볼 때, 같은 이미지가 줄어든 것처럼 보이고, 사람은 더 작게 보여 인식하기 어려울 정도가 될 것이다. 이 상황에서는 아마 더 작지만 인물 위주인 이미지를 보여주는 것이 더 나을 것이다. <picture> element는 이러한 종류의 해결책을 실행할 수 있게 한다.

not-responsive.html 예시에서는 art direction이 필요한 상태의 이미지를 보여준다.

<img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva">

자, 이것을 <picture>와 함께 고쳐보도록 하자! <picture> element는 가장 중요한 <img> element에 이어, browser가 선택할 수 있는 다른 소스값을 가지는 element인 <source>를 포함하는 포장 element다. responsive.html에서 보여지는 부분의 코드는 다음과 같다:

<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="Chris standing up holding his daughter Elva">
</picture>
  • <source> element의 media 속성에서 미디어 조건을 포함할 수 있다. 위의 사례에서 media 속성의 조건문에 따라 최대 너비가 799px 이하일 경우 첫 번째 srcset에 기술된 이미지를 사용하게 되고 그 이상일 경우 두 번째 조건의 이미지를 사용하게 된다.

  • 상기의 <img> 사례에서 srcset에 복수의 이미지를 할당하고 sizes 속성을 이용해 구분했던 것처럼 <source> element에서도 동일하게 해당 속성들을 사용할 수 있지만 이런 식으로 자주 사용하지는 않는다.

  • 모든 경우에 있어서 </picture> 전에 srcalt 속성을 포함한 <img> element를 제공해야 한다. 그렇지 않을 경우, 이미지가 표기되지 않을 것이다. 또한 미디어 조건에 해당하는 이미지가 존재하지 않거나 <picutre> element를 지원하지 않는 browser에서 기본 이미지를 표기한다는 점에서 필요하다.

Note: media 속성은 art direction 시나리오를 사용할 때에만 사용하도록 한다. 또한 media 속성을 사용하고 있다면, sizes 속성에 미디어 조건문을 제공하지 않도록 주의해야 한다.

CSS 혹은 JavaScript를 사용하지 않는 이유는?

Browser가 한 페이지를 load할 때, Browser는 main parser(메인 분석기)가 load를 시작하고 Page의 CSS와 JavaScript를 해석하기 이전에 이미지들을 다운로드(preload)하기 시작한다. 이 메커니즘은 page의 load 시간을 감소시킨다는 점에서 유용하지만 반응형 이미지에 있어서는 그다지 유용하지 않다. 그렇기에 srcset과 같은 해결책을 실행할 필요가 있는 것이다. 예를 들어, <img> element를 load 할 수 없어서 JavaScript로 viewport를 추적한 다음 동적으로 소스 이미지를 변경시켜 작게 만들었다고 하자. 그렇다면 본래의 이미지는 이미 load 된 상태에 추가로 작은 이미지까지 load 하게 되는 것이다. 이것은 반응형 이미지 조건에 더 나쁜 방식이다.

최신 이미지 포맷을 대담하게 사용하자

새로운 이미지 포맷인 WebP 그리고 AVIF는 작은 파일 크기를 유지하는 동시에 높은 퀄리티를 제공한다. 이러한 포맷들은 상대적으로 넓은 browser에서 지원을 받고 있지만, “역사적 깊이” 때문에 널리 전파되고 있지 못한다.

<picture>을 통해 오래된 browser들을 지원할 수 있다. MIME types를 type 속성에 제공해 지원하지 않는 파일 형식을 즉시 거부할 수 있도록 할 수 있다.

<picture>
  <source type="image/svg+xml" srcset="pyramid.svg">
  <source type="image/webp" srcset="pyramid.webp">
  <img src="pyramid.png" alt="regular pyramid built from four equilateral triangles">
</picture>
  • Art direction을 사용할 것이 아니라면 media 속성을 사용하지 않는다.

  • <source> element 안에서 type 속성을 통해 이미지의 type을 참조할 수 있다.

  • srcsetsizes를 사용해야 한다면 쉼표(,)로 구분해 list를 기술하도록 한다.

저작권


Mozilla 기여자가 작성한 MDN에 대해는 CC-BY-SA 2.5 라이선스에 따라 사용할 수 있습니다.


크리에이티브 커먼즈 라이선스
이 저작물은 크리에이티브 커먼즈 저작자표시-동일조건변경허락 4.0 국제 라이선스에 따라 이용할 수 있습니다.