기존 본 블로그는 Jekyll로 구성되어 있었습니다. 별도로 블로그 툴을 개발하지 않아도 되고, markdown을 통해 블로깅이 가능하며, 문법 강조나 버전 관리 등의 여러 혜택을 받을 수 있었기 때문입니다.

하지만 한계가 분명했습니다. 일단 render를 GitHub 서버에서 하기 때문에 편리하긴 하지만 추가적인 기능을 얹을 방법이 없었습니다. 문법 강조도 pygments.rb가 버전이 올라가지 않는 한 대책이 서지 않는 상태였습니다. 무엇보다, Jekyll이 내부적으로 사용하는 템플릿 엔진, Liquid의 기능이 줄곧 불만이었습니다.1

그리고 2015년 12월 22일, Python 웹 프레임워크 Flask의 개발자로 유명한 Armin이 Lektor라는 신제품을 내놓습니다.

Lektor

Lektor는 Python으로 개발된 정적 사이트용 CMS입니다. Jekyll처럼 적당히 파일을 배치하고 빌드하면 정적 웹 사이트가 완성되는 방식입니다.

장점

  • Python이다.
    • 따라서 Pygments등의 Python Third-party와의 궁합이 좋다.
    • 내가 잘 모르는 Ruby보다는 훨씬 익숙하다. 필요하다면 기여를 한다거나 하는 방식으로 문제 대처 가능
  • 템플릿 엔진으로 Jinja2를 사용한다.
    • 보다 많은 표현식이 지원된다.
    • {%- if some %} 과 같은 -를 사용해서 소스상에 불필요한 여백 발생을 없앨 수 있다.
  • Pagination을 여러 곳에 분산 배치 가능
  • 다국어 지원 가능
  • 여러 endpoint로의 배포 시스템
  • 관리자 페이지
  • 보다 효율적인 첨부 파일 관리 시스템
  • webpack 지원

단점

  • 보급이 덜되서 상대적으로 참고할만한 자료가 적다 (시간이 해결해줄 문제)
  • DateTime형 변수가 없다. (2.0에 추가 예정)
  • 문법 강조를 위해 플러그인을 추가로 설치해줘야 하는데, 아직 해당 플러그인이 PyPI에 올라가있지 않다. (시간이 해결해줄 문제)
  • Jekyll이 아니므로 GitHub에서 자동 빌드를 해주지 않는다.
  • 설정이 Jekyll의 _config.yml보단 덜 유연하다.
  • 게시물 포맷이 다르다.

저는 단점이 별로 장애가 되지 않는다고 판단하고 과감히 Jekyll을 버리고 Lektor로 이사를 감행했습니다.

Quickstart

Lektor 공식 사이트의 Quick Start 섹션 내용이 좋습니다. 공식 Screencast 영상을 첨부합니다.

Webpack

Jekyll을 쓸 때는 내부적으로 sass가 돌아가기 때문에 .scss파일만 덩그러니 놔두면 모든 것이 해결되었지만, Lektor에서 예전 소스를 쓰려면 webpack 연동이 필수적이게 되었습니다.

주의할 점은 다음과 같습니다.

  • package.jsonwebpack.config.js 파일은 webpack 디렉토리 내에 생성해야 합니다.
  • 의존성 파일들은 당연히 버전 관리의 대상이 아니므로 webpack/node_modules.gitignore에 추가합시다.
  • 당연하지만, node 버전에 영향을 받습니다. 적절한 버전을 설치해야 합니다.
  • Babel을 쓰실거면 Babel 버전에 주의하세요! Babel 6는 preset 설치가 필요합니다.

Liquid to Lektor + Jinja2

사실 둘의 문법은 흡사합니다. 문법 자체는 그렇게까지 손이 가진 않습니다.2 중요한 것은 기존의 변수명들인데, 변수명 사용법만 몇 가지 다뤄볼까 합니다.

URL

  • Liquid
    <a href="{{ page.url }}">this page</a>
    
  • Lektor
    <a href="{{ this | url }}">this page</a>
    

Lektor는 url 필터를 사용합니다. 외부 링크용 주소가 필요한 경우에는 url(external=True)와 같이 사용하면 됩니다. asset용 링크는 asseturl 필터를 사용하면 매 빌드마다 다른 쿼리문을 추가로 붙여줍니다.

Variables

  • Liquid
    <!doctype html>
    <html>
    <head>
    <title>{{ page.title }}"></title>
    </head>
    <body>
    {{ content }}
    </body>
    </html>
    
  • Lektor
    <!doctype html>
    <html>
    <head>
    <title>{{ this.title }}"></title>
    </head>
    <body>
    {{ this.body }}
    </body>
    </html>
    

Lektor에서는 해당 페이지에 대한 정보는 모두 this 변수에 들어있습니다. this에 어떤 프로퍼티가 있는지는 models/ 디렉토리에서 각 모델별 구조를 보면 확인할 수 있습니다.

Configuration

  • Liquid
    {{ site.author }}
    
  • Lektor
    {{ config['PROJECT'].author }}
    

Lektor는 .ini 형식으로 설정을 처리합니다. 다른 더 편한 방법이 있을 것 같은데 아직은 찾지 못했습니다.

Pagination

  • Liquid
    {% for post in paginator.posts %}
    {% endfor %}
    
  • Lektor
    {% for post in this.pagination.items %}
    {% endfor %}
    

Lektor는 하위 디렉토리가 있는 모든 페이지에 대해서 pagination을 지원합니다.

Deploy

Jekyll은 GitHub에 올리기만 해도 자동 배포를 해주지만 Lektor는 그렇지 못합니다. Command Line으로 배포할 수 있는데, 당연히 CI에서 해당 명령을 실행하면 자동 배포가 됩니다. 저는 Travis-CI를 사용했습니다.

주의할 점은 다음과 같습니다

  • 환경변수 LEKTOR_DEPLOY_PASSWORD값은 비공개로 하셔야 합니다.
  • .travis.yml이 없으면 CI하지 않게 설정하셔야 합니다. 안그러면 master branch가 빌드 할 필요도 없는데 계속 빌드 시도되고, 실패합니다.
  • webpack을 쓰신다면 node 버전에 주의하세요.3 stylesheet가 생성이 안된다던가 할 수 있습니다.
  • Lektor 1.0 버전대에선 아직 지원이 안되는 기능들이 몇 있습니다.4 저는 이 문제를 최신 버전을 설치하는 것으로 우회했습니다.

옮겨오면서 바꾼 사항

Jekyll에서 옮겨오면서 바뀐 사항들이 있습니다.

댓글을 disqus로 변경

기존에 사용하던 komments는 로딩 속도가 빠른 점을 제외하면 다른 장점이 없었습니다. Lektor에서 기본적으로 disqus 플러그인이 있기도 하기에 옮겼습니다.

스킨 개발 목적 변경

Cute Polar Bear는 앞으로 Jekyll이 아닌 Lektor용 스킨으로 개발됩니다.

Atom feed 생성기 변경

Armin이 Lektor 공식 사이트에서 사용하는 AtomFeedSupportPlugin을 사용합니다. 그러는 바람에 RSS의 unique id가 깨져서 RSS를 연동해놓은 곳이 난리가 난 모양입니다. (...)

지금 옮겨도 될까?

게시물 변환을 포함해서 옮기는 데에 하루 정도 소요되었습니다. 난이도가 높진 않지만 찾아볼 자료가 공식 사이트와 소스밖에 없다는 점이 문제인데, 공식 사이트도 꽤 잘 되어 있습니다. 저는 지금 옮겨도 된다고 생각하지만, 조금 더 안정된 상황(문법 강조, pagination 등의 시스템 확립 등)을 원하신다면 2.0까지 기다리시는 것도 나쁘지 않을 것 같습니다.


  1. 사실 이건 Liquid가 기능이 없는 것이라기 보단 제가 즐겨쓰는 Jinja2가 탁월하게 좋아서 생긴 문제 같습니다.

  2. 굳이 문법 차이를 꼽자면 capture 대신 set을 쓰고, unless 등이 없습니다.

  3. Travis-CI는 nvm을 사용합니다.

  4. _discoverable: no 등의 설정이 1.0에 없습니다.