블로그 개편: 커스텀 정적사이트생성기 개발기

약 3년 전 텀블러에서 Hugo를 이용한 정적생성기로 블로그를 이전하였었는데 이번에 커스텀 정적생성기를 개발하며 Hugo를 떠났다.

텀블러에서 Hugo로 이전했던 주요 이유는 유연한 사이트 관리를 위해서였다. 사이트 전체 코드를 내가 원하는 에디터를 통해 Git으로 관리할 수 있다는 점이 마음에 들었다. 하지만 시간이 지나며 Hugo에도 차츰 불편함과 답답함을 느끼기 시작했다.

정적사이트생성기란

정적사이트생성기(Static Site Generator)는 말 그대로 정적인 웹사이트를 생성해주는 툴인데 일반적으로 마크다운 파일을 읽어 HTML을 생성하는 기능을 가진다. 워드프레스와 같은 툴은 서버와 데이터베이스를 이용해 사용자가 페이지를 방문할 때마다 동적으로 웹페이지를 생성한다면 정적생성기는 미리 HTML을 생성해 서버에서는 해당 파일을 제공하기만 하면 되도록 한다.

정적사이트생툴을 이용해 웹사이트를 운용하면 서버나 데이터베이스를 관리해야하는 부담이 적어지고 이미 만들어져 있는 페이지를 제공만 하면 되니 빠른 웹페이지 로딩이 가능하다는 장점이 있다.

유명한 정적사이트 생성기로는 루비로 개발된 Jekyll이 있다. Hugo는 Go로 개발되어 Jekyll 보다 빠르다는 장점이 있고 패키지 의존성 문제에서도 자유롭다. Jekyll이 먼저 개발되어 인기가 많았는데 깃헙에서 받은 Star 기준으로 보았을 때 지금은 Hugo가 더욱 사랑받고 있다.

Hugo의 문제

Hugo를 이용해 블로그의 기능이나 디자인 수정 하기 위해서는 Hugo가 어떻게 동작하는지 이해해야하고 제공하는 API나 템플릿 문법을 익혀야한다. 블로그 수정이 자주 있는 일이 아니다보니 한번 이해를 했던 것도 다시 봐야하고 작은 문제를 해결하는데도 많은 시간을 들여야하는 상황이 반복되었다. 실제 내가 가지고 있는 문제의 Complexity 때문이 아닌 Accidental complexity로 인해 시간이 낭비되는 경우가 지속적으로 발생하는 것이다.

이전 버전과 호환되지 않는 Hugo의 새 버전도 문제였다. 가끔 Hugo가 업그레이드 되며 기존에 잘 동작하는 것들에서 문제가 생기는 경우도 생겼으며 그것을 고치기 위해 문서와 릴리스 노트를 읽으며 애를 써야했던 경우도 있었다. 예를 들어 작년 업데이트 후 첫 화면과 RSS가 깨지는 문제가 발생하여 내가 사용하는 어떤 부분이 새 버전과 호환이 되지 않는지를 한참 찾아봐야했다. 나는 쓰지도 않는 많은 기능들이 있고 그것들이 업그레이드 되면서 정작 내가 잘 사용하던 것들은 망가지는 일이 발생하는 것이다.

이와 같은 상황이 발생할 때마다 이것이 나의 시간을 의미있게 사용하는 방식인가에 대한 의문이 들었다. 커스텀 툴을 만들 경우 새로운 기능이 필요할 때마다 그것을 구현하는데 시간이 들지만 그것은 내가 완전히 이해하는 코드이며 완전한 컨트롤을 가질 수 있다. 다른 이가 만든 문서를 읽고 이해하는 것보다는 내가 직접 개발을 하는 것이 나의 시간을 더욱 의미있게 쓰는 것이라는 생각이 들었다.

커스텀 정적사이트생성기

텀블러에서 Hugo로 이전하며 블로그에 대한 자유도가 한 단계 업그레이드 되었는데 이번에 생성기까지 나의 것이 되면서 다시 한번 자유도가 높아졌다.

다양한 기능을 원하지 않는다면 쉽게 툴을 만들 수도 있다. 예를 들이 Ben이라는 블로거의 경우 Bash 스크립트를 이용하여 주석을 포함하여 79줄의 코드로 툴을 만들었다.

정적생성기가 기본적으로 하는 일은 마크다운 파일을 읽어 HTML을 생성해주는 것이므로 기본 기능에 충실하게 만든다면 Bash 스크립트도 나쁘진 않다. 하지만 지금 블로그와 같이 URL에 블로그의 날짜를 넣는다거나 블로그 글이 아닌 About 페이지와 같은 것을 넣는다거나 RSS를 넣는 등 약간의 고급기능이라도 넣으려면 Bash로는 어려워진다.

개발에 꽤 많은 시간이 걸릴 것이라고 예상했기 때문에 과연 이것이 나의 시간을 투자하는 좋은 방식인가를 고민하였다. 툴을 만드는 것으로 결정을 내리는 데에는 두 가지 주요 이유가 있었는데 첫째 앞으로 블로그 운영을 수 십년은 더 하게 될 것인데 장기적으로 충분한 투자 효과가 있을 것이라는 것이엇다. 한동안 글을 못쓰고 있었지만 다시 써볼 생각이고 영어블로그도 시작할 예정인데 같은 도메인을 통해 두 개의 블로그를 운영하는 것은 커스텀 툴이 아니고서는 어려울 것이라는 생각도 있었다. 내가 가진 불편을 해소하기 위해 만든 툴들이 있는데 만드는데 시간이 걸리기는 헀지만 장기적으로 충분한 효용을 준 경우가 많았기 때문에 이 툴도 그렇게 될 것이라는 믿음이 있었다.

두 번째로는 Clojure를 학습하기 위해서였다. 개인적으로 Clojure를 공부하고 있는데 업무에서는 사용을 하지 않으니 실용적으로는 쓸 수 있는 기회가 없었고 그래서 이 프로젝트를 통해 경험을 더 쌓을 수 있다고 생각했다. 결론적으로 보면 연습용으로 만들어보기 좋은 프로젝트였다.

Lisp과 Clojure

Lisp은 많은 사람들이 사용하는 언어는 아니지만 그 언어를 사용하는 개발자들에게는 가장 인기있는 언어 중 하나이다. 약 7년 전 쯤 Lisp을 사랑하는 개발자이자 벤처기업투자자인 폴그레이엄의 해커와 화가를 읽은 후부터 Lisp을 공부해보고 싶었는데 그 외에도 이것저것 공부할 것이 많은데다가 해외취업 준비까지 하다보니 상황이 여의치 않았다. 몇 번 시도를 하지만 결국 우선순위에 밀려 잊혀지곤 했었다.

올해 다시 Lisp 공부를 시도하며 Lisp 계열 언어인 Scheme에 관한 책 The Little Schemer를 읽었다. 흥미로운 책이었지만 Scheme을 사용해보며 언어와 관련된 빈약한 생태계에 실망을 하였다. 인터넷에서 찾을 수 있는 관련 자료들이 오래되었거나 제대로 없는 경우가 많았다. 예를 들어 제대로 된 테스트 프레임워크를 찾는 것도 불가능했다.

이후 Racket이 생태계가 잘 갖추어진 Scheme이라는 정보를 얻고 Realm of Racket이라는 책을 읽으며 Racket을 공부하였다. 실제로 문서도 잘 되어 있고 테스트 프레임워크 등 다양한 라이브러리가 존재했다.

하지만 Racket도 완전히 만족스럽지는 않았다. 먼저 Racket 개발을 위해서는 DrRacket이라는 툴을 써야한다는 것이 불편했다. 둘째로 여전히 충분치 않은 라이브러리였다. 예를 들어 Processing이라는 비주얼 아트 라이브러리를 사용하고 싶었는데 Racket으로는 쉽게 사용할 수 있는 방법이 없었다.

새로운 언어를 배울 때 기본적으로 보는 것들은 다음과 같다.

이 모든 것들이 특정 개발언어를 둘러싼 좋은 생태계가 구성되어 있을 때에 제공되는 것이다.

Clojure는 Java 플랫폼에서 구동되는 Lisp 계열의 언어이다. 해커뉴스의 글을 읽다보면 가끔 Clojure에 대한 글이 올라오는데 리뷰나 댓글들이 긍정적이어서 그런 글을 볼때마다 시간나면 살펴봐야겠다는 생각을 가지고 있었다.

Clojure도 많은 사람들에게 인기가 많은 언어는 아니지만 내가 찾는 것에 대해서는 항상 라이브러리가 있었다. 앞서 말한 Processing은 물론이고 정적생성기를 만드는데 필요할만한 템플리팅, RSS 생성, 마크다운 렌더러 등 풍부한 라이브러리가 있었다. Stasis라는 정적생성기 라이브러리도 있는데 막상 쓰려고 하니 나의 요구사항과는 맞지 않는 부분이 있었다. 나의 블로그는 Hugo에서 제공하는 기능에 맞추어져 있었고 기존의 URL이나 마크다운 형식을 유지하기 위해서는 Stasis를 사용할 수 없었다. 소프트웨어 재사용은 레고블럭보다는 신장이식에 가깝다는 말이 다시 와닿았다. 오픈소스 프로젝트를 이용해 개발을 하려다보면 종종 발생하는 일인데 막상 제공되는 기능 이외의 것을 하려다보면 코드 분석과 재개발에 많은 에너지를 써야하는 일이 생기고 차라리 처음부터 다시 개발하는게 낫지 않을까하는 생각이 들때가 있다. 그렇다고 처음부터 개발하려고하면 다양한 Edge case 처리나 기능 구현에 많은 시간이 들기도 하니 여러가지를 잘 고려해보아야한다.

Stasis를 그대로 가져다 쓰지는 못했지만 소스코드는 Clojure 초보자로서 어려워하던 부분에 대한 힌트를 많이 제공해주었다. Clojure 개발을 하며 느낀 훌륭한 점 하나는 코드가 간결하여 많은 라이브러리들이 하나의 파일로 제공된다는 점이다. Stasis도 핵심코드는 257라인의 한개의 파일에 제공되는데 파일이 하나 밖에 없으니 코드 분석하기에 부담이 없었다.

의외로 시간이 들었던 부분은 날짜 처리였다. Clojure에서 날짜 처리를 하려면 Java 라이브러리를 써야하는데 그 사용법이 꽤 까다롭다. 예전에 Java 개발을 하며 적지 않게 써봤음에도 불구하고 Clojure에서 사용하기 위해 다시 찬찬히 들여다보아야했다. 강력한 기능을 제공하는 대신 간단한 작업을 하는데에도 다양한 API를 익혀야해서 많은 시간이 걸리는 문제가 있는 것이다.

프론트엔드

블로그를 개편하며 디자인도 새롭게 바꾸어볼까 고민을 하였는데 지금 꼭 해야하는 부분을 먼저 처리하자는 생각에 기존의 디자인을 최대한 유지하는 쪽으로 하였다.

Hugo로 블로그를 만들었을 때는 기존에 있던 테마를 손봐서 사용했었다. 이번에는 Classless CSS 프레임워크 중 하나인 Sakura를 기본 CSS로 하여 기존 디자인과 비슷하게 만들었다.

Hugo를 쓸 때에는 테마에서 제공되는 레이아웃이나 CSS와 커스텀 코드가 뒤섞여 관리가 쉽지 않았는데 최소한의 기본 코드를 사용하니 그 문제가 해결되었다.

기존 블로그에서는 LESS를 이용해서 커스텀 CSS를 생성했었지만 최대한 단순하게 만들기 위해 이것도 제외하였다.

도메인과 Netlify 호스팅 그리고 배포

이전 블로그 글에서 블로그를 이전하며 자체 도메인은 없애고 깃헙 페이지를 사용하기 시작했다는 이야기를 했었다.

시간이 지나니 나만의 도메인이 없는 것이 다시 아쉬웠다. 독일에서 일을하며 Sang을 이름으로 사용하기 시작했는데 I am Sam을 패러디한 iamsang으로 도메인을 하면 좋겠다는 생각이 들어 도메인을 다시 구매하였다 (아내에게 이야기 했더니 "거기서 Sam은 좀 모자란 사람인데?"라는 반응을 보였다.)

깃헙 페이지를 이용하니 공개된 장소에 모든 코드와 완성되지 않은 글을 공유해야한다는 점이 거슬렸다. 그래서 Private Repository를 무료로 제공하는 BitBucket으로 옮기고 Netlify에 연동해 블로그를 운용하기 시작하였다.

지금은 깃헙에서도 Private Repository를 무료로 제공하기 시작하여서 이전에 가끔이라도 쓰던 깃랩이나 BitBucket을 사용할 일이 전혀 없어졌다.

Netlify는 정적 페이지를 호스팅하기 좋은 서비스인데 기본적으로는 무료이면서 훌륭한 기능과 서비스를 제공한다. 깃헙과 쉽게 연동되고 도메인 연결도 간단하며 HTTPS (SSL) 세팅도 원클릭으로 가능하다. 깃헙에 코드가 푸시될 때마다 배포되게 할 수 있으며 이메일로 노티피케이션을 받을 수도 있다.

배포과정을 그려보면 다음과 같다.

GitHub과 Netlify를 이용한 블로그 배포

요구사항 쳐내기

사이드 프로젝트는 완료하기 어렵기로 유명하다. 많은 경우 재미있는 부분이 지나고 나면 흥미와 열정을 잃고 버려지기 마련이다. 그것을 극복하기 위해 요구사항을 줄이는데에 신경을 많이 썼다. 지금 당장 첫번째 버전을 출시하는데에 필요하지 않은 것은 다 나중에 할일 목록으로 옮겼다. 예를 들어 블로그 이전하며 각 글 하단에 있던 "이전 글" 섹션이 없어졌다. 그리고 정정사이트생성기의 기본 기능 중 하나인 로컬 서버 기능도 제외하였다. 이것은 프론트엔드 작업을 할때 필요한 기능인데 수정한 것을 바로 확인할 수 있기 위해 꽤 필수적인 기능이다. 아직 익숙하지 않은 Clojure로 서버를 넣는 것에 부담이 있어 Watcher를 이용해 변경이 있을 때마다 복사하는 방식을 이용했다.

영어블로그를 만들고 메인페이지에서 선택할 수 있게 하는 것도 초기 계획의 일부였는데 일단 새 툴을 이용해 이전 블로그와 같은 형태로 운용하는 것으로 목표로 변경하였다.

프로젝트 개발을 하다보면 "이런 것도 넣으면 좋지 않을까?"하는 생각이 끝없이 들고 종종 그것은 일정의 차질로 이어진다. 일정을 맞추기 위해서 요구사항을 쳐내는 것은 필수이며 꼭 필요해보였던 기능도 시간이 지나서 보면 전혀 필요 없었던 것으로 나타나기도 한다.

스택오버플로의 창업자 조엘의 블로그 글 Painless Software Schedules에는 이런 일화가 나온다. 마이크로소프트 엑셀의 프로젝트 메니저였던 조엘은 Excel 5 개발일정을 맞추기 위해 기능들을 추려내야했다. 모든 기능들이 꼭 필요해 보였지만 당시 선택의 여지가 없었기 때문에 다음 버전에 넣자는 기약을 하고 덜 중요해 보이는 기능들을 제외하였다고 한다. 이후 Excel 6 개발을 위해 동료와 이전 버전에서 추려내었던 기능 목록을 다시 살펴보며 충격을 받았다고 한다. 단 하나의 기능도 필요해 보이지 않았기 때문이다.

마무리

해커뉴스 글에 있는 한 댓글에서 누군가 정적사이트생성기를 직접 만들어 쓴다는 이야기를 읽고 그건 조금 과하다 생각했었는데 어느 순간 내가 그것을 하고 있었다. 그 댓글을 보지 않았더라도 이것을 직접 만들어 쓸 생각을 하였을까.

자신이 사용할 소프트웨어를 직접 만들어 쓸 수 있는 것은 멋진 일이다.

github stackoverflow twitter linkedin email rss