이전부터 효율적인 이미지 최적화 방안에 대해 고민을 했습니다. 오늘은 그동안 고민했던 효율적인 이미지 최적화 방안에 대해서 살펴보겠습니다.
1. 이미지 최적화를 고민하는 이유
먼저 이 글을 시작하게 전에 이미지 최적화를 고민한 이유를 간단히 정리해 보았습니다.
1.1. 풍부한 소스를 지닌 콘텐츠로 경쟁력을 높여야
여기와 같은 블로그 사이트든, 쇼핑몰이든 경쟁력을 가지려는 그 사이트가 얼마나 콘텐츠 경쟁력을 가지고 있느냐가 매우 중요해지고 있습니다.
사이트 방문자에게 풍부한 콘텐츠 이용 경험을 주기 위해서는 다양한 정보 소스를 풍부하게 제공하고, 흥미를 끌 수 있도록 배치해 쉽고 편하게 콘텐츠를 이용하도록 만드는 것이 필요합니다.
이러려면 포스팅이든 새로운 콘텐츠이든 이미지나 동영상 등의 정소 원천을 과하다고 생각될 정도로 풍부하게 사용해야 합니다. 웹 페이지가 가질 수 있는 장점을 최대한 활용해야 어느 정도 경쟁력을 가질 수 있습니다.
이전에는 트래픽이나 로딩 속도를 고려해 이미지나 동영상 사용을 자제하거나 최소한으로 활용했다면 앞으로는 콘텐츠 경쟁력 자체에 중점을 둬야 합니다.
이제는 5G가 전면에 등장하는 등 어느 정도 속도와 트래픽을 보장할 수 있는 시대로 나아가고 있습니다.
1.2. 속도도 중요하지만 콘텐츠 질이 더 중요
이제는 트래픽이나 속도가 중요한 것이 아니라 얼마나 풍부하게 충실한 콘텐츠를 만들 수 있느냐가 점점 더 중요해지고 있습니다.
이는 예전부터 지당하게 여견운 일종의 언명이었지만 요즘과 같이 동영상을 비롯한 다양한 콘텐츠 포맷이 경쟁하면서 콘텐츠의 질과 풍부함은 더욱 더 중요해졌습니다.
기술의 발전과 콘텐츠 최적화 기술의 발전으로 이제는 최적화가 용이해져 풍부한 콘텐츠 소스를 적용하면서도 느리다는 느낌을 주지 않아 콘텐츠 질로서 승부할 수 있는 시기가 왔습니다.
1.3. 점차 중요해지는 이용자와 커뮤니케이션
이전에도 중요해졌지만 요즘 더 중요해지는 것이 기업과 이용자 또는 소비자간 커뮤니케이션이 매우 중요해졌습니다.
이는 이용자 리뷰나 Q&A와 같은 방식으로 이용자와 적극적으로 커뮤니케이션해야합니다. 이러다보면 글과 콘텐츠를 올리는 고객 및 이용자가 늘어야 합니다.
사이트에 글을 쓰는 사람이 단 관리자 한명이라면 애정을 가지고 최적화된 이미지를 사용하겠지만 불특정 다수가 글을 쓰는 경우 최적화된 이미지를 사용하는 확율은 그리 크지 않습니다.
더우기 모바일이 보편화된 시점에서 이미지 편집이 쉽지는 않기 때문에 대부분 그냥 활영한 사진을 그대로 올릴 가능성이 높죠.
스마트폰 사진 사양이 고급화되면서 이미지 크기도 커졌기때문에 대용량 파일을 올릴 가능성이 커지지죠.
그렇기때문에 정기적으로 이미지 크기와 품질을 최적화해서 적절한 사이즈로 만들어주는 것이 필요합니다.
2, 이미지 최적화 방법
그러면 어떻게 이미지를 최적활 수 있을까요? 이미지를 최적화해주는 다양항 솔류션이 있음에도 불구하고, 하나하나 점검해 보면 괜찮은 선택지는 별로 없습니다.
그래도 몇가지 고민하고 탐색해본 내용을 여기에 정리해 봅니다.
2.1. 플러그인 + 유료 서비스 이용
워드프레스에는 당연히 수많은 이미지 최적화를 도와주는 플러그인들이 있습니다. 이미지 압축 등 이미지 최적화에 대한 니즈가 많기 때문에 관련 플러그인도 괸장히 많습니다.
그러나 이들 플러그인들을 자세히 살펴보다보면 많은 한계점을 발견하게 됩니다.
쓸만한 플러그인은 유료가 많다
그러나 워드프레스용 플러그인들 상당수는 본격적으로 이미지 최적화를 하려면 일정 비용을 내야 합니다.
이미지 크기를 줄이고, 이미지 압축도를 변경하는 등의 작업은 서버 자체를 활용해야 하므로 워드프레스 내에서 자체적으로 해결하기엔 한계가 큽니다.
그렇기때문에 API 등을 활용해 별도 작업 서버에서 작업 후 보내주는 방식을 취하게 되죠.
그리고 이러한 방식은 무료로 운영하기 힘들기도하고 어느 정도 수요도 있기 때문에 자연스럽게 비지니스 모델로 이어지고 있다는 생각입니다.
이미지 최적화 플러그인을 잘 살펴보면 무료로 쓸만한 플러그인이 많지 않습니다. 쓸만하다싶어 본격적으로 사용하려면 비용을 내야 합니다.
저의 경우 이미지량이 어느 정도인지 봤더니 12GB쯤 되더군요. 워드프레스는 다양한 크기의 이미지를 만들기 때문에 용량이 더 많은 스토리지가 필요합니다.
앞으로도 계속 콘텐츠를 만들면 이미지 및 동영상이 계속 증가할텐데 이를 유료 서비스로 해결하기엔 감당이 되지 않습니다.
워드프레스 속도에 악영향을 끼치기도
그리고 이미지 최적화 플러그인들은 API를 이용하든 다양한 서비스를 제공하기 때문이든 워드프레스 자체 속도에 영향을 미치는 경우가 많습니다.
EWWW Image Optimizer, Smush Image Compression & Optimization, Imsantiy 등은 대표적인 이미지 관리 플러그인이지만 동시에 사이트 속도르 느리게 만드는 플러그인이기도 합니다.
2.2. CDN 활용 – 유료
일부 CDN을 사용하면 이미지 압축 및 WebP 파일 생성등 로딩 속도를 높이고, 트래픽을 절감해주는 기능을 통해서 최상의 이미지 최적화 효과를 누릴 수 있습니다.
예를들어 Akamai은 이미지 품질을 유지하면서도 이미지 용량을 압축해주며, 모바일 및 데스크 탑 PC 등과 같은 이용자 디바이스별로 최적 크기의 이미지를 보여주어 속도를 개선하며, WebP(크롬, 엣지, 파이어폭스 등 지원)나 JPEG-XR/JPEG 2000과 같이 특정 브라우저에서 최고 효과를 내는 이미지 포맷으로 변환해 보여줍니다.
다만 이런 서비스는 비쌉니다. Akamai은 1TB 트래픽당 350$ 사용료를 받습니다.
무료 플랜이 있는 Cloudflare의 경우에도 자동으로 기기에 맞추어 압축해 주는 서비스는 유료(월 20$)인 프로부터 제공합니다.
2.3. 이미지 최적화 솔류션 – 유료
또한 이미지 최적화 서드파티 솔루션업체드링 많이 존재합니다.
Cloudinary, imgix, Fastly’s Image Optimizer, Instart Logic’s SmartVision, ImageOptim API등이 그것인데요. 이들 업체는 이미지 최적화를 자동으로 해주는 종합 솔류션들을 탑재하고 비지니스를 하고 있습니다.
당연히 이들은 제한적으로 무료 서비스도 제공하지만 제대로 사용하려면 유료로 서비스를 이용해야 합니다.
위 리스트중에서 맨 처음으로 언급된 Cloudinary는 Free/Plus/Advanced/Custom 서비스가 있는데요.
Free 플랜의 경우 월 트래픽을 25GB를 줍니다.. 저의 경우 최소 300GB가 나오기때문에 Free 플랜은 사용 불가하고 월 99$짜리 Plus 플랜을 사용해야 합니다.
2.4. 서버에서 자체적으로 관리 – 무료
비용 문제나 속도 저하 문제로 플러그인을 사용할 수 없다면 서버에서 자체적으로 이이미지 최적화를 할 수 밖에 없습니다.
다행히 우분투와 같은 서버에서 적용할 수 있는 다양한 이미지 최적화 패키지들이 존재하기 때문에 이를 잘 활용하면 완벽하지는 않지만 해결 가능할 것입니다.
물론 서버에서 작동하도록 만들어야하므로 상당한 서버 운용 능력이 필요하다는 어려움은 있습니다.
구체적인 방법은 다음 장에서 차분히 설명하기로 하죠.
3. 서버에서 이미지 관리 프로세스
그러면 이제부터 서버에서 이미지 관리하는 방안을 살펴보도록 하겠습니다.
참고로 저는 Vultr VPS를 이용하고 있으며, Ubuntu 18.04에 웹서버는 NGINX를 사용하고 있기 때문에 이를 기반으로 설명해 보고자 합니다.
- 서버 업체 : Vultr(일본 동경)
- 서버 상품 : High Frequency 4GB RAM, 2 CPU
- 서버 타입 : Ubuntu 18.04
- 웹서버 : NGINX
조금 더 구체적으로 어떤 솔류션을 상요해야 할까요? 무슨 작업이 필요할까요?
다양하고 훌륭한 방법이 많이 있겠지만 저는 아래와 같은 프로세스를 사용했습니다.
- 이미지 최적화를 진행하기 전에 최적화 대상 이미지들을 백업받습니다.
- 그 다음 업로드된 이미지 리사이즈 여부를 검토, 리사이즈 합니다. 이때 기준은 사이트 도구 – 미디어에서 정의하는 최대 이미지 사이즈에 맞추기로 합니다.
저는 최대 이미지 폭을 1024로 정했기 때문에 폭이 1024를 넘으면 1024로 줄이도록 했고
이미지 높이는 어쩔 수 없이 긴 이미지를 사용하는 경우가 많아서 이는 컨트롤하지 않기로 했습니다. 쇼핑몰의 경우 설명을 이미지로 대체해 아주 긴 이미지를 사용하는 경우가 많죠. - 다음으로는 JPEG와 PNG 이미지를 압축합니다.
- 다음으로는 WebP나 JPEG-XR과 같은 특정 브라우저에서 효율적인 이미지 포맷을 생성합니다.
- 이미지가 효과적으로 이용자들에게 노출될 수 있도록 Lazy Loading을 적용합니다.
이러한 이미지 최적화 프로세스는 서버에 새로운 이미지가 발생시마다 바로 바로 할 수도 있고 정기적으로 모아 한번에 처리하는 방법이 있습니다.
대부분 서비스는 이미지가 새로 생성되는 순간 관련 작업을 진행해 항상 최적의 상태로 이미지를 최적화합니다.
그러나 이러한 방식은 서버에 무리를 줄 수도 있기 때문에 일정 시간만다 일괄 처리(Batch) 하는 것도 나쁘지는 않을 듯 합니다.
여기에서는 더 적용하기가 쉽기 때문에 크론탭을 사용해 일정 시간마다 일괄 처리하는 방법을 채택해 설명드립니다. 저는 1시간마다 실행토록 만들었습니다.
4. 서버를 이용한 이미지 최적화 시스템
여기서터는 위에서 정의한 프로세스에 따라서 이미지 최적화 시스템(?)을 구축하는 구체적인 방법을 살펴봅니다.
4.1. 이미지 백업
이미지 최적화를 진행 전 백업을 진행합니다.
최적화 시스템 구축 방법에 따라 해당 이미지만을 백업 받을 수도 있고, 폴더를 통채로 백업받을 수도 있습니다.
저는 서버 공간도 남아돌고, CPU도 남아돌고 있기 때문에 폴더채 백업받는 방안을 선택했습니다. 그리고 이는 우선 서버 내에서 백업을 하는 것으로 했습니다.
4.1.1 백업 디텍토리 만들기
# mkdir /backup # backup 디렉토리 만들기
# chmod +x /backup # 퍼미션 조정
Code language: PHP (php)
4.1.2. 백업 스크립트 만들기
이어서 백업 스크립트를 만듭니다. 이걸 실핼해도 되고, 뒤에서 설명하는 크론탭에서 자동 실행토록 하면 됩니다.
# 이미지 최적화 진행 전에 백업하기
tar -zcvf /backup/"happistimagebackup$(date +%y%m%d%H%M).tgz" /home/happist/wp-content/uploads/2020 1>/dev/null 2>/dev/null
Code language: PHP (php)
4.1.3. 오래된 백업 파일 삭제
백업을 계속하다보면 엄청난 백업 파일이 쌓이게 됩니다. 그러면 아무리 서버 용량이 많아도 곧 용량 부족 상태에 이르게 되겠죠.
그래서 일정 시간이 경과한 백업 파일은 삭제하도록 합니다. 여기서는 10일 지난 백업 파일은 삭제하도록 했습니다.
find /backup/ -type f -mtime +10 | sort | xargs rm -f
Code language: PHP (php)
워드프레스 자동 백업 시스템에 대해서는 아래 글을 참조하세요.
4.2. 이미지 리사이즈
먼저 이미지가 새로 업로드되면 이미지가 지나치게 크지는 않은지를 검토합니다.
이 전 글에서도 언급했지만 사이트에 글을 쓰는 사람이 단 관리자 한명이라면 애정을 가지고 최적화된 이미지를 사용하겠지만 불특정 다수가 글을 쓰는 경우 최적화된 이미지를 사용하는 확율은 그리 크지 않습니다.
더우기 모바일에서 댓글 등의 글을 쓴다면 모바일에서 이미지 편집이 쉽지는 않고 그 귀찮은 일을 할 사람이 거의 없기 때문에 대부분 그냥 활영한 사진을 그대로 올립니다.
스마트폰 카메라 사양이 고급화되면서 이미지 크기도 커졌기때문에 대용량 파일을 그냥 올릴 가능성이 커졌습니다. 물론 댓글이나 상품 리뷰 시 이미지를 사용하지 않토록 만들었다면 별 문제는 없지만 대세는 적극적으로 이미지를 댓글과 상품 리뷰에 적용하고 있는 상황이기도 합니다.
그렇기때문에 정기적으로 이미지 크기와 품질을 최적화해서 적절한 사이즈로 만들어주는 것이 필요합니다.
저는 이러한 이미지 크기를 점검해 지나치게 크다면 사이즈를 줄이는 것을 Imagemagick를 이용해 구현했습니다.
기준으로 폭만 변경하려면 widthxheighr중에서 앞의 width만 적어주고, 높이를 맞추려면 xheight를 사용합니다. 아래 내용을 보시고 제가 사용한 명령어를 그 아래에 소개해 놓았습니다.
- 폭만 변경하여면 width> 예를 들어 1024>
- 높이만 변경하려면 xheight> 예를 들어 x1024>
# JPEG 이미지가 지나치게 크다면 폭을 1024px로 줄임
find /home/happist/wp-content/uploads/2020 -iname '*.jpg' -exec convert \{} -verbose -resize 1024\> \{} \;
# PNG 이미지가 지나치게 크다면 폭을 1024px로 줄임
find /home/happist/wp-content/uploads/2020 -iname '*.png' -exec convert \{} -verbose -resize 1024\> \{} \;
Code language: PHP (php)
ImageMagick를 이용한 이미지 리사이즈에 대해서는 아래 글을 참조해 보세요.
4.3. 이미지 압축
적절한 크기의 이미지로 사이즈 조정되었다면 각 이미지를 압축하는 단계로 진입니다. 이미지 압축 대상은 가장 많이 사용하는 JPEG와 PNG 이미지입니다.
JPEG 이미지 압축 방법
JPEG 이미지를 압축하는 방법은 여러가지가 소개되어 있습니다. 각기 자기 방법이 최고라고 주장하고 있죠.
그렇지만 전문가들의 평가를 보면 MozJPEG와 Guetzli를 가장 좋은 JPEG 이미지 압축 방법으로 소개하고 있습니다.
그렇지만 Guetzli는 가장 압축 효과가 뛰어난 대신 인코딩 시간이 많이 걸리고, Progressive를 지원하지 않는등 약점이 있습니다.
그래서 저는 MozJPEG를 사용하는 JPEG-recompress를 사용하기로 했습니다.
JPEG-recompress를 이용해 JPEG와 PNG 이미지를 압축하는 아래와 같은 명령을 사용했습니다.
# jpeg-recompress를 이용 JPEG 이미지 압축
find /home/happist/wp-content/uploads/2020 -type f -iname '*.jpg' -exec jpeg-recompress --quality medium --min 60 --method smallfry \{} \{} \;
Code language: PHP (php)
JPEG 압축 방법에 대한 설명은 아래 글을 참조하세요
PNG 파일 압축 방법 – pngquant 사용
마찬가지로 PNG 이미지 압축 방법도 여러가지가 있지만 가장 효율이 좋은 압축 방법으로 pngquant가 추천되고 있기에 이를 사용하기로 했습니다.
pngquant를 이용한 PNG 이미지 파일 압축 명령을 아래와 같습니다.
# pngquant를 이용 PNG 이미지 압축
find /home/happist/wp-content/uploads/2020 -iname "*.png" -exec pngquant --force --quality=40-100 --skip-if-larger --strip --verbose \{} --output \{} \;
Code language: PHP (php)
pngquant를 비롯한 PNG 이미지 파일 압축에 대한 내용은 하기 포스팅을 참조하세요
4.4. WebP 적용 및 WebP 이미지 생성
기존 JPEG이미지보자 20%이상 압축효과가 좋다는 WebP 이미지를 사용할 수 있도록 만들고 WebO 이미지를 생성하는 방법을 알아 봅니다.
여기서는 아주 간단히 정리해 설명하니 자세한 내용은 아래 링크하는 포스팅을 참조하시기 바랍니다.
WebP이미지를 사용 가능하게 만들자.
웹서버가 NGINX인 경우 WebP를 지원하는 브라우져가 WebP 이미지를 인식토록 하기위해 아래와 같은 과정을 거칩니다.
먼저 NGINX 웹서버 동작을 설정하는 http
블락안에 다음 코드를 추가합니다.
map $http_accept $webp_suffix {
default "";
"~*webp" ".webp";
}
Code language: PHP (php)
다음으로는 server 블락안에 다음 코드를 추가합니다.
이는 브라우져가 WebP 이미지를 지원하는 경우, 모든 이미지(jpg, png)에 대한 WebP 이미지를 로딩하도록 합니다.
location ~* ^.+\.(jpe?g|png) {
add_header Cache-Control "public, no-transform";
add_header Vary "Accept-Encoding";
try_files $uri$webp_suffix $uri =404;
expires max;
}
Code language: PHP (php)
WebP 이미지 생성
그 다음으로는 WebP 이미지를 만들기 위해 아래와 같은 명령을 사용합니다.
물론 이 명령이 제대로 실행되면면 사전 서버에 webp 패키지를 설치해야 합니다.
apt-get install webp
Code language: PHP (php)
JPEG 이미지나 PNGㅇ 이미지에 대한 WebP 이미지 생성은 아래와 같은 명령어를 사용합니다.
# JPEG와 PNG 이미지 파일을 WebP파일로 변환
echo "===== Converting images into WebP .webp ====="
for x in `find /home/happist/wp-content/uploads/2020 -type f \( -iname \*.jpeg -o -iname \*.jpg -o -iname \*.JPG -o -iname \*.png \)`
do cwebp -quiet -q 80 ${x} -o ${x}.webp;
echo "Converted $x to ${x}.webp"
done
Code language: PHP (php)
위와 같이 WebP 이미지 이용에 대해서는 아래 포스팅을 참조해 보시기 바랍니다.
4.5. 이미지 Lazy Loading 적용
페이지 로딩 시 페이지 전체의 이미지를 한꺼번에 로딩하지 말고 이용자가 이미지를 볼 시점에 로딩시켜주자는 것이 lazy Loading인데요.
이 lazy loading의 효과나 사용자 경험 관련해서는 긍정과 부정이 섞여 있습니다. 심지어 lazy loading은 인터넷 속도가 느리던 시절의 유산이므로 요즘에는 전혀 신경쓸 필요가 없다는 주장도 있습니다.
사용자 경험 관점에서 마우스를 내리면 그제야 이미지가 로딩되는 경험은 그리 좋은 경험은 아닙니다.
그렇지만 유튜브의 경우 지나치게 많은 이미지와 자바스크립트 등을 로딩하면서 확실히 속도를 늦추고 있기 때문에 Lazy Loading 효과가 아주 극명합니다.
저는 Lazy Loading은 유튜브 동영상과 이미지 lazy loading을 지원하는 플러그인을 사용해 로딩 시간이 많이 걸리는 문제를 해결했습니다.
5. 이미지 최적화 크론탭 설정
위에서 설명한 일련의 이미지 최적화 과정을 하나씩 하나씩 실행하기는 쉽지 않으므로 우분투 서버의 크론탭 기능을 활용해 자동화 합니다.
저의 경우 매시 15분마다 살행되도록 성정했습니다.
실행 배치 파일 만들기
먼저 실행 배치 파일을 만듭니다. 여기서는 nano 편집기를 이용해 webp.sh 파일을 만듭니다.
nano webp.sh
Code language: PHP (php)
nano 편집기가 열리면 아래와 같은 실행 명령문을 입력하고 저장합니다.
# 이미지 최적화 진행 전에 백업하기
tar -zcvf /backup/"happistimagebackup$(date +%y%m%d%H%M).tgz" /home/happist/wp-content/uploads/2020 1>/dev/null 2>/dev/null
# 10일이 지난 백업 파일은 삭제합니다.
find /backup/ -type f -mtime +10 | sort | xargs rm -f
# JPEG 이미지가 지나치게 크다면 폭을 1024px로 줄임
find /home/happist/wp-content/uploads/2020 -iname '*.jpg' -exec convert \{} -verbose -resize 1024x10240\> \{} \;
# PNG 이미지가 지나치게 크다면 폭을 1024px로 줄임
find /home/happist/wp-content/uploads/2020 -iname '*.png' -exec convert \{} -verbose -resize 1024x10240\> \{} \;
# jpeg-recompress를 이용 JPEG 이미지 압축
find /home/happist/wp-content/uploads/2020 -type f -iname '*.jpg' -exec jpeg-recompress --quality medium --min 60 --method smallfry \{} \{} \;
# pngquant를 이용 PNG 이미지 압축
find /home/happist/wp-content/uploads/2020 -iname "*.png" -exec pngquant --force --quality=40-100 --skip-if-larger --strip --verbose \{} --output \{} \;
# JPEG와 PNG 이미지 파일을 WebP파일로 변환
echo "===== Converting images into WebP .webp ====="
for x in `find /home/happist/wp-content/uploads/2020 -type f \( -iname \*.jpeg -o -iname \*.jpg -o -iname \*.JPG -o -iname \*.png \)`
do cwebp -quiet -q 80 ${x} -o ${x}.webp;
echo "Converted $x to ${x}.webp"
done
Code language: PHP (php)
이제 자동 실행되도록 크론탭을 설정합니다.
crontab -e
Code language: PHP (php)
아래와 같이 15분마다 webp.sh 파일이 실행되도록 합니다.
15 * * * * webp.sh
Code language: PHP (php)
크론탭 설정을 마쳤으면 크론탭이 재시작할 수 있도록 합니다. 아래 명령어를 사용합니다.
service cron restart
Code language: PHP (php)
크론탭 사용 방법에 대해서는 아래 포스팅을 참조하세요.