NGINX 및 NGINX Plus는 쉽게 반응성 있는 이미지를 제공합니다.

관리자
조회수 335


Image‑Filter 모듈과 srcset 태그를 사용하여 즉석에서 이미지 크기 조정

반응형 웹 디자인은 현대 웹사이트와 웹 애플리케이션의 표준이 되었으며, 다양한 기기에서 일관된 경험을 제공하는 동시에 각 기기의 디스플레이를 최적화합니다. 그러나 현대 기기는 화면 크기뿐만 아니라 픽셀 밀도도 다양합니다. HTML5 img태그는 서버에서 여러 변형을 제공하는 경우 브라우저가 가장 적합한 자산을 선택할 수 있도록 하는 여러 기능을 제공합니다. 웹사이트가 동일한 이미지의 여러 다른 크기를 배포하는 경우 웹 브라우저는 현재 환경에 가장 적합한 크기를 선택할 수 있습니다.

따라서 반응형 이미지를 사용하면 웹 브라우저가 디자이너의 의도와 밀접하게 일치하는 렌더링을 생성할 수 있습니다. 이는 사용자 경험을 개선하지만 개발 및 운영 팀에 추가적인 부담을 주는데, 이들은 이제 기본 이미지뿐만 아니라 수많은 이미지 자산 변형을 만들고 배포해야 합니다.

이 블로그 게시물에서는 NGINX 및 NGINX Plus용 Image‑Filter 모듈을 사용하여 수많은 이미지 자산 변형을 만들고 관리하는 번거로움 없이 반응형 이미지를 제공하는 방법을 보여줍니다. 대신, NGINX 또는 NGINX Plus가 즉시 크기를 조정하는 각 이미지의 단일 "소스" 버전을 배포할 수 있습니다. 게시물의 정보는 NGINX Open Source와 NGINX Plus에 모두 적용됩니다( Image‑Filter 모듈 설치 의 별도 지침 제외 ). 간결하게 하기 위해 전체에서 NGINX Plus를 참조합니다.


속성srcset

반응형 이미지를 제공하는 주요 도구는 srcsetHTML5 img태그의 속성입니다. 이를 사용하여 다양한 픽셀 밀도와 뷰포트 크기에 대한 여러 이미지 자산 변형을 지정할 수 있습니다. 뷰포트 는 데스크톱의 창이든 모바일 기기의 전체 화면 앱이든 웹 브라우저에서 사용할 수 있는 디스플레이 공간을 나타내는 일반적인 용어입니다.

다음 예에서 속성은 해당 속성을 지원하지 않는 브라우저에 대한src 기본 이미지를 정의하고 속성 은 두 가지 변형을 명명합니다. 하나는 표준 픽셀 밀도( )를 갖는 디스플레이용이고, 다른 하나는 Apple Retina™ 디스플레이 및 일부 4K 모니터와 같이 두 배 픽셀 밀도를 갖는 디스플레이용입니다( ).srcsetsrcset1x2x

<img src="/images/mylogo-default.png"  srcset="/images/mylogo-density1.png 1x, /images/mylogo-density2.png 2x">

다음의 보다 정교한 예는 뷰포트의 너비에 따라 표시할 여러 이미지 자산 변형을 정의합니다. 이 sizes속성은 뷰포트가 뷰포트보다 넓으면 브라우저가 뷰포트의 절반에 이미지를 렌더링하고 10em그렇지 않으면 전체 뷰포트를 사용한다는 것을 지정합니다. 브라우저는 이미지에 사용할 수 있는 공간을 확인하고 사용 가능한 공간에 가장 적합한 이미지 자산 변형을 선택합니다. 일반적으로 다음 너비(접미사)로 "반올림" w하고 내부적으로 이미지 크기를 조정하여 공간을 정확히 채웁니다.

<img src="/images/racecar-default.jpg"  sizes="(min-width: 10em) 50vw, 100vw"
  srcset="/images/racecar-100px.jpg 100w, /images/racecar-225px.jpg 225w,
          /images/racecar-450px.jpg 450w, /images/racecar-675px.jpg 675w">

이미지 자산 변형의 범위를 지정하여 반응형 이미지를 제공하는 이 접근 방식은 코딩하기 쉽고 매우 효과적입니다. 그러나 이미지 변형 자체를 만들고 관리하는 측면에서 과제가 있습니다. 사전 제작 이미지 크기를 많이 조정하고 서버에 훨씬 더 많은 파일을 배포해야 합니다. 각 변형의 최적 수와 크기를 미세 조정하는 데 시간이 많이 걸릴 수 있으며, 이로 인해 각 이미지 자산 변형에 액세스할 수 있는지 테스트하는 데 어려움이 발생합니다.

srcset반응형 이미지의 속성 및 기타 기술 에 대한 자세한 내용은 이 훌륭한 블로그 게시물을 참조하세요 .


이미지 필터 모듈 설치

NGINX Plus와 NGINX에서 해당 Image‑Filter 모듈을 얻는 절차가 다릅니다.

NGINX Plus용 이미지 필터 모듈 설치

Image‑Filter 모듈은 NGINX Plus 구독자에게 무료 동적 모듈 로 제공됩니다 .

  1. NGINX Plus 저장소에서 모듈을 설치하여 모듈 자체를 얻습니다.

    Ubuntu 및 Debian 시스템의 경우:

    $ sudo apt-get install nginx-plus-module-image-filter

    RedHat, CentOS 및 Oracle Linux 시스템의 경우:

    $ sudo yum install nginx-plus-module-image-filter
  2. nginx.confload_module 구성 파일 의 최상위("main") 컨텍스트에 해당 지시문을 포함하여 모듈을 활성화합니다 (즉, 또는 컨텍스트에는 포함되지 않음).httpstream

    load_module modules/ngx_http_image_filter_module.so;
  3. NGINX Plus를 다시 로드하여 실행 중인 인스턴스에 Image‑Filter 모듈을 로드합니다.

    $ sudo nginx -s reload>

NGINX 오픈 소스용 이미지 필터 모듈 설치

Image‑Filter 모듈을 설치하는 가장 쉬운 방법은 공식 NGINX 저장소에서 가져오는 것입니다. 다음 지침 에 따라 시스템을 구성하여 공식 NGINX 저장소에 액세스한 다음 운영 체제 패키지 관리자로 설치합니다.

Ubuntu 및 Debian 시스템의 경우:

$ sudo apt-get install nginx-module-image-filter

Red Hat, CentOS 및 Oracle Linux 시스템의 경우:

$ sudo yum install nginx-module-image-filter

설치가 완료되면 NGINX Plus용 이미지 필터 모듈 설치 의 2단계와 3단계에 따라 NGINX를 구성하고 다시 로드합니다.

소스에서 Image‑Filter 모듈을 컴파일하여 정적으로 컴파일된 모듈 또는 동적 모듈로 로드하는 것도 가능합니다. 자세한 내용은 NGINX Plus 관리자 가이드를 참조하세요 .

픽셀 밀도에 맞는 이미지 크기

Image‑Filter 모듈을 사용하면 각 이미지의 단일 "소스" 버전을 만들고 배포할 수 있으며 NGINX Plus에서 브라우저에서 요청한 모든 크기 변형을 제공하기 위해 즉시 크기를 조정할 수 있습니다. 이미지를 수동으로 크기를 조정하고 웹 서버에 배포하지 않고도 HTML 소스 내에서 반응형 웹 페이지와 이미지를 미세 조정할 수 있습니다.

이 샘플 HTML 파일에서는 픽셀 밀도가 다른 장치에 대한 4가지 이미지 변형을 정의합니다.

<!DOCTYPE html><html>
<head>
<title>Responsive Logo</title>
</head>
<body>
 
<h2>Logo selection based on pixel density</h2>

<img src="/img400/mylogo.png"
  srcset="/img400/mylogo.png 1x, /img800/mylogo.png 2x, /img1200/mylogo.png 3x, 
          /img1600/mylogo.png 4x">
 
</body>
</html>

/ img400 , /img800 , /img1200 , 그리고 /img1600 디렉토리는 실제로 존재하지 않습니다. 대신, 다음 NGINX Plus 구성은 /img 로 접두사가 붙은 자산에 대한 요청을 매치하고 이를 원래 파일 이름(예: 이전 HTML의 mylogo.png ) 으로 이미지 크기를 조정하는 요청으로 변환합니다 .

server {    listen 80;
    root /var/www/public_html;
 
    location ~ ^/img([0-9]+)(?:/(.*))?$ {
        alias /var/www/source_images/$2;
        image_filter_buffer 10M;
        image_filter resize $1 -;
    }
}

이 server블록은 NGINX Plus가 들어오는 HTTP 요청을 처리하는 방법을 정의합니다. 이 listen지시문은 NGINX Plus에 HTTP 트래픽의 기본값인 포트 80에서 수신하도록 지시합니다. 이 root지시문은 이 웹사이트의 디스크 위치를 지정합니다. 이 간단한 예에서는 NGINX Plus에서 호스팅하는 정적 웹사이트를 사용하지만 NGINX Plus가 동적 콘텐츠의 역방향 프록시 또는 FastCGI와 같은 애플리케이션 커넥터 역할을 하는 것도 일반적입니다. 이러한 모든 사용 사례는 여기에 설명된 대로 Image‑Filter 모듈을 활용하여 소스 이미지를 NGINX Plus 서버에 배포할 수 있습니다.

이 location블록은 정규 표현식을 사용하여 /img 로 시작 하고 숫자가 하나 이상 붙은 모든 디렉토리에 저장된 자산에 대한 요청을 매치합니다. 숫자는 변수로 캡처 $1되고 그 뒤에 오는 파일 이름은 변수로 캡처됩니다 $2. 그런 다음 지시문을 사용하여 alias소스 이미지가 들어 있는 디스크의 디렉토리에서 이 요청을 처리합니다. 이 디렉토리는 경로 아래에 없으므로 root클라이언트가 소스 이미지를 직접 요청할 수 없습니다.

소스 이미지가 매우 크고, 아마도 수천 픽셀 너비일 수 있으므로 Image‑Filter 모듈이 이미지를 로드하고 크기를 조정할 수 있는 충분한 메모리를 할당해야 합니다. 이 예에서 우리는 image_filter_buffer최대 10MB 크기의 이미지 파일을 지원하기 위해 지시문을 사용합니다.

마지막으로, 지시어는 Image‑Filter 모듈에 소스 이미지의 크기를 /imgimage_filter 디렉토리 이름 의 접미사에서 캡처한 너비로 조정하라고 지시합니다 . 대시(‑)는 NGINX Plus에 소스 이미지의 종횡비를 유지하라고 지시합니다.

생산 사용을 위한 고려 사항

이미지 크기를 픽셀 밀도에 맞추기 에서 설명한 구성은 이미지를 요청하는 데 사용된 디렉토리 이름에 따라 이미지의 모든 크기 변형을 제공할 수 있습니다. 그러나 프로덕션 환경에서는 웹 서버가 각 요청에 대해 이미지 크기를 조정할 때까지 기다리고 싶지 않습니다. 이는 전체 지연 시간에 좋지 않으며 상당한 CPU 오버헤드를 추가할 수도 있습니다.

가장 효과적인 해결책은 크기 조절된 이미지 변형을 캐시하여 이후 각 변형에 대한 요청이 Image-Filter 모듈을 거치지 않고 캐시에서 제공되도록 하는 것입니다. NGINX Plus 구성을 사용하여 이미지 크기 조절을 수행하는 별도의 가상 서버를 정의하고 요청된 이미지 크기가 캐시에 없는 경우에만 요청을 프록시하여 이를 달성할 수 있습니다. 이를 반응형 이미지 서버 라고 합니다 .


임의의 요청이 이미지 크기 조정 작업을 수행하도록 허용하는 것의 보안 영향도 고려해야 합니다. 공격자가 /img1001/mylogo.png , /img1002/mylogo.png , /img1003/mylogo.png 등과 같은 고유한 이미지 자산 변형에 대한 빠른 요청을 하는 경우 캐싱을 구성해도 도움이 되지 않습니다. 요청 볼륨이 비교적 적더라도 이러한 공격은 과도한 CPU 사용으로 인해 서비스 거부(DoS)를 일으킬 수 있습니다. 이를 해결하기 위해 반응형 이미지 서버에 속도 제한을 적용하지만 캐시된 변형이 포함된 프런트엔드 서버에는 적용하지 않습니다. 다음 구성은 캐싱과 속도 제한을 Image‑Filter 모듈에 적용하여 이미지 크기를 픽셀 밀도에 맞추는 구성을 확장합니다 .

proxy_cache_path /var/www/imgcache levels=1 keys_zone=resized:1m max_size=256m;
server {
    listen 80;
    root /var/www/public_html;

    location ~ ^/img([0-9]+)(?:/(.*))?$ {
        proxy_pass        http://127.0.0.1:9001;
        proxy_cache       resized;
        proxy_cache_valid 180m;
    }
}

limit_req_zone "1" zone=2persec:32k rate=2r/s;

server {
    listen 9001;
    allow 127.0.0.1;
    deny all;
    limit_req zone=2persec burst=10;

    location ~ ^/img([0-9]+)(?:/(.*))?$ {
        alias /var/www/source_images/$2;
        image_filter_buffer 10M;
        image_filter resize $1 -;
    }
}

우리는 지시문으로 캐시된 이미지의 위치를 정의하는 것으로 시작합니다 proxy_cache_path. keys_zone매개변수는 캐시 인덱스( resized)에 대한 공유 메모리 영역을 정의하고 약 8,000개의 크기 조정된 이미지에 충분한 1MB를 할당합니다. max_size매개변수는 NGINX Plus가 캐시에서 가장 최근에 요청된 이미지를 제거하여 새 캐시된 항목을 위한 공간을 만드는 시점을 정의합니다.

location프런트엔드 웹 서버(포트 80에서 수신 대기)에 대한 지시문은 지시문을 사용하여 / imgproxy_pass 로 시작하는 요청을 내부적으로 호스팅된 반응형 이미지 서버(127.0.0.1:9001)로 전송합니다. 지시문 은 반응형 이미지 서버의 응답을 저장하는 데 사용할 캐시 이름( )을 지정하여 이 위치에 대한 캐싱을 활성화합니다 . 지시문은 크기가 조정된 이미지가 최소 180분 동안 캐시에 보관되도록 하고(캐시가 초과되어 최근에 요청되지 않은 경우) 반응형 이미지 서버의 모든 오류 응답이 캐시되지 않도록 합니다.proxy_cacheresizedproxy_cache_validmax_size

캐싱에 대한 자세한 설명은 NGINX 및 NGINX Plus를 사용한 캐싱 가이드를 참조하세요 .

반응형 이미지 서버 자체를 정의하기 전에 지시어로 속도 제한을 지정합니다 limit_req_zone. 지시어 자체는 속도 제한을 적용하지 않습니다. 초당 두 개의 요청으로 속도 제한을 정의한 다음 지시어를 블록 limit_req에 포함하여 반응형 이미지 서버에 적용합니다 server(다음 문단 참조). 일반적으로 속도 제한은 요청의 속성에 따라 키가 지정되지만 이 경우 "1"모든 요청자에게 제한이 적용되도록 정적 키 값을 지정합니다. 키의 고정된 카디널리티가 1이므로 공유 메모리 영역의 크기를 가능한 가장 작은 값인 3KB로 설정합니다.

server반응형 이미지 서버 블록은 포트 9001에서 수신합니다. 우리는 및 지시어를 포함하여 로컬 allow호스트deny (프런트엔드 웹 서버)만 반응형 이미지 서버에 연결할 수 있도록 지정합니다. 그런 다음 지시어를 포함하여 이전에 정의된 속도 제한을 적용합니다 limit_req. burst매개변수는 속도 제한을 적용하기 전에 10개의 동시 요청을 허용합니다. 속도 제한이 적용되면 초과 요청은 제한 내에서 처리될 때까지 지연됩니다.

이 블록은 픽셀 밀도에 맞는 이미지 크기 조정location 의 블록과 동일 하지만, 이제 요청된 이미지가 캐시에 없고 속도 제한을 초과하지 않은 경우에만 실행됩니다.

이 기본 구성에서 단일 NGINX Plus 인스턴스는 프런트엔드 웹 서버와 반응형 이미지 서버 역할을 모두 합니다. 이미지 처리에는 매우 많은 컴퓨팅이 필요하여 잠재적으로 매우 높은 작업 부하로 이어지고 NGINX Plus가 DoS 공격을 받을 수 있습니다. 모든 작업자 프로세스가 이미지 크기 조정 요청으로 바빠서 프런트엔드 웹 서버가 새 요청을 즉시 수락할 수 없는 상황을 피하려면 이미지 처리에 전담된 별도의 NGINX Plus 인스턴스를 실행하는 것이 좋습니다. 이렇게 하면 프런트엔드 웹 서버의 작업자 프로세스가 이미지 처리를 수행하는 작업자 프로세스와 분리됩니다. 동일한 호스트에서 별도의 NGINX Plus 인스턴스를 실행하려면 명령줄에 다른 구성 파일을 지정합니다.

$ sudo nginx -c /etc/nginx/resize-server.conf


반응형 이미지의 액션

반응형 이미지가 실제로 어떻게 동작하는지 보는 가장 효과적인 방법은 브라우저가 srcset뷰포트 크기가 변경될 때 사용할 이미지 변형을 결정하는 것을 관찰하는 것입니다. 간단한 이미지 갤러리의 HTML 소스는 다음과 같습니다. 데모 목적으로 각 이미지의 크기 변형이 약간씩 다르므로 브라우저가 다른 변형을 선택할 수 있는 많은 "중단점"이 생성됩니다.

<!DOCTYPE html>
<html>
<head>
<title>Responsive Image Gallery</title>
</head>
<body>
 
<h2>Responsive Image Gallery</h2>

<img src="/img100/1-dominos.jpg" sizes="(min-width: 20em) 40vw, 100vw"
  srcset="/img110/1-dominos.jpg 110w, /img210/1-dominos.jpg 210w,
          /img310/1-dominos.jpg 310w, /img410/1-dominos.jpg 410w,
          /img510/1-dominos.jpg 510w, /img610/1-dominos.jpg 610w">

<img src="/img100/2-sign.jpg" sizes="(min-width: 20em) 40vw, 100vw"
  srcset="/img120/2-sign.jpg 120w, /img220/2-sign.jpg 220w,
          /img330/2-sign.jpg 330w, /img420/2-sign.jpg 420w,
          /img520/2-sign.jpg 520w, /img620/2-sign.jpg 620w">

<img src="/img100/3-thruppence.jpg" sizes="(min-width: 20em) 40vw, 100vw"
  srcset="/img130/3-thruppence.jpg 130w, /img230/3-thruppence.jpg 230w,
          /img330/3-thruppence.jpg 330w, /img440/3-thruppence.jpg 440w,
          /img550/3-thruppence.jpg 550w, /img660/3-thruppence.jpg 660w">

<img src="/img100/4-aces.jpg" sizes="(min-width: 20em) 40vw, 100vw"
  srcset="/img140/4-aces.jpg 140w, /img240/4-aces.jpg 240w,
          /img340/4-aces.jpg 340w, /img440/4-aces.jpg 440w,
          /img540/4-aces.jpg 540w, /img640/4-aces.jpg 640w">

</body>
</html>

아래 스크린샷은 Inspector가 Network 탭 으로 열린 Chrome 브라우저에서 이 웹 페이지의 내용을 보여줍니다 . 이름 열은 서버에서 요청한 각 이미지 변형의 경로를 보여주므로 웹 서버의 로그를 확인하지 않고도 선택한 크기를 확인할 수 있습니다.


결론

NGINX Plus와 Image‑Filter 모듈을 사용하면 현재 브라우저 조건에 맞는 최적의 이미지 크기를 제공할 수 있습니다. 사전 제작 이미지 크기 조정, 일괄 처리 또는 디스크에서 수백 개의 이미지 자산 변형을 관리할 필요 없이 이를 수행할 수 있습니다. NGINX Plus가 완벽한 애플리케이션 제공을 달성하는 데 도움이 되는 또 다른 방법입니다.



위 내용과 같이 NGINX Plus 를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요



전문가에게 상담받기