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

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

https://blog.lael.be/post/7605

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

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

 

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

 

구축 방법

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

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

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

운영체제Ubuntu 18.04 LTS 또는 Ubuntu 22.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 라운드로빈을 통해 다수의 캐시 서버를 두면, 부하가 더욱 분산됩니다. 하지만 하나만 두어도 충분한 기대 효과가 나옵니다.

 

85 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 단에서 처리되어야 합니다.

  18. 안녕하세요. 정말 많은 도움을 받고 있습니다.
    한가지 질문을 드리자면 저같은 경우에는 Proxy를 사용하여 도메인으로 WAS를 분기하고 있는데요.
    그렇게 분기된 도메인의 리소스도 이미지 캐싱할 수 있을까요?
    도메인은 site-enabled의 사용자정의 파일을 만들어 아래처럼 분기처리하고 있습니다.

    ServerName sub-domain1.main-domain.com
    ProxyRequests Off
    ProxyPreserveHost On
    ProxyPass / http://localhost:10000/
    ProxyPassReverse / http://localhost:10000/

    ServerName sub-domain2.main-domain.com
    ProxyRequests Off
    ProxyPreserveHost On
    ProxyPass / http://localhost:10001/
    ProxyPassReverse / http://localhost:10001/

    1. 웹브라우저에서 접속가능한 모든 이미지 경로에 대해서 캐시 구성 가능합니다.
      즉, 원본 서버의 proxy 등의 구성과 무관하게 잘 동작합니다.

  19. 안녕하세요! 위의 팁대로 적용을 해보려고 합니다!
    궁금한게 생겼는데요, 궁금한 것은 제가 본 서버에 nginx 핫링크 방지 코드를 추가시켜뒀는데 만약 이미지 캐시서버를 운영한다 하더라도 굳이 본 서버에 있는 nginx 핫링크 방지 코드를 수정하거나 없앨 필요는 없나요?
    그리고 이미지 캐시 서버는 apache로 해볼 생각인데 .htaccess에서 RewriteCond %{HTTP_REFERER} !^http(s)?://blog\.lael\.be [NC] 이렇게 되어있는 곳에는 본 사이트의 주소를 적으면 안되는게 맞나요?
    rewritecond가 보통 핫링크 차단을 하는 걸로 알고있는데 이렇게 되면 본 사이트를 차단하게 되는 것이니깐요
    그리고 img.example.com 이란 도메인은 다른 서버에서 ‘주’도메인으로 쓰면 되는건가요?

    아 그리고 가장 궁금한건 사진 파일은 분명히 example.com이란 사이트로 올라왔는데 img.example.com 이라는 도메인으로 사진 주소를 치환했을때 어떻게 img.example.com에서 사진 파일이 보일 수 있는지 궁금하네요ㅠㅠ 아무리 생각해봐도 왜 그렇게 될 수 있는지 이해가 잘 안가서요

    초보라서 궁금한게 너무 많네요ㅠㅠ 팁 정말 감사합니다!

  20. 안녕하세요. 냑에서 넘어와 도움되는 글 잘 읽고 있습니다.
    설명하신 방법은 Ubuntu에 설치하는 방법인데 혹시 Centos에서도 무리 없이 작동할까요?
    일반 웹호스팅에서도 가능하다고 하셨는데 OS별 특성을 타는지 궁금합니다.

    1. PHP 만 설치되어 있으면 동작합니다.
      운영체제 종류나 버전과 무관하게 잘 동작합니다.

  21. 항상 글 잘보고 있습니다!

    저희 회사에서 사용할 이미지캐시서버를 만드는데 해당 방법으로는
    이미지 서버도 https인 경우 정상작동하는지 궁금합니다ㅠㅠ
    (시도 해보니 작동이 안되서 ㅠㅠ 제가 잘못 셋팅한건지..)

    1. 당연히 잘됩니다! 저도 쓰고 있고 많은 분들이 이미 쓰고 있어요.

  22. 안녕하세요!
    nginx로 강의 따라 캐시 서버를 만들어봤는데, 어떤 파일을 요청하건 응답 상태는 200으로 텅 빈 html 파일을 보냅니다.
    혹시 이럴 땐 뭐가 문제일까요?

    루트 디렉토리엔 만들어둔 php 파일 등 외엔 아무것도 생성되지 않고 있습니다.

    1. 소스 문제는 아닌것 같고, 웹서버 설정이 잘못되었을것 같아요. 재부팅해보세요.

      1. 재부팅 해도 계속 오류가 떠서 삽질해보니 nginx 설정 파일 문제였네요. 😂

        location ~ [^/]\.php(/|$) {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php7.4-fpm.sock;
        fastcgi_buffers 64 16k;
        add_header my-ray “KR1”;
        add_header cache-control “public, max-age=31560000”;
        }

        이렇게 수정하니 잘 작동합니다!
        감사합니다~

  23. 잘 됩니다. 하지만 그누보드에서 적용해보니 결론적으론

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

    이 부분이 문제더라구요.

    함수치환도 모르고, CDN 플러그인도 없고… 디자인 스킨파일 방법도 모르니 ㅠㅠ DB 수정하는 곳도 한정적이고, 대부분 스킨에서 URL 불러오더라구요.

    아무튼 thumbnail.lib.php에서 CDN URL 붙일 수 있는 곳은 붙여서 글 내부에 썸네일로 출력되는 부분은 모두 CDN으로 적용했습니다.

    아쉽게도 webp를 적용했는데, 불러오는 URL이 webp가 아닌 jpg, png, gif 기존 파일 확장자라서 그 부분은 조금 아쉽습니다만

    오라클 클라우드 무료 인스턴스와도 호환이 잘되고 트래픽 절감에 매우 도움이 많이되고 있습니다.

    감사합니다!

    1. 안녕하세요.
      대부분의 CDN 플러그인들은 CDN URL 이라는 특별 변수를 설정하여 처리합니다.
      DB를 직접 수정하는 것은 별로 추천하지 않습니다.
      Hook 방식을 지원하지 않는 소프트웨어에서, core 코드를 직접 수정하는 것 또한 추천하지 않습니다.

      본문에 따로 적지는 않았으나, 다음을 시도해보세요.
      ==
      wsgvet.com.conf 파일의
      error_log /var/log/nginx/~ 바로 아래줄에

      sub_filter “https://www.wsgvet.com/data/editor/” “https://cdn.wsgvet.com/data/editor/”;
      sub_filter “https://www.wsgvet.com/data/file/” “https://cdn.wsgvet.com/data/file/”;
      ==
      두줄 추가.
      에디터는 이미지만 첨부 할 수 있고, 첨부파일 또한 static 하다는 가정하에 동작하는 코드입니다.
      webp 를 적용하시려면 캐시서버 코드의 config.php 파일을 열어서 편집하시면 됩니다. 옵션으로 설정해뒀습니다.

      시도해보세요. 감사합니다.

      1. 오.. 그누보드에서는 대박인데요.

        모든 첨부파일과 에디터에서 입력되는 파일이 /data 폴더에 들어가니 최고 좋은 방법이네요.

        워드프레스에서도 /wp-content를 똑같은 방식으로 하면 대박이겠는데요.

        에디터는 보통 이미지만 들어가니 상관없고

        첨부파일은 이미지외에 txt나 pdf zip 파일도 들어가니 모두 config.php에 넣어주면 되겠네요.

  24. set $webp_suffix “”;
    if ($http_accept ~* “webp”) {
    set $webp_suffix “.webp”;
    }
    location ~ \.(gif|jpe?g|png)$ {
    add_header Cache-Control “public, no-transform”;
    try_files $uri$webp_suffix $uri $uri/ =404;
    expires max;
    }

    저는 이런 식으로 브라우저에서 webp를 받아들일 수 있으면 첨부파일 확장자명을 jpg 대신 webp로 변환시키는 셋팅을 하고 있어요.

    그런데 이 방법을 써보니 config.php에서 webp를 추가해도 안되더라구요 ㅠㅠ

    실제적으로 요청하는 URL 자체가 jpg, png라서 그런지도 모르겠습니다.

    webp로 요청되면 용량이 정말 많이 줄어들더라구요.

    그 효과까지 누리고 싶었는데 안되더라구요.

    혹시 Nginx에서 CDN을 이용하면서도 브라우저 조건적으로 webp를 받아들일 수 있을때 webp까지 전송할 방법이 있을까요?

    1. 이 부분은 너무 동적이라서 구현이 안될것 같네요.
      확장자가 jpg 이면서 webp를 지원하는 브라우저면 => .webp 를 붙은 파일 응답
      위와같이 고정적인 조건이면 구현이 가능할 수도 있는데,
      try_files $uri$webp_suffix $uri $uri/ =404; 이렇게 원격 서버에서, test.jpg.webp 요청하고, 없으면 test.jpg 요청하는건 무리가 있을것 같네요.
      만약 webp 파일이 항상 존재하는 것이라면, 위의 CDN 서버에서 nginx 구문은 사용하지 마시고, https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/ What to do instead 부분의 예제코드, location, if 를 보시고 응용해서,
      location 이 .jpg 이고, webp 를 accept 할 수 있으면, 확장자를 붙여서 301 redirect 를 하게 구현해보세요.

  25. sub_filter_once off;
    sub_filter ‘https://www.wsgvet.com/data/file/’ ‘https://cdn.wsgvet.com/data/file/’;
    sub_filter ‘https://www.wsgvet.com/data/editor/’ ‘https://cdn.wsgvet.com/data/editor/’;

    이렇게 작성하니 잘되네요!

    그런데 한가지 의문인게, config.php에도 mp4, webm을 넣었는데, mp4와 webm은 캐시가 안되네요.

    동영상 파일이라서 그런걸까요?

    1. 헐.. 다른 서버는 그냥 되네요 -_-;;;;;;

      URL로 직접 표현이 되면 되는 것 같고, 실제 URL을 넣으면 안되고 -_-;;;

      좀 난감하지만 그누보드 5.4에서는 잘 됩니다. ㅎㅎㅎ

      5.3에서 아직 머물고 있지만 5.4에서 잘 되니 넘어가도 될 듯 합니다. ㅎㅎ

    2. 아까 동영상 안됐던게 허용된 도메인 앞에 확장자 있는거에서 동영상 확장자를 지정 안해서 그랬네요.

      이제 발견하고 해결하고 갑니다. ㅎㅎㅎ

      혹시나 동영상도 캐시하고 싶은 분은

      location ~* \.(png|jpg|jpeg|gif|webp|mp4|webm)$ {
      valid_referers none blocked *.naver.com *.daum.net *.namu.wiki *.자신의서버도메인

      Nginx 기준 위와 같이 mp4 webm을 넣어주시면 캐시됩니다~

  26. apache는 substitue 모듈을 사용하면 됩니다.

    https://www.wsgvet.com/ubuntu/129

    여기에 Nginx와 , Apache 웹서버 모두에 적용하는 방법을 적어보았습니다.

    1. 와! 너무 잘 응용해주셔서 감사하네요.
      저도 오랜만에 코드를 조금 더 업데이트 해야겠습니다.
      감사합니다!

  27. 혹시 Nginx나 Apache에서 특정경로만 sub 모듈로 옮기는 것보단

    jpg, png 등 특정 확장자만 대치시킬 수 있는 방법이 있을까요?

    만약에 그게 된다면 굳이 /data/file 등 해당 폴더에 있는 내용물 뿐만아니라, 다른 폴더에 있는 이미지 파일들도 캐시가 가능할 것 같은데요.

    그누보드 뿐만 아니라 세상 모든 사이트에서 가능할 것 같습니다.

    제가 찾아봤는데, 특정 조건에서만 대치시키는 방법은 잘 안보이더라구요.

    만약에 찾는다면, 굳이 플러그인이나 애드온 모듈도 필요없을 것 같습니다.

    1. 만약 그런 모듈이 존재한다고 하여도, 정규식 처리는 연산 비용이 큽니다. 부하가 걸리죠.
      지금처럼 sub 모듈로 해두는게 응용하기도 쉽고, 관리자들도 안헷갈릴 것 같아요.
      그리고 의도하지 않은 부작용이 있을 수도 있습니다. 이미지 태그도 다양하게 사용할겁니다.
      sample.png
      /data/file/free01/sample.png
      //blog.lael.be/data/file/free01/sample.png
      https://blog.lael.be/data/file/free01/sample.png
      관리자가 헷갈리지 않고 확실하게 사용할 수 있도록 가이드 해주는 것 까지만 하는게 나을 것 같아요.

      1. 이미지 태그의 다양성도 중요하겠네요.

        일단은 간단하게 sub모듈이 제일 무난할 것 같습니다.

        Nginx proxy cache로 이미지 캐시 서버 구축도 도전해보려고 합니다.

  28. $allowed_extension[] = ‘png’;
    $allowed_extension[] = ‘PNG’;

    이게 2개가 다르게 인식되는 것 같습니다.

    PNG 확장자가 404가 나와서 PNG를 config.php에 넣어줬더니 인식이 잘 되네요.

    1. 오우 그렇게 사용할 수도 있겠네요. 관련 부분을 업데이트 했습니다.

  29. $original_host 를 더 늘릴수는 없나요?
    지금은 도메인 한개만 작성이 가능한데 여러 도메인을 작성해서 동작할수는 없을까요?

    1. 아무리 생각해도 그렇게 사용하는 사례는 있을것 같지 않네요.

  30. 현재 도메인을 abc.com 이라는 도메인을 쓰고 있고,
    cdn을 구축하고 cdn 도메인을 media.abc.com으로 하고싶습니다.

    현재 abc.com은 서비스 중에 있으며 cdn을 새로 도입하려합니다.

    도메인 셋팅을 어떻게 해야할지 감이 안잡혀 질문글 올립니다.

    1. 우선 media.abc.com 도메인을 생성하고, 서버에 연결합니다.
      그 서버에 본문의 캐시서버 소스를 붙여넣습니다.
      그 후에 약간의 설정만 하면 됩니다.

  31. 맨 처음 접속해서 이미지를 불러올때는 엑스박스가 뜹니다.

    상태 코드는 200인데 엑스박스가 나오네요.

    맨 처음 접속한다음 새로고침을 하면 새로고침을 한 다음 부터는 이미지가 정상 출력이 됩니다.

    어떻게 해결해야할까요ㅜ

    1. 올바른 길로 거의다 오신것 같네요. 실제의 이미지 링크를 알려주시면 확인해보겠습니다.

      1. 현재는 해결을 어찌어찌 하였습니다.

        .htaccess 파일을 어떻게 수정하다보니 적용은 되었습니다.

        아직 어떠한 부분이 정확히 어떤 처리를해서 해결이 되었는지 이해가 잘 되진 않습니다.

        공부를 조금 더 해보고 궁금한점이 있으면 코멘트를 남기겠습니다.

        덕분에 CDN 구축을 하게되었습니다. 좋은 글에 감사드립니다~

  32. 안녕하십니까.
    좋은 팁 감사합니다. 가상서버에서도 큰 도움을 얻었는데 이번에도 도움을 받네요. 🙂

    우선
    .htaccess 파일은
    RewriteCond %{HTTP_REFERER} !^http(s)?://(.+\.)?domain\.com [NC]
    RewriteRule \.(jpg|jpeg|png|gif|css|js)$ https://cdn.domain.com/invalid_referer.png [NC,R,L]
    으로 제 도메인에 맞춰 수정하고
    config.php 파일은
    $original_host = ‘https://domain.com’;
    으로 수정하였습니다.

    처음에는 .htaccess 파일을 수정안했더니
    invalid_referer.png 파일만 나오더군요.
    그 뒤 .htaccess 파일을 수정하니 관련된 이미지들이 404에러가 나옵니다.
    개발자도구 네트워크 탭을 보니

    Response headers 가
    Connection: Keep-Alive
    Content-Type: text/html; charset=UTF-8
    Date: Thu, 25 Feb 2021 03:53:09 GMT
    Keep-Alive: timeout=5, max=98
    my-cache-status: MISS
    my-ray: KR1
    Server: Apache/2.4.39 (Unix) OpenSSL/1.0.2k-fips
    Transfer-Encoding: chunked
    X-Powered-By: PHP/5.6.37
    이런 식으로 type이 이미지가 아니라 text/html로 나오네요.

    어느 부분에서 잘못되어 이렇게 나오는 걸까요?

    1. htaccess 에서 불펌방지 구문을 모두 제거해보셔요.

  33. 라엘님 안녕하세요

    이미지캐시 구축하고 cdn.도메인/이미주주소 하면 잘 나옵니다

    그런데 cdn사용하는 폴더안에 캐시폴더가 안생겨서 hit부분이 miss로 나옵니다

    혹시나해서 임시로 폴더를 만들어서 해보니 hit로 잘나오는데

    cdn으로 사용하는 폴더에 왜 캐시폴더가 안생길까요 ㅠㅠ?

    마지막으로 설정에서 이부분만 에러로그밑에다가 넣어주면
    따로 그누에서 경로수정을 할필요가 없나요?

    sub_filter “https://도메인/data/editor/” “https://cdn.도메인/data/editor/”;
    sub_filter “https://도메인/data/file/” “https://cdn.도메인/data/file/”;

    질문이 많아서 죄송합니다

    1. 안녕하세요.
      폴더가 생성되지 않는것은 권한 문제인 것 같습니다.
      php 코드가 동작할 때의 실행권한을 확인해보세요.
      또는 캐시서버에서 기본 폴더를 생성후에 (그누보드의 경우 /data 폴더) 퍼미션을 777로 설정해보세요. (즉, 권한을 강제로 주는방법임)

      sub_filter 는 데이터가 client 에 전송되기 직전에 실행되는 치환 기능입니다. 따라서 DB나 그누보드상에서 데이터 코드를 수정하지 않아도 모두 변경되어 동작하게 됩니다.
      감사합니다.

      1. 퍼미션과 권한까지 해봤지만 안되서 제가 잘못이해 하고있는거 같아서 여쭈어봅니다

        a도메인 그리고 b도메인이 있습니다 (같은서버를 사용합니다)

        a도메인 기본 사이트

        b도메인 이미지캐시 사용

        위에 방법대로 imgcdn 유저와 폴더를 생성하고 파일복사후 config파일을 수정했습니다

        $original_host =a도메인

        b도메인 conf파일에 해당부분 valid_referers none blocked *.a도메인;

        그리고 엔진엑스 재부팅하하고 b도메인으로 a도메인에 있는 이미지를 불러보면

        잘가져오는데 문제는 캐시폴더가 생성이 안됩니다..ㅠㅠ

        아마존 라이트세일을 이용하고있습니다

        혹시 제가 잘못이해하거나 잘못한 부분이 있는지 궁금합니다..

        1. 해당 도메인 사용자로 로그인한 후에, 웹루트디렉토리로 진입하신후 (일반적으로 # cd www)
          퍼미션변경 (# chmod 777 .) 을 입력해보세요.
          캐시파일이 생성되지 않는 것은 권한 문제입니다.

  34. 안녕하세요 좋은 글 써주셔서 너무 잘 읽었습니다. 감사합니다.
    처음으로 이미지캐싱 서버를 만들어보는 데 설명이 잘 이해가 안되는 부분이 있어서 질문 드립니다.

    1. 다운로드 받은 소스 파일을 어디에 복사해야 하는지 잘모르겠습니다.
    -> 아마존라이트세일을 이용해서 lamp(php7)을 설치했습니다.
    -> 파일질라를 이용해서 sftp 접속하여 소스파일을 복사하려는데 어디에 복사해야하는지 모르겠습니다.(일반적으로 htdocs 가 main 루트로 알고 있는데 파일질라에서 나오는 주소는 아래와 같습니다.
    -> /opt/bitnami/apache2/htdocs

    2. .htaccess 를 수정하려는데 11번째줄 은 이미지를 불러올 원본도메인 맞는지요?
    12번째줄은 이미지파일이 저장되어 있을 도메인이구요?

    3. 아래 코드를 수정하라고 하셨는데요
    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

    home의 위치가 1번에서 이야기한 부분인지 아니면 어떤 부분인지 헷갈립니다. 3번 폴더에 1번 소스를 복사했어야 하는 것인지 도통 헷갈립니다.

    죄송합니다. 개발자가 아니라 일반 유저라 이해를 많이 못하고 질문드려서요.

    1. 안녕하세요.
      1. /opt/bitnami/apache2/htdocs 위치에 넣어주세요. 즉 /opt/bitnami/apache2/htdocs/index.php 가 있어야 합니다.
      2. 이미지 접근을 허용할 도메인입니다. 그 외의 도메인에서는 엑박이 뜹니다.
      3. 10 4 * * * /usr/bin/find /opt/bitnami/apache2/htdocs -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
      이렇게 적어주세요.

      1. 와 이렇게 빨리 답변을 주시다니 감사합니다! 소중한 정보 정말 감사합니다!

  35. 안녕하세요.
    현재 이미지서버를 처음 구축해보려 합니다.
    라엘님과 우성짱님 게시글 & 댓글을 정독했는데도 잘 모르겠네요ㅜㅠ
    혹시 이미지서버를 구축해야한다면 이미지서버와 이미지 캐시 서버 둘 중에 어떤걸 구축하는게 더 나은 선택일까요?

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>
*
*