이미지 캐시 서버 구축하기 (나만의 CloudFlare 구축하기)

HYEONG HWAN, MUN/ 10월 14, 2018/ 미분류/ 42 comments

이 글의 방법대로 구축하여 런칭한 “짤그램” zzalgram 움짤 어플리케이션을 홍보해봅니다! 완전빠른 속도! 대용량 트래픽 움짤 서비스!
(제가 만든 앱은 아닙니다.)

앱 다운로드(무료) : https://zzalgram.com/


 

이 글에서는 나만의 이미지 캐시 서버를 구축하여, 사이트 속도를 높이고 부하를 줄이는 방법에 대해 설명합니다.

당신의 사이트가 해외 서버를 이용 중이라면 이 방법을 통해 아주 높은 속도 향상효과를 얻을 수 있습니다.

 

CDN 캐시 서비스 업체인 CloudFlare 를 목표로 삼고, 비슷하게 동작하도록 만들어 보겠습니다.

 

구축 방법

해외망이 좋은 서버 고르기.
2018년 현재 한국에서 해외망이 가장 좋은 서버는 AWS 입니다.

AWS 의 상품 중에서 저가형인 Lightsail 을 이용하도록 하겠습니다.

공식사이트 : https://lightsail.aws.amazon.com

운영체제Ubuntu 16.04 LTS 또는 Ubuntu 18.04 LTS 를 선택하세요.

이미지 캐시 서버는 CPU와 Memory를 거의 사용하지 않습니다.
오직 스토리지 용량만 고려하여 선택하세요. 5달러 상품 또는 10달러 상품 선택하시면 됩니다.

AWS Lightsail 은 기본적으로 서버에 유동IP 를 할당하기 때문에, 따로 고정IP 를 발급받아 연결해주어야 합니다. 적당히 웹사이트 콘솔 보고 연결하세요.

 

캐시 처리할 파일 종류 결정하기

CloudFlare 의 경우 다음 확장자에 대해 캐시 처리합니다.

하지만 우리는 이미지 캐시 서버를 만들 것이기 때문에 png, jpg, jpeg, gif 만 캐시처리 할 것입니다. 더 많은 확장자를 캐시처리를 하고 싶으면 예제의 config.php 파일을 수정해서 사용하세요.

 

캐시 파일의 생명주기 정하기

5일동안 사용되지 않으면 삭제되게 정함.

 

이미지 캐시 도메인 정하기

여러분이 자주가는 대형 커뮤니티를 보고 따라하시면 됩니다.

 

이 글의 예제에서는 이미지캐시 도메인으로 img.lael.be 를 사용하겠습니다.

 

웹서버 구축

일반 웹서버와 동일하게 구축하시면 됩니다.
Apache 웹서버 또는 Nginx 웹서버를 구축해주세요. (아무거나 취향에 맞게)

Ubuntu 16.04 + 웹서버 구축방법 (MySQL 은 설치할 필요 없음) https://blog.lael.be/post/73

Ubuntu 18.04 + 웹서버 구축방법 (MySQL 은 설치할 필요 없음) https://blog.lael.be/post/7264

또는 일반 웹호스팅에서도 사용 가능합니다.

 

이미지 캐시 사이트 설치

이미지 캐시 웹사이트에 다음의 소스 코드를 넣으시면 됩니다.

소스 둘러보기 : https://github.com/laelbe/my-image-cdn/tree/master/www

다운로드 : https://github.com/laelbe/my-image-cdn/archive/master.zip

 

- .htaccess 파일

불펌 방지 코드를 넣어두었습니다. 적절하게 수정하세요.

- invalid_referer.png 파일

이미지 링크 사용을 허용한 도메인이 아닐 경우 이 이미지가 대신 표시됨. (예제에서는 투명이미지로 설정)

- config.php 파일

$original_host , $allowed_extension 부분을 적절하게 수정하세요.

 

- NGINX 사용자의 경우 .htaccess 파일이 동작하지 않으니 .htaccess 파일 변경 대신 다음의 설정을 적용하세요.

https://blog.lael.be/demo-generator/imagecdn/my-example-site.com.php

 

일정시간이 지난 캐시파일 삭제하기

반복 실행 등록 (crontab 등록)

# crontab -e

매일 새벽 4시 10분에 삭제 명령이 실행되도록 설정. (일반적으로 새벽 4시에 사용자가 적음.)
파란색 부분을 수정해 주세요.

10 4 * * * /usr/bin/find /home/imagecdn/www -mindepth 2 -atime +5 -type f \( -iname \*.png -o -iname \*.jpg -o -iname \*.jpeg -o -iname \*.gif \) | xargs rm 1>/dev/null 2>/dev/null

* 옵션 설명
-mindepth 2 : 최상위 폴더는 삭제대상에서 제외.
-atime +5 : 최종 access 한지 5일이 지났을 경우.
-type f  : 파일만 검색
-iname 파일명 : 조건 파일명 검색
-o : OR (조건문 OR)
1>/dev/null : 명령어의 동작 출력이 있을 경우 화면 표시하지 않음
2>/dev/null : 명령어의 오류 출력이 있을 경우 화면 표시하지 않음

 

운영 중인 웹사이트에서 이미지 링크 수정

예를 들어 https://blog.lael.be/wp-content/uploads/2018/10/s2.png 링크가 있다면
https://img.lael.be/wp-content/uploads/2018/10/s2.png 로 변경합니다.

출력코드에 PHP 함수를 사용하여 치환하거나, CDN 관련 플러그인 사용, 디자인 스킨파일 변경, 또는 직접 DB를 수정하여 이미지 경로를 변경하면 됩니다.

 

정상 동작 확인

캐시 파일이 생성된 것을 알 수 있습니다.

 

캐시에 적중(HIT)했는지 적중 안했는지(MISS) 머리 속으로 동작을 그려보세요.

CloudFlare의 이것과 같은 동작이 이루어지고 있다고 생각하시면 됩니다.

 

또한, CloudFlare의 동작과 같이 서버명, 캐시 적중 유무를 헤더에 표시하게 적용해 두었습니다.

< CloudFlare 의 응답헤더 예시 >

 

< 본문 소스 코드의 응답헤더 예시 >

 

 

결론

나만의 (이미지) 캐시 서버가 구축되었습니다!

root 사용자 권한으로 다음 명령어를 실행하시면 실시간 동작 상태를 볼 수 있습니다! (종료방법 : 컨트롤 c)

# tail -f /var/log/apache2/img.lael.be-access.log

DNS 라운드로빈을 통해 다수의 캐시 서버를 두면, 부하가 더욱 분산됩니다. 하지만 하나만 두어도 충분한 기대 효과가 나옵니다.

 

42 Comments

  1. 너무너무 기다렸던 글 입니다 ㅠㅠ 감사합니다.

    몇가지 궁금한 점이 있습니다.

    1. 원본 웹서버는 nginx를 이용하고 있습니다. 이 팁을 따라 이미지서버는 아파치을 이용해도 될까요?
    2. 이 팁을 따라 이미지 서버를 구축후에 DNS 설정 변경을 통해 img 서브도메인을 이미지서버에 할당만 해주고, 여태까지 올렸던 게시글의 이미지 주소만 수정해주면 되는건가요?

    1. 1. 원본 웹서버 종류와 무관하게 사용 가능합니다.
      2. 네 이미지 주소만 바꿔주면 즉시 동작합니다!

    1. 한사람이 아이피 바꿔서 댓글 두개 쓰는줄 알았는데, 두분이셨나보네요.
      감사합니다!

  2. 라엘님, 혹시 같은 사람이 캐시서버에서 같은 이미지를 또 불러올때 캐시 서버 자체에 이미지 브라우저 캐시가 되도록 설정하는 방법을 알려주실 수 있나요?

    1. 이미 적용되어 있어요.
      브라우저 헤더보면 상태코드가 304 라고 나올거에요. 이 경우 헤더만 보내고 body 는 안보냅니다.
      또한 .htaccess 보면 cache-control: public 이라고 되어있는데, 브라우저가 판단해서 애초에 서버에 파일 요청을 하지도 않습니다.

  3. 좋은 자료 감사합니다.

  4. 라엘님 좋은글 감사합니다
    시간 여유 되실때 nginx쪽도 친절하게 만들어주시면 감사하겠습니다

  5. 만약에 js,css 포함시킬려면
    $allowed_image_ext = array(‘png’, ‘jpg’, ‘jpeg’,’gif’);
    $contents_types = array(
    ‘png’ => ‘image/png’,
    ‘jpg’ => ‘image/jpeg’,
    ‘jpeg’ => ‘image/jpeg’,
    ‘gif’ => ‘image/gif’
    에 추가하면 되나요?

    1. 그외에 조금 더 수정해야 합니다. 예제를 보강하도록 하겠습니다.

      1. 감사합니다.JS,CSS,동영상,이미지 캐시하려고 할때도 용량만 고려해서 서버를 선택하면 될까요?

        1. 넵. 트래픽은 충분하기 떄문에 오직 용량만 고려하세요.

  6. 그누보드 + 아미나를 사용하고있습니다

    해당 index 부분을 기존 index에 추가하고 $target_host 부분을 수정했습니다

    그러나 404 에러를 계속 뿜어내고 정상작동을 하지 않습니다 ㅠ

    1. 이 코드는 rewrite 모듈을 필요로 합니다.

      root 권한에서 a2enmod rewrite , a2enmod headers 명령을 실행후 재부팅해보세요.

  7. 라엘님 혹시 .htaccess 이부분을 nginx에 사용할수있게 알려주시면 안될까요?

    제가 구글 검색하면서 해봤지만 잘 적용이 안되서 조언을 좀 얻고자 합니다

    1. 넵 이따가 본문에 추가하도록 할께요.

      1. 라엘님 감사합니다 항상 도움받고 조언 얻으면서 공부를 하네요

  8. 언제나 좋은 글 감사합니다 ㅎㅎ
    다름이 아니라 소스코드에서 약간 수정되면 좋을 것 같은 부분을 알려드리려고 댓글을 남겨봅니다.

    https://github.com/laelbe/my-image-cdn/blob/72966c9f39b8769bbf843a67e5c5bb78f3651bea/www/.htaccess#L25

    해당 라인이 안에 들어가 있는 것이 좀 더 나을 것 같습니다.

  9. 라엘님 안녕하세요

    403에러가 뜨면서 캐시서버에서 이미지를 불러오지못하고 있습니다

    그래서 캐시서버 이미지주소를 입력해보니 이미지가 잘나오는데

    적용사이트 내에서 403에러로 이미지를 불러오지를 못하네요

    그래서 퍼미션문제인가 싶어서 캐시서버 폴더를 755로 바꿨지만 역시 안됩니다

    적용서버 ubuntu16.04 + nginx 와 캐시서버 ubuntu16.04 + nginx 로 셋팅했습니다

    조금만한 조언좀 부탁드리겠습니다

    1. 불펌 방지 코드가 들어가 있습니다. 이미지 링크를 허용할 도메인을 설정해주세요.
      nginx 설정파일 예제의 valid_referers 부분을 수정하세요.

  10. 라엘 님 안녕하세요?

    본문에 VPS로 웹서버를 구축하는 방법을 전제로 설명하셨는데

    웹호스팅에서도 사용할 수 있는 방법인지 질문을 드릴게요.

    감사합니다.

    1. 안녕하세요!
      보통 많은 트래픽 용량을 사용할 경우 이러한 분산처리를 고려하기때문에 클라우드서버 기준으로 작성했습니다.
      위의 코드는, 당연히 일반 웹호스팅에서도 사용가능합니다. 용량을 많이 지원해주는 웹호스팅이 있는지는 모르겠지만요.

  11. 안녕하세요. 좋은 기사 정말 감사합니다.

    그런데 이걸 다른 서버에 하는게 아니라, 하나의 호스팅에서 A레코드로 서브도메인을 만들어 (img.example.com)

    각각의 서버 블록을 지정한 후에, 적용해도 괜찮을까요?

    감사합니다.

    1. 해당 방식으로, 적용해도 좋습니다. 아주 약간의 성능향상이 있습니다.
      네트워크 속도가 좋은곳에 구축하면 성능 향상이 크게 느껴집니다.
      다만, 아트갤러리 사이트를 살펴보았는데, 굳이 이렇게 하지 않아도 충분히 사이트 속도가 빠른 것 같습니다.

      1. 친절한 답변 정말 감사합니다!!!

        저는 오히려 속도가 쇼핑몰 치고 느린것 같았는데, 다행입니다. ㅠㅠ

        위에 알려주신 방법에는 Webp가 포함되어 있지 않지만, 라엘님께서 알려주신 방법을 적용하고자하면, Nginx의 서버 블록에 있는 png|jpg|jpeg|gif 중에서 Webp만 추가해주면 될까요?

        유용한 정보 늘 정말 감사합니다.

        1. 아니요. 확장자를 추가하려면 소스를 조금 더 손봐야 합니다. webp 를 제외하고 적용하시거나, 수정해서 사용하셔야합니다.

  12. 혹시 시간 날때 캐시할 파일 종류 변경 예제도 업데이트 해줄수 없을까요?

    1. 코드가 수정되었습니다. 원하시는대로 사용할 수 있습니다.

      1. 네 감사합니다. 잘 쓰겠습니다.

  13. 훌륭하네요~

    쉽게 잘 적용했습니다.

  14. 안녕하세요 라엘님 제로보드XE대신 라이믹스 1.9.9.4를 사용중입니다만
    aws 서비스에 아차피 + php + phpmyadmin까지 모두 설치한 다음 웹에서 별도의 도메인(aname)을 만들어서 올렸습니다
    물론 var/www/public_html 폴더로 캐시사이트 설치해야할 파일들도 설치를 했고요

    그런데 config.php에서 이미지 캐싱을 해야할 사이트 주소를 넣었음에도 캐싱 사이트(aws)의 폴더엔 새로 추가되는 것이 없습니다 거기에 더불어 캐싱 사이트 페이지는 404 오류가 나옵니다

    혹시 라이믹스 1.9.9.4를 기준으로 설명해 주실 수 있으신가요?

    1. 캐시사이트의 root 사용자 환경에서 a2ensite rewrite 한다음 재부팅해보세요.

  15. 혹시 이 글 타래는 워드프레스 사용자만 해당하는 php인가요?
    라이믹스 1.9.9.4의 경우 php에서 _MYCDN_ 값만 가져와서 error_404로 넘어가는 것 같습니다

    1. 제가 올린 코드는 특정 웹소프트웨어와 전혀 무관하게 동작합니다. 경로가 정확한지, 파일 생성 권한은 있는지, 방화벽 연결은 정확한지 확인해보세요.

      1. ————————————————————————————————————————————–
        RewriteCond %{HTTP_REFERER} !^http(s)?://aaa\.kr [NC]
        RewriteRule \.(jpg|jpeg|png|gif|css|js)$ https://img.aaa.kr/invalid_referer.png [NC,R,L]

        .htaccess는 위 두 개의 값 외엔 원본 그대로 입니다
        *본섭은 aaa.kr이고 캐시 사이트는 img.aaa.kr입니다

        본섭의 ANAME은 집에 설치한 서버에서 구동되고 있으며, 현재 사이트 접속 잘되고 있습니다(불펌 방지 코드 모두 해제 시켰어요)

        캐시 사이트의 ANAME은 AWS/Light Sail의 고정 ip 설정 값으로 지정해서 AWS/Light Sail측 /var/www/html 폴더로 phpinfo.php 또는 index.html은 잘 연결되고 있습니다 혹시나 싶어서 rewrtie 모듈 테스트 해보았으나 rewrite 모듈이 잘 동작하고 있고, 라이믹스나 제로보드 XE를 설치해도 짧은 주소 사용이 가능했습니다

        ———————————————————————————————————————————–
        $original_host = ‘https://aaa.kr’;

        config.php의 original_host는 본섭의 주소를 기재했습니다

        ———————————————————————————————————————————–

        AWS/Light Sail의 VPS의 웹 접속 www/var/html 폴더 내용은 다음과 같습니다
        .htaccess
        cache_function.php
        config.php
        index.php
        invalid_referer.png
        robots.txt

        이 상태서 http://img.aaa.kr을 웹 브라우저에서 열면 404 오류만 나오고 멈춰있습니다 ㅠㅠ

        * 캐시 이미지 사이트(AWS/LS)는 Apache2, php7.2.22+7.2.22용 라이브러리가 설치되어 있습니다
        * 처음 설치시엔 phpmyadmin까지 설치했지만 2번째 테스트에선 제외 시키고 테스트 해봤습니다

        본섭의 iptables는 다음과 같습니다
        111.222.333.44/32는 22번 포트에 접속하게 했습니다
        aaa.bbb.ccc.dd/32는 443번에 접속하게끔 해놓았습니다

        그외 설정은 유분투 설정에서 서술하신 iptables 값을 사용하고 있습니다

  16. 차근 차근 다시 되짚으면서 3-4회가량 해보았으나 결과는 똑같이 캐시 사이트에서 404 오류가 발생합니다

    본섭의 443 포트도 이미지 캐시 서버에서 들어오게끔 해당 공인 IP를 열어주고, 클플의 방화벽에서도 이미지 캐시 서버의 ip와 443포트를 열어도 그렇습니다

    이미지 캐시서버에 본섭에 있는 파일 즉 files/attach에 해당하는 폴더와 파일이름을 그대로 매칭해서 본섭의 게시물에 이미지 첨부를 시키고 해당 URL를 이미미 캐시 서버에 넣고 돌리니 이미지가 정상으로 표기됩니다

    * my-image-cdn-master/www 내부의 폴더는 755, 파일도 755 혹은 777로 권한을 넣어도 캐시 서버의 index.php가 404 오류를 표시합니다

    * my-image-cdn-master/www 내부의 모든 파일을 /var/www/html 폴더에 모두 mv 처리 한 다음 파일 권한 755 폴더 권한 755로 넣거나 777로 넣어도 404 오류가 발생합니다

    * 이미지 본섭의 common/js/plugins/jquery.fileupload/js/main.js의 파일 업로드 이후 게시글 본문에서 보이는 링크를 본섭 링크가 아닌 이미지 캐시 서버의 도메인 주소로 연결해도 (80/443:http/https) 이미지의 alt값만 표시되고 엑박으로 나옵니다

    * 테스트를 위해 이미지 핫링크는 본섭과 클플 그리고 캐시 서버 모두 정지 시킨 상태입니다

    * 결과적으로 캐시 이미지 서버에서 라이믹스나 워드프레스의 설치및 짧은 주소(Rewrite module 구동 확인)는 모두 정상적으로 작동하며 firewall은 모두 해당 포트및 ip를 모두 개방한 상태입니다

    * 설마 외부 ISP만 그런가 싶어서 버추얼 박스에서 가상화 호스트 2개를 만들어 사설 내부 IP로 각각 포트 열고 테스트 했으나 작동하지 않습니다

    * 이미지 본섭과 네이티브 설치된 별도의 유분투 18.04 LTS에다가 다시 한 번 OS 올려서 캐시 서버 테스트 했습니다만 결과는 404 오류입니다 이 테스트는 공인 IP 하나 더 추가하고 공유기 추가한 다음, 잉여 도메인을 ANAME으로 할당 받아 테스트 해봤습니다만 안되고 있습니다

    1. 위의 Ubuntu 18.04 + 웹서버 구축방법 을 따라하셔서 환경 구축이 되었다면 바로 되었을텐데 그렇게 안하신것 같네요.
      이 경우에는 /etc/apache2/sites-available/000-default.conf 파일을 수정해서
      <VirtualHost></VirtualHost> 사이에

      <Directory /var/www/html>
      AllowOverride All
      </Directory>

      추가해보세요.
      chmod 777 /var/www/html 명령도 실행하셔야 올바르게 동작합니다.

  17. 아마도 Directory /var/www/html 구간의 rewrite 모듈이 실행 안되서 그런것 같습니다
    18.04 LTS 설치에선 /var/www까지만 rewrite 모듈이 열리도록 가이드가 되어 있더라고요 ㅎㅎ
    우선 구동은 잘 됩니다 ^^

    자바스크립트로 _read.html에서 img 엘리먼트 속성의 url 값을 이미지 캐시 서버로 가도록 설정을 했는데 문제는… elem.src를 사용해서 치환하게 되면 이미지 캐시서버에 files 폴더가 아니라 https: 폴더로 저장되더군요 ㅎㅎ

    결과적으로 저장은 되니 크게 신경쓰지 않긴 합니다만 깔끔한 코드로 마감되려면 /files/cache 폴더로 가져가도록 자바스크립트에서 img 엘리먼트 속성에 표시된 https://aaa.com 도메인 텍스트만 공백으로 바꿔야겠습니다

    xetown의 다른 분께서 올려주신 문자 치환은 말 그대로 본문에 대한 text만 치환이 되는 형식이고, 조금 위험하지만 ckeditor의 js를 변경하는 방법도 되긴 합니다만 문제는… 제가 ckeditor를 쓰지 않고 프로알라 에디터를 쓰고 있다는거죠 ㅎㅎ

    아무쪼록 괴롭혀 드려서 죄송합니다 ㅠㅠ

    라엘님께선 게시물의 이미지 링크 주소 치환은 어떤 방식으로 변경하신건가요?

    1. xetown에 달린 답변처럼 처리하세요. 당연히 이미지 경로 변경은 화면 출력전 php 단에서 처리되어야 합니다.

Leave a Comment

작성하신 댓글은 관리자의 수동 승인 후 게시됩니다.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>
*
*