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

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

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

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

 

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

 

31 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. 네 감사합니다. 잘 쓰겠습니다.

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