들어가며
웹 문서를 작성할 일은 많다. 그런데 특별한 기능이 있는 문서를 원하는 것이 아닌, 블로그와 같이 일반적인 ‘글’을 작성하고 싶을 때의 경우를 생각해 보자. 크게 다음과 같은 방법들이 있을 것이다.
- 포털이 제공하는 서비스(Ex. 네이버 블로그, 티스토리 등) 사용
- 설치형 CMS(Ex. WordPress 등) 사용
- GitHub Pages 등을 이용한 Jekyll 사용
포털 서비스의 경우 글 백업과 이전 등이 상당히 어려울 수 있으므로 쳐다보지조차 않았다. 설치형 CMS를 쓴다고 했을 때, 언젠가 HTML 기술이 필요해진다면 소스 편집 기능을 활용할 수도 있을 것이다. 그런데 양식이 바뀌는 등의 큰 변화가 있으면 처리하기 어려운 부분이 존재할 수 있다.
Jekyll을 사용하면 Markdown 등의 문법을 활용하여 정적 페이지를 만들 수 있다. GitHub Pages는 gh-pages branch 등을 통해 사용할 수 있다. 그런데 마냥 쓰자니 테마 등 여러 가지로 고민할 것들이 또 있다.
이에 바닥부터 블로그 등의 글을 위한 프레임워크라고 부르기도 뭐한 간단한 것을 만들어 보기로 했고 PHP의 Parsedown을 이용하여 만들었다. 물론 그 과정에서 Parsedown에 기여도 하게 되었다.
한편 작성된 문서에 접근하기 쉽게 만드는 것도 필요하다. 모바일에서 구글 검색을 할 때 ⚡ 표시가 붙은 항목을 본 적이 있을 것이다. 그리고 그것은 클릭하면 다른 항목보다 훨씬 빨리 로드된다. 이 기능을 지원하는 것이 목적이다.
Markdown
Markdown은 간단한 몇 가지 문법을 지원하는 문서 형식이다. 공식적인 표준은 없지만, 흔히 Simple Markdown, GFM(GitHub Flavored Markdown), Extra Markdown 등으로 분류한다. 편집기에 따라서 아래와 같이 수식 등을 추가로 지원하기도 한다.
이제 Markdown을 HTML로 변환하는 방법을 소개한다.
Showdown.js
JavaScript단에서 동작하는 라이브러리로 클라이언트와 node.js 서버 모두에서 사용할 수 있다. 처음에는 이것을 사용하여 XHR로 Markdown 파일을 받아 변환하는 방식을 썼는데, 느리고 검색엔진에도 잡히지 않는 등 큰 문제점들이 있었다.
Strapdown.js
<xmp> 태그 안의 내용을 자동으로 변환해주는 라이브러리이다. 위와 달리 검색엔진에 잡히겠지만, 정적 페이지만 사용하려면 관련 내용을 매번 적어줘야 하므로 적용이 곤란했고, 동적 페이지 생성으로 넘어가면 어차피 더 좋은 것들이 있어서 안 쓰게 되었다.
Parsedown
동적 페이지 생성을 하기로 생각한 후 찾은 라이브러리이다. PHP 라이브러리로, 자체 Markdown 관련 기능보다 더 빠르고 오픈 소스라서 커스터마이징이 가능하다. 필자도 표의 셀 병합을 지원하는 버전을 만들고 배포한 바 있다.
AMP(Accelerated Mobile Pages)
AMP는 구글이 정해 놓은 웹페이지를 빠르게 로드하기 위한 표준 정도라고 보면 되겠다. 추가 리소스 다운로드 없이도 레이아웃을 미리 결정할 수 있고, 구글이 콘텐츠를 캐싱해준다는 점 등이 있다. 이 글은 AMP를 설명하는 것보다 이를 어떻게 적용할지에 대해 다루기에 자세한 설명은 생략한다.
기능
<link>
로 AMP가 아닌 페이지와 AMP 페이지 사이를 연결한다.
특정 규칙을 사용해 자동으로 연결하고 싶은 경우 아래와 같이 현재 요청 중인 페이지의 URL을 알아낼 수 있다.
$url=((@$_SERVER["HTTPS"]==="on")?"https":"http")."://".$_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"];
연결에 성공하면 다음과 같이 확인할 수 있다.
<img>
, <video>
, <audio>
등을 사용할 수 없다.
대신 <amp-img>
등을 사용할 수 있고 이는 필요할 때 로드된다. 이런 요소들은 문서의 레이아웃을 미리 결정하기 위해 width와 height가 반드시 주어져 있어야 한다. 창 크기에 따른 레이아웃 모드는 다음과 같다. 이미지를 위한 가장 무난한 모드는 intrinsic으로 보인다.
구현은 PHP Simple HTML DOM Parser를 사용해 다음과 같이 할 수 있다.
foreach($dom->find("img") as $img)
{
$img->tag="amp-img";
$size=getimagesize(realpath(dirname($_GET["md"]).DIRECTORY_SEPARATOR.$img->src));
if(!$img->hasAttribute("width"))$img->setAttribute("width",$size[0]);
if(!$img->hasAttribute("height"))$img->setAttribute("height",$size[1]);
$img->setAttribute("layout","intrinsic");
}
유효성 검사
제대로 된 AMP 문서가 맞는지 확인하기 위해서는 유효성 검사가 필요하다. 여러 방법으로 할 수 있다.
- 라이브러리 내장
- 브라우저 확장 프로그램 : http://chrome.google.com/webstore/detail/amp-validator/nmoffdblmcmgeicmolmhobpoocbbmknc
유효성 검사를 통과한 모습이다.
CSS
CSS는 외부 링크는 안 되며 하나의 <style amp-custom>
안에 모든 내용이 포함되어 있어야 한다. 대부분 속성이 지원되지만 다른 곳에서 가져온 경우 !important
키워드는 사용할 수 없으므로 이를 제거해 주어야 한다.
외부 링크의 내용을 직접 포함해서 주기 위해 PHP에서는 다음 두 가지의 방법을 사용할 수 있다. 먼저 첫 번째는 PHP 설정의 allow_url_fopen이 true인 경우 사용할 수 있다. Remote fread()
를 사용한다.
$fp=fopen("https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/2.10.0/github-markdown.min.css","r");
$css=str_replace("!important","",stream_get_contents($fp));
fclose($fp);
해당 설정을 조정할 수 없는 경우에는 cURL 확장이 사용 가능하다면 이를 활용할 수도 있다.
$curl=curl_init();
curl_setopt($curl,CURLOPT_URL,"cdnjs.cloudflare.com/ajax/libs/github-markdown-css/2.10.0/github-markdown.min.css");
curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);
$css=str_replace("!important","",curl_exec($curl));
curl_close($curl);
이렇게 $css
에 외부 CSS 내용을 받아온 후 아래와 같이 전송해주면 된다.
<style amp-custom><?php echo($css); ?></style>