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

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

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

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

 

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

 

구축 방법

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

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

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

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

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

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

 

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

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

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

 

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

캐시된 파일은 5일동안 사용되지 않으면 삭제되게 정함.

 

이미지 캐시 도메인 정하기

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

 

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

 

웹서버 구축

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

한번에 끝내는 우분투 웹서버! (MySQL 은 설치할 필요 없음) https://blog.lael.be/post/73

 

이미지 캐시 사이트 설치

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

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

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

 

- .htaccess 파일

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

- invalid_referer.png 파일

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

- index.php 파일

$target_host 부분을 적절하게 수정하세요.

 

- NGINX 사용자의 경우 .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 링크가 있다면
Apache 예제 : https://img.lael.be/wp-content/uploads/2018/10/s2.png변경합니다.
(NGINX 예제 : https://img2.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 라운드로빈을 통해 다수의 캐시 서버를 두면, 부하가 더욱 분산됩니다. 하지만 하나만 두어도 충분한 기대 효과가 나옵니다.

 

20 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

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

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