이번 장에서는 서비스 구축시 클라이언트에게 최적의 이미지를 제공하기 위해 필요한 이미지 처리서버를 구축해 보겠습니다.

현대의 서비스들은 웹, 모바일 웹, android, ios등 다양한 다양한 플랫폼으로 서비스가 되고 있습니다. 각각의 플랫폼은 같은 이미지라 하더라도 플랫폼별로 권장되는 최적의 이미지 사이즈가 있습니다. 원본 이미지 하나로는 플랫폼 전체를 커버할 수 없게 되었습니다. 따라서 원본 이미지로 다양한 사이즈의 썸네일을 만들어내거나, 각각의 이미지를 최적화 하여 서비스 하기 위한 이미지 솔루션이 필요하게 되었습니다.

thumbor와 varnish를 이용하면 제법 쓸만한 이미지 처리서버의 구축이 가능합니다. 그 방법에 대해 실습해 보도록 하겠습니다.

thumbor

thumbor는 오픈소스 이미지 처리 서비스입니다. python으로 만들어져 있으며 이미지에 다양한 처리를 쉽고 빠르게 적용할 수 있습니다. thumbor의 특징은 기존의 이미지 서비스처럼 사용할 사이즈의 썸네일을 미리 만들어 서비스하는 것이 아니라, 필요한 사이즈의 썸네일을 URL을 통해 유동적으로 생성해낼수 있다는 점입니다.

ex) http://이미지서버주소/unsafe/요청이미지사이즈/원본이미지주소

thumbor에 대한 자세한 내용은 아래 링크에서 확인 할 수 있습니다.
https://thumbor.readthedocs.io/en/latest/index.html

의존성 프로그램 설치

$ sudo yum install ffmpeg libjpeg-dev libpng-dev libtiff-dev libjasper-dev libgtk2.0-dev python-numpy python-pycurl webp python-opencv python-dev python-pip

thumbor 설치

$ sudo pip install thumbor

thumbor config 파일 생성

$ sudo thumbor-config > /etc/thumbor.conf

thumbor config 수정

기본 설정들은 모두 주석 처리되어 있습니다. 몇가지 설정을 활성화 하고 값을 변경합니다.

QUALITY = 95 # 이미지 처리시 결과물 퀄리티 변경 80->95
PRESERVE_EXIF_INFO = True # EXIF값을 유지.
ENABLE_ETAGS = False # Etag가 자동 생성되지 안도록 처리.
STORAGE_EXPIRATION_SECONDS = 0 # 이미지 유효시간. vanish를 사용하여 이미지를 캐시할 것이므로 0으로 설정.

thumbor 실행

아래 방법으로 띄우면 서버 데몬으로 뜨지 않습니다. 따라서 crtl+c를 누르면 종료됩니다. 아래 내용의 Supervisor를 이용하여 서버 데몬으로 띄우도록 하겠습니다.

$ thumbor

Supervisor

Supervisor는 사용자가 UNIX와 유사한 운영 체제에서 여러 프로세스를 쉽게 제어 할 수 있도록 도와주는 프로그램입니다. Supervisor를 이용하면 thumbor를 쉽게 서버 데몬으로 구성이 가능합니다. 다음 명령어로 설치합니다.

$ sudo pip install supervisor

Supervisor 설정

/etc/supervisord.conf를 생성합니다. 아래 내용 중 –port=900%로 설정하고 numprocs=2로 설정하면 9001, 9002번 포트로 thumbor가 자동으로 생성됩니다. 로그 위치를 지정하면 thumbor에서 처리되는 로그를 Supervisor가 해당 경로로 출력되도록 처리해 줍니다.

$ sudo vi /etc/supervisord.conf
[supervisord]
[program:thumbor]
command=thumbor --conf="/etc/thumbor.conf" --port=900%(process_num)s
process_name=thumbor900%(process_num)s
numprocs=2
autostart=true
autorestart=true
startretries=3
stopsignal=TERM
stdout_logfile=/var/log/thumbor900%(process_num)s.stdout.log
stdout_logfile_maxbytes=1MB
stdout_logfile_backups=10
stderr_logfile=/var/log/thumbor900%(process_num)s.stderr.log
stderr_logfile_maxbytes=1MB
stderr_logfile_backups=10

Supervisor 실행

설정한 conf파일로 Supervisor를 실행합니다. 프로세스를 확인하면 Supervisor와 thumbor 프로세스가 실행되고 있음을 확인할 수 있습니다.

$ sudo supervisord -c /etc/supervisord.conf
$ ps -ef | grep supervisord
root     24420     1  0 11:36 ?        00:00:00 /usr/bin/python2 /bin/supervisord -c /etc/supervisord.conf
$ ps -ef | grep thumbor
root     24421 24420  0 11:36 ?        00:00:00 /usr/bin/python2 /bin/thumbor --conf=/etc/thumbor.conf --port=9001
root     24422 24420  0 11:36 ?        00:00:00 /usr/bin/python2 /bin/thumbor --conf=/etc/thumbor.conf --port=9000

Varnish 설치

Varnish는 오픈소스 웹 캐시 프로그램입니다. thumbor만으로도 사용가능하지만 동일한 static resource에 대한 반복 요청을 Varnish를 통해 캐시하여 빠르게 처리할 수 있습니다. thumbor앞단에 Varnish캐시를 적용하면 thumbor단독으로 사용하는것보다 최소 2배에서 10배 이상 뛰어난 응답속도 개선을 얻을 수 있습니다.
Varnish는 설치하기 전에 epel reposotiry를 install 해야 합니다. install후에 varnish를 설치합니다.

$ sudo amazon-linux-extras install epel
$ sudo yum install -y varnish

Varnish 설정 수정

Varnish를 thumbor 앞단의 캐시로 사용할 것이므로 아래 설정 파일의 주석을 풀고 값을 수정합니다.

$ sudo vi /etc/varnish/varnish.params
VARNISH_LISTEN_ADDRESS=0.0.0.0
VARNISH_LISTEN_PORT=80

thumbor를 서비스 하기 위해 proxy설정 및 purge 관련 설정을 추가합니다.
purge는 varnish의 이미지 캐시를 삭제하는 명령입니다. HttpMethod를 PURGE로 해서 썸네일을 요청하면 캐시가 지워집니다. 이미지주소는 동일한데 원본이 변경되었을경우 PURGE를 요청하면 됩니다. 아무나 요청하면 안되므로 localhost에서만 수행 가능하도록 설정합니다.

$ sudo vi /etc/varnish/default.vcl
vcl 4.0;

import directors;
# 서비스할 thumbor 서버 정보를 세팅
backend thumbor1 { .host ="127.0.0.1"; .port="9000";  .max_connections = 200; .connect_timeout = 5s; .between_bytes_timeout  = 5s; }
backend thumbor2 { .host ="127.0.0.1"; .port="9001";  .max_connections = 200; .connect_timeout = 5s; .between_bytes_timeout  = 5s; }

# purge, ban 요청 가능한 네트워크 목록
acl internal {
    "localhost";
    "127.0.0.1";
}

# 위에서 설정한 thumbor 2대를 varnish에서 round-robin으로 서비스하도록 설정
sub vcl_init {
    new vdir = directors.round_robin();
    vdir.add_backend(thumbor1);
    vdir.add_backend(thumbor2);
}

sub vcl_recv {
    set req.backend_hint = vdir.backend();
    if (req.method == "PURGE") {
         # Purge는 acl목록의 네트워크에서만 가능
         if (!client.ip ~ internal) {
            return (synth(405, "This IP is not allowed to send PURGE requests."));
         }
         return (purge);
    }

    # 이미지 주소 ?문자열 뒤의 내용을 제거
    if (req.url ~ "\?$") {
        set req.url = regsub(req.url, "\?$", "");
    }
    return (hash);
}

Varnish 실행

$ sudo service varnish start
Redirecting to /bin/systemctl start varnish.service
$ ps -ef | grep varnish
root     27109     1  0 15:00 ?        00:00:00 /usr/sbin/varnishd -P /var/run/varnish.pid -f /etc/varnish/default.vcl -a 0.0.0.0:80 -T : -S /etc/varnish/secret -u varnish -g varnish -s malloc,256M
varnish  27110 27109  0 15:00 ?        00:00:00 /usr/sbin/varnishd -P /var/run/varnish.pid -f /etc/varnish/default.vcl -a 0.0.0.0:80 -T : -S /etc/varnish/secret -u varnish -g varnish -s malloc,256M

테스트

원본 이미지 – 사이즈 : 1680×1050
https://sites.google.com/site/davidenglishpost/_/rsrc/1456907158206/ironman3/Iron-Man-3-slots.jpg

가로x세로 : 300px x 300px 정사각형 Resize & Crop
http://서버주소/unsafe/300×300/https://sites.google.com/site/davidenglishpost/_/rsrc/1456907158206/ironman3/Iron-Man-3-slots.jpg

x세로 : x300px 세로 사이즈 300px 직사각형 Resize
http://서버주소/unsafe/x300/https://sites.google.com/site/davidenglishpost/_/rsrc/1456907158206/ironman3/Iron-Man-3-slots.jpg

-가로x-세로 : -300px x -300px 가로 세로 반전
http://서버주소/unsafe/-300x-300/https://sites.google.com/site/davidenglishpost/_/rsrc/1456907158206/ironman3/Iron-Man-3-slots.jpg

왼쪽상단:오른쪽하단 : 특정 부분 Crop
http://서버주소/unsafe/600×200:900×600/https://sites.google.com/site/davidenglishpost/_/rsrc/1456907158206/ironman3/Iron-Man-3-slots.jpg

필터 효과
http://서버주소/unsafe/300×300/filters:brightness(10):contrast(30)/https://sites.google.com/site/davidenglishpost/_/rsrc/1456907158206/ironman3/Iron-Man-3-slots.jpg

이상으로 thumbor + varnish 서버 구축이 완료되었습니다. 해당 썸네일 서버를 통해 플랫폼별로 최적의 이미지를 제공 할 수 있게 되었습니다!