이미 우분투 서버의 크론탭 기능을 활용한 이미지 최적화 시스템 구축 방안에 대해 정리했고, 이를 기반으로 운영중입니다.
그런데 조금 더 자료를 검색하다보니 inotify-tools을 사용해 조금 더 효과적으로 Webp 이미지를 적용하고 관리할 수 있는 방법이 있어 소개해 봅니다.
이는 VPS업체인 디지탈오션(digitalocean) 튜터리얼에서 소개하는 방법인데요. 도움이 될 것 같아서 번역 겸해서 소개해 봅니다.
이 글에서는 우분투 16.04와 CentOS 7를 설치하고 웹서버로는 아파치를 사용자를 대상으로 설명하고 있습니다.
How To Create and Serve WebP Images to Speed Up Your Website
필요 조건
이 방법은 우분투 16.04와 CentOS 7에 아파치 사용자를 대상으로 설명된 것입니다. 저는 NGINX를 사용하므로 소개만 하기로 합니다.
- 사용자는 non-root sudo user여야 함
- 웹서버는 아파치
-
mod_rewrite
가 설치 되어 있어야 함
1. cwebp 설치 및 이미지 폴더 준비
여기에서는 webp 이미지를 만들 수 있는 webp를 설치해 webp를 사용할 수 있게 만들고 webp이미지를 저장할 수 있는 폴더를 만드는 방법에 대해서 알아봅니다.
1.1. webp 설치
sudo apt-get update
sudo apt-get install webp
Code language: PHP (php)
만약 CentOS 7 사용자라면 아래 명령어를 사용합니다
sudo yum install libwebp-tools
Code language: PHP (php)
1.2. 이미지 폴더 생성
webp라는 이미지 저장 폴더를 만듭니다. 이는 아파치 웹 루트( /var/www/html )에 만듭니다.
sudo mkdir /var/www/html/webp
Code language: PHP (php)
이 폴더의 소유권을 변경합니다.
sudo chown sammy: /var/www/html/webp
Code language: PHP (php)
새로 만든 이미지 폴더로 이동합니다.
cd /var/www/html/webp
Code language: PHP (php)
이 단계에서 아파치 서버에서 mod_rewrite와 cwebp
이 설치되어 있고 이미지 폴더가 만들어 졌다면 준비가 완료된 것입니다.
2. cwebp를 이용 이미지 압축
이용자들에게 webp 이미지를 보여주려면 webp 이미지가 만들어져야 합니다. 너무 당연한 소리..
이를 위한 일반적인 명령어는 아래와 같은 형식을 띱니다. 여기서 -o 옵션은 WebP 파일의 경로를 지정합니다.
cwebp image.jpg -o image.webp
Code language: PHP (php)
3. JPEG와 PNG 이미지를 변환합니다.
이제 본격적으로 JPEG와 PNG 이미지를 변환을 위한 스크립트 파일 webp-convert.sh를 만들어 봅니다.
nano ~/webp-convert.sh
Code language: PHP (php)
여기에는 아래와 같은 내용으로 구성됩니다.
#!/bin/bash
# converting JPEG images
find $1 -type f -and \( -iname "*.jpg" -o -iname "*.jpeg" \) \
-exec bash -c '
webp_path=$(sed 's/\.[^.]*$/.webp/' <<< "$0");
if [ ! -f "$webp_path" ]; then
cwebp -quiet -q 90 "$0" -o "$webp_path";
fi;' {} \;
# converting PNG images
find $1 -type f -and -iname "*.png" \
-exec bash -c '
webp_path=$(sed 's/\.[^.]*$/.webp/' <<< "$0");
if [ ! -f "$webp_path" ]; then
cwebp -quiet -lossless "$0" -o "$webp_path";
fi;' {} \;
Save the file
Code language: PHP (php)
- find : 지정된 디렉토리 내에서 파일을 검색합니다.
- $1 :이 위치 매개 변수는 명령 행에서 가져온 이미지 디렉토리의 경로를 지정합니다.
- -type f : 일반 파일 만 찾도록 합니다.
- -iname : 지정된 패턴과 파일 이름을 일치시킵니다.
-iname은 대소 문자를 구분하지 않으며, jpg 또는 .jpeg 파일 이름을 찾도록 합니다. - -o : find 명령을 사용하여 첫 번째 -iname 테스트(“*.jpg”) 또는 두 번째 테스트(iname “*.jpg”)와 일치하는 파일을 나열합니다.
- () : -and 연산자와 함께이 테스트를 괄호로 묶으면 첫 번째 테스트 (예 : -type f)가 항상 실행됩니다.
- bash: webp 이미지 파일을 만드는 스크립트를 실행합니다.
이 스크립트는 -c 옵션 덕분에 문자열로 bash로 전달됩니다. - ‘commands’ : 이 자리 표시자는 webp 이미지를 만드는 스크립트입니다.
- webp_path : 이 변수는 위치 매개변수 $0로 표시된 bash 명령에서 sed 및 일치하는 파일 이름을 사용하여 생성됩니다.
여기서 문자열(<<))은 이 이름을 sed로 전달합니다. - if [ ! -f “$webp_path” ] : 이 테스트는 “$webp_path”라는 이름의 파일이 이미 존재하는지(!) 논리 비 연산자를 사용하여 확인합니다.
- cwebp : webp 파일이 존재하지 않는 경우 -q 옵션(상태를 출력하지 않음)으로 webp 이미지 파일을 만듭니다.
이 스트립트 실행 가능하도록 권한을 변경합니다.
chmod a+x ~/webp-convert.sh
Code language: PHP (php)
이 스크립트 파일은 이미지 폴더에서 실행합니다.
./webp-convert.sh /var/www/html/webp
Code language: PHP (php)
4. 이미지 폴더 변경 사항을 모니터링 하기
이 단계에서는 notify-tools을 이용해서 이미지 폴더에서 어떤 변경 사항이 발생하는지 모니터링하고 이에 따른 액션읗 취합니다.
4.1. inotify-tools 설치하기
우분투 18.04를 위한 inotify-tools 바이너리 패키지가 있기 때문에 apt-get 명령어로 inotify-tools를 설치할 수 있습니다.
sudo apt-get update -y
sudo apt-get install -y inotify-tools
Code language: PHP (php)
참고로 CentOS 7을 이용한다면 다음 명령어를 이용해서 설치할 수 있습니다.
sudo yum install epel-release
sudo yum install inotify-tools
Code language: PHP (php)
4.2. inotify-tools 이용한 모니터링 스크립트 작성
inotifywait -q -m -r --format '%e %w%f' -e close_write -e moved_from -e moved_to -e delete $1
Code language: PHP (php)
inotifywait
: 이 명령어는 특정 폴더의 변경 내용을 모니터링 합니다.-q
: 이 옵션은inotifywait
작동 시 불필요한 소리와 메세지를 내지말도록 합니다.-m
: 이 옵션은inotifywait
를 계속 실행하고, 어느 한 이벤트가 끝나도 종료하지 않습니다.-r
: 이 옵션은 지정된 폴더와 하위 폴더 모니터링을 반복적으로 실행합니다.--format
: 이 옵션은inotifywait
에게 이벤트 이름과 파일 경로를 이용하여 변경 사항을 모니터링하도록 합니다.- –format ‘%w%f’ : /complete/path/file.name과 같은 형식으로 파일을 인쇄(print out)
- 모니터링하는 이벤트는 close_write(파일을 만들고 디스크에 기록을 완료할 때 발생), moved_from 및 moved_to (파일 이동 시) 및 delete (파일 삭제 시)입니다.
$1
: 변경된 파일 경로를 가지고 있는 위치 매개 변수
| grep -i -E '\.(jpe?g|png)$' --line-buffered
Code language: PHP (php)
- grep : 이 명령어를 사용해 변경된 파일이 JPEG나 PNG 파일인지 확인합니다.
- -i : 이 옵션은 grep에게 대문자, 소문자를 무시하도록 합니다.
- -E : 이 옵션은 grep이 확장 정규 표현식을 사용하도록 합니다.
- –line-buffered : 이는 grep에게 일치하는 행을 while 루프에 전달하도록 지시합니다.
| while read operation path: do
# commands
done;
Code language: PHP (php)
- 여기서는 read 명령으로 while 루프를 만듭
- read는 inotifywait가 감지 한 이벤트를 처리하여 $ operation이라는 변수에 처리하고 파일 경로는 $ path라는 변수에 지정합니다.
while 루프가 이벤트를 확인하면, 그 결과에 따라 다음 명령을 수행합니다.
- 새로운 이미지 파일을 생겼거나 대상 폴더로 이동해온 경우 이 이미지에 대한 WebP 파일을 만듭니다.
- 관련 이미지 파일이 삭제되거나 대상 폴더에서 다른 곳으로 이동한 경우 WebP 파일을 삭제합니다.
루프 내부에는 세가지 주요 섹션이 있습니다. webp_path라고 불리우는 변수는 해당 이미지의 WebP에 대한 경로 정보를 가지고 있습니다.
webp_path="$(sed 's/\.[^.]*$/.webp/' <<< "$path")";
Code language: PHP (php)
if [ $operation = "MOVED_FROM" ] || [ $operation = "DELETE" ]; then
# commands to be executed if the file is moved or deleted
elif [ $operation = "CLOSE_WRITE,CLOSE" ] || [ $operation = "MOVED_TO" ]; then
# commands to be executed if a new file is created
fi;
Code language: PHP (php)
- 만약 파일이 다른 곳으로 옴겨졌거나 지워졌으면 WebP 파일을 지웁니다.
if [ -f "$webp_path" ]; then
$(rm -f "$webp_path");
fi;
if [ $(grep -i '\.png$' <<< "$path") ]; then
$(cwebp -quiet -lossless "$path" -o "$webp_path");
else
$(cwebp -quiet -q 90 "$path" -o "$webp_path");
fi;
Code language: PHP (php)
만약 이미지가 새로 만들어졌다면 아래 조건에 따라 압축이 이루어집니다.
- 만약 PNG 이미지라면 무손실 압축을 실시
- PNG 이미지가 아니라면 손실 압축을 실시
이미지 폴더를 모니터링하고 변화에 따른 후속 조치를 취하는 전체 스크립트는 아래와 같습니다. 이 스크립트를 watchers.sh에서 반영합니다.
nano watchers.sh
Code language: PHP (php)
아래 스크립트를 watchers.sh에 포합시킵니다.
#!/bin/bash
echo "Setting up watches.";
# watch for any created, moved, or deleted image files
inotifywait -q -m -r --format '%e %w%f' -e close_write -e moved_from -e moved_to -e delete $1 \
| grep -i -E '\.(jpe?g|png)$' --line-buffered \
| while read operation path; do
webp_path="$(sed 's/\.[^.]*$/.webp/' <<< "$path")";
if [ $operation = "MOVED_FROM" ] || [ $operation = "DELETE" ]; then # if the file is moved or deleted
if [ -f "$webp_path" ]; then
$(rm -f "$webp_path");
fi;
elif [ $operation = "CLOSE_WRITE,CLOSE" ] || [ $operation = "MOVED_TO" ]; then # if new file is created
if [ $(grep -i '\.png$' <<< "$path") ]; then
$(cwebp -quiet -lossless "$path" -o "$webp_path");
else
$(cwebp -quiet -q 90 "$path" -o "$webp_path");
fi;
fi;
done;
Code language: PHP (php)
watchers.sh 파일을 실행가능토록 권한을 변경합니다.
chmod a+x ~/webp-watchers.sh
Code language: PHP (php)
이 배치 파일은 아래와 같은 형식으로 사용합니다.
./webp-watchers.sh /var/www/html/webp > output.log 2>&1 &
Code language: PHP (php)
5. HTML에서 WebP 이미지 사용
여기에서는 아파치에서 WebP 이미지 파일을 활용할 수 있도록 만드는 방법을 설명합니다.
먼저 /var/www/html/webp 폴더에 .htaccess
파일을 만듭니다. /var/www/html/webp/.htaccess
nano /var/www/html/webp/.htaccess
Code language: PHP (php)
아래 내용이 반영됩니다.
<ifModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{REQUEST_URI} (?i)(.*)(\.jpe?g|\.png)$
RewriteCond %{DOCUMENT_ROOT}%1.webp -f
RewriteRule (?i)(.*)(\.jpe?g|\.png)$ %1\.webp [L,T=image/webp,R]
</IfModule>
<IfModule mod_headers.c>
Header append Vary Accept env=REDIRECT_accept
</IfModule>
AddType image/webp .webp
Code language: PHP (php)