GitHub Pages를 사용하다보니 다 좋은데 서버가 미국에 있어서 속도가 느린 것이 늘 마음에 걸렸습니다.

사이트 속도를 개선하고자 AWS의 CDN 서비스인 CloudFront를 사용하기로 마음을 먹었습니다. GitHub Pages(http://pyrasis.github.io)를 오리진으로 설정하고 CloudFront 배포(Distribution)를 생성했습니다. 그리고 Route 53으로 최상위 도메인과 www 서브도메인을 CloudFront 배포에 연결했습니다. 네임서버를 변경하고, 잘 되기를 기대했는데 생각지도 못한 문제가 생겼습니다.

Jekyll의 고질적인(?) 문제인 URL 마지막의 슬래쉬(/) 때문에 CloudFront로 캐시한 사이트에 접속해도 오리진으로 리다이렉트 되는 문제였습니다.

Jekyll은 포스팅을 하면 디렉터리를 생성하고 그 안에 index.html을 생성합니다. 그래서 /hello-posting으로 접속해도 /hello-posting/으로 리다이렉션됩니다(301 Moved Permanently).

문제 발생과정은 이렇습니다.

  1. GitHub Pages에 Jekyll로 사이트를 생성.
  2. pyrasis.github.io를 오리진으로 설정하여 CloudFront 배포 생성
  3. Route 53으로 도메인 설정, 네임서버 변경
  4. CloudFront로 캐시된 http://pyrasis.com/hello-posting으로 접속하면 http://pyrasis.github.io/hello-posting/으로 리다이렉션됩니다. http://pyrasis.com/hello-posting/처럼 뒤에 /를 붙여서 바로 접속하면 CloudFront로 접속됩니다.

이렇게 슬래쉬 존재 여부에 따라 pyrasis.github.io로 리다이렉션되면 정말 웃긴 모양이 되어버립니다. CloudFront는 제 역할을 못하게 되죠.

게다가 CNAME 파일에 pyrasis.com이라고 도메인을 설정하면 pyrasis.github.io으로 접속하더라도 pyrasis.com으로 리다이렉션됩니다(301 Moved Permanently). 그래서 pyrasis.com(CloudFront) -> pyrasis.github.io -> pyrasis.com으로 무한 리다이렉션 문제까지 발생합니다.

GitHub Pages의 Jekyll 설정을 아무리 찾아봐도 포스팅 URL에서 /를 제거하는 방법은 없었습니다. 애초에 파일이 아니라 디렉터리라서 웹 서버 레벨에서 제어를 해줘야하는데 GitHub Pages는 웹 서버 설정을 못바꿉니다.

고심 끝에 CloudFront와 Heroku를 연결하는 것으로 해결했습니다.

  1. Heroku에 Jekyll, Rack Jekyll, Unicorn을 설치
    1. https://github.com/bry4n/rack-jekyll
    2. http://unicorn.bogomips.org/
  2. Unicorn으로 Jekyll 정적 HTML 배포
  3. Heroku를 오리진으로 설정하여 CloudFront 배포 생성
  4. Route 53으로 도메인 설정

여기서 모든 문제의 원인을 해결해준 것은 rack-jekyll이었습니다. Jekyll은 웹 서버를 Ruby의 기본 웹 서버인 WEBrick을 사용하고 있습니다. WEBrick이 디렉터리를 301 Moved Permanently로 처리해서 이런 문제가 생긴 것이죠.

rack-jekyll은 디렉터리로된 경로라 하더라도 index.html이 있으면 디렉터리 경로를 파일로 처리해줍니다(Rack은 웹 서버 미들웨어입니다). 즉, /hello-posting으로 접속하면 /hello-posting/으로 리다이렉션하지 않고 hello-posting 이름으로된 HTML 파일을 출력합니다.

/hello-posting으로 접속하든, /hello-posting/, /hello-posting/index.html로 접속하든 그대로 처리합니다. 이렇게 해주니 외부에서 슬래쉬를 붙여서 오든 말든 모두 호환이 됩니다. 자연스럽게 CloudFront와 연동해도 리다이렉션 되지 않고 /hello-posting이 그대로 캐싱됩니다.

처음에는 Heroku로 옮기되 WEBrick을 수정해서 사용하려고 소스를 한참 들여다봤는데 시간이 많이 절약되었습니다.

참고
Heroku에서 Jekyll를 사용할 때 _config.yml에서 vendor는 꼭 제외시켜주어야 합니다.
exclude: [ "vendor", "Gemfile", "Gemfile.lock", "Procfile" ]

저작권 안내

이 웹사이트에 게시된 모든 글의 무단 복제 및 도용을 금지합니다.
  • 블로그, 게시판 등에 퍼가는 것을 금지합니다.
  • 비공개 포스트에 퍼가는 것을 금지합니다.
  • 글 내용, 그림을 발췌 및 요약하는 것을 금지합니다.
  • 링크 및 SNS 공유는 허용합니다.

Published

27 June 2014