nginx와 image-filter 모듈을 사용하여 사용자 브라우저 조건에 부합하는 반응형 이미지를 표출할 수 있습니다.
시작에 앞서, 본 글에서는 nginx open-source 버전을 기반으로 작성하였습니다.
nginx image-filter 모듈 설치
Ubuntu 및 Debian:
$ sudo apt-get install nginx-module-image-filter
Red Hat, CentOS 및 Oracle Linux:
$ sudo yum install nginx-module-image-filter
설치 확인
nginx -V
--with-http_image_filter_module=dynamic 포함 확인
이미지 크기와 픽셀 밀도 일치시키기
Image-Filter 모듈을 사용하면 각 이미지의 단일 “Source” 버전을 생성 및 배포할 수 있으며, 이미지를 수동으로 크기를 조정하고 웹 서버에 배포할 필요 없이 HTML Source 내에서 반응형 웹 페이지와 이미지를 세밀하게 조정할 수 있습니다.
다음 샘플 HTML 파일에서는 픽셀 밀도가 다른 디바이스를 위한 네 가지 이미지 변형을 정의합니다.
<!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 디렉터리는 실제로 존재하지 않습니다. 대신 /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가 들어오는 HTTP 요청을 처리하는 방법을 정의합니다.
listen 지시문은 HTTP 트래픽의 기본값인 포트 80에서 수신 대기하도록 NGINX에 지시합니다.
root 지시문은 이 웹사이트의 디스크 위치를 지정합니다.
location 블록은 정규 표현식을 사용하여 /img로 시작하는 디렉터리에 저장된 리소스에 대한 요청에 하나 이상의 숫자가 뒤따르는 요청을 일치시킵니다.
숫자는 변수 $1로 캡처되고 그 뒤에 오는 파일 이름은 변수 $2로 캡처됩니다.
그런 다음 alias 지시문을 사용하여 Source 이미지가 포함된 디스크의 디렉터리에서 이 요청을 서비스합니다.
이 디렉터리는 root 경로 아래에 있지 않으므로 클라이언트가 Source 이미지를 직접 요청할 수 없습니다.
Source 이미지의 너비가 수천 픽셀로 매우 클 수 있으므로 Image-Filter 모듈이 이미지를 로드하고 크기를 조정할 수 있는 충분한 메모리를 할당하는지 확인해야 합니다.
image-filter-buffer 지시문을 사용하여 최대 10MB 크기의 이미지 파일을 지원합니다.
image_filter 지시문은 Image-Filter 모듈에 Source 이미지의 크기를 /img 디렉터리 이름의 접미사에서 캡처한 너비에 맞게 조정합니다.
대시(-)는 Source 이미지의 가로 세로 비율을 유지하도록 합니다.
Production 사용 시 고려 사항
이미지 크기 조정 작업을 수행하기 위해 임의의 요청을 허용하는 것이 보안에 미치는 영향도 고려해야 합니다.
캐싱을 설정해도 공격자가 /img1001/mylogo.png, /img1002/mylogo.png, /img1003/mylogo.png 등과 같은 고유한 이미지 리소스 변형을 빠르게 요청할 경우 도움이 되지 않습니다.
이러한 공격은 요청량이 상대적으로 적더라도 과도한 CPU 사용률로 인해 서비스 거부(DoS)를 유발할 수 있습니다.
이 문제를 해결하기 위해 반응형 이미지 서버에는 속도 제한을 적용하지만 캐시된 변형을 포함하는 Frontend 서버에는 적용하지 않습니다.
다음 구성은 Image-Filter 모듈에 캐싱 및 속도 제한을 적용하여 이미지 크기와 픽셀 밀도 일치의 구성을 확장합니다.
proxy_cache_path /var/www/imgcache levels=1 keys_zone=resized:1m max_size=256m;
//캐시된 이미지 위치 정의
//keys_zone : 캐시 인덱스의 공유 메모리 Zone을 정의하고 크기가 조정된 이미지 약 8,000개에 충분한 1MB를 할당
//max_size : 새로운 캐시 항목을 위한 공간을 확보를 위해 캐시에서 최근 요청 이미지 제거 시작지점
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_pass : 내부적으로 호스팅되는 반응형 이미지 서버(127.0.0.1:9001)로 /img가 접두사로 붙은 요청을 보냅니다.
proxy_cache : 반응형 이미지 서버의 응답을 저장하는 데 사용할 캐시의 이름을 지정하여 이 위치에 대한 캐싱을 활성화합니다.
proxy_cache_valid : 캐시에 최소 180분 동안 유지(캐시가 max_size를 초과하지 않고 가장 최근에 요청된 이미지가 아닌 경우), 응답 이미지 서버의 잘못된 응답이 캐시되지 않도록 합니다.
limit_req_zone : 속도 제한(Rate Limit)을 지정합니다.
초당 두 개의 요청으로 속도 제한(Rate Limit)을 정의한 다음 server 블록에 limit_req 지시문을 포함시켜 반응형 이미지 서버에 적용합니다.
일반적으로 속도 제한(Rate Limit)은 요청의 속성에 대해 Key가 지정되지만, 이 경우에는 모든 요청자에게 제한이 적용되도록 정적 Key 값 “1”을 지정합니다.
Key의 고정 Cardinality가 1이기 때문에 공유 메모리 Zone의 크기를 가능한 가장 작은 값인 3KB로 설정
반응형 이미지 서버용 server 블록은 포트 9001에서 수신 대기합니다.
allow 및 deny : localhost(Frontend 웹 서버)만 반응형 이미지 서버에 연결할 수 있도록 지정
limit_req : 이전에 정의한 전송률 제한을 적용하고, burst 매개변수는 전송률 제한을 적용하기 전에 10개의 동시 요청을 허용합니다.
전송률 제한이 적용되면 초과 요청은 제한 내에서 처리될 때까지 지연됩니다.
location 블록은 이미지 크기와 픽셀 밀도 일치의 블록과 동일하지만 이제 요청된 이미지가 캐시에 없고 전송률 제한을 초과하지 않은 경우에만 실행됩니다.
이 기본 구성에서는 단일 NGINX 인스턴스가 Frontend 웹 서버와 반응형 이미지 서버의 역할을 모두 수행합니다.
'nginx' 카테고리의 다른 글
[nginx] FastCGI & PHP-FPM (1) | 2025.04.25 |
---|---|
리버스 프록시 서버? (0) | 2024.11.09 |
[nginx] error 로그 유형 및 대응방안 (1) | 2024.11.07 |
[nginx] nginx 서버 config 분석 -1 (1) | 2024.09.30 |
[Nginx] SSL 인증서 갱신 (0) | 2024.09.02 |