안녕하세요, Andrea입니다.
저는 Rust에 익숙하지 않은 초보자인데, 이 언어와 접촉할 수 있는 아주 실용적인 방법은 무언가를 직접 만들어 보는 것이라고 생각했습니다. 오랫동안 저만의 .md에서 .html 컴파일러를 작성해 보고 싶었습니다. 그래서 여기 이렇게 제 마이크로 블로그와 프로젝트가 현실화되었습니다. 심지어 이것을 쓰기 전에 저는 Hugo를 사용하고 있었습니다.
정말 좋았지만, 아시다시피 때로는 너무 복잡합니다. 저는 테마를 고르는 데 평생을 바치거나 하는 것 말고 아주 간단한 것이 필요했습니다.
혹은 SWE로서 제가 직접 만들 수 있을 거라고 생각했는지도 모르겠습니다. 그리고 제 별로 여유롭지 않은 시간으로 12~13시간이 지난 후에 마침내 무언가를 완성하게 되었습니다.
이것은 매우 기본적인 버전이며, GenAI 도구를 사용하지 않고 작성했고 가능한 한 많은 문서화를 포함했습니다. 현재는 아주 기초적인 .md 문법만 구현했으며, 나중에 확장할 예정입니다.
얼마 전에 드래곤 북(dragon book)을 읽었기 때문에 컴파일러를 작성하는 것이 완전히 새로운 일은 아니었지만, 제가 내린 몇 가지 선택들이 실제 .md에서 .html 컴파일러들, 심지어 Hugo 자체와도 상당히 유사하다는 것을 보는 것은 재미있었습니다.
컴파일 과정은 다음 단계를 따릅니다:
post/ 디렉터리 스캔
- 각 파일을 순회하며 블록 요소(block elements)를 검색
- 각 블록을 순회하며 인라인 요소(inline elements)를 검색
- 그 결과로 중간 표현(intermediate representation)이 나옵니다 (AST를 구축하는 것은 항상 멋진 일입니다):
[
Heading {
level: H1,
...
- 템플릿을 사용하여
.html로 출력하기 (매우 기본적인 수준)
파일로 출력이 된 것은 Block에 대해 Display를 재정의하여 Inline과 동일하게 만들었기 때문에 특히 간단했습니다.
여기에 생성된 index와 몇 가지 게시물의 데모가 있습니다.
demo
이제 좀 더 기술적인 내용으로 들어가 보겠습니다:
모든 게시물은 ---로 구분되는 YAML 프론트 매터(front matter) 블록으로 시작합니다:
---
title: Building a markdown compiler
date: 2026-07-27
...
title과 date는 필수이며, 나머지는 선택 사항입니다. date는 YYYY-MM-DD 형식이며 인덱스의 순서를 결정합니다. draft: true로 설정하면 해당 게시물 전체가 건너뜁니다. 현재 CommonMark 커버리지는 다음과 같습니다:
index.html
은 전체 게시물 목록이며, 페이지네이션이나 클라이언트 측 라우터가 없습니다. 필터링은 페이지 상단의 검색창을 통해 할 수 있으며 (검색창 단축키는 /이고, esc를 눌러 검색 텍스트를 삭제할 수 있습니다), 또는 개별 포스트의 태그나 여전히 페이지 상단에서 가능합니다.
vim과 유사한 이동 방식으로 게시물 내와 간에 탐색할 수 있습니다 (이것은 분위기(vibe) 코딩이며 테마에 따라 달라지므로, 제가 추적하지는 않겠습니다. 시도해 보세요, 꽤 멋지고 텍스트를 잘라낼 수도 있습니다 :) ). 아직 초기 단계이므로 .md 문법을 다룰 때 주의하세요. 예를 들어, 모든 블록 요소는 빈 줄로 분리해야 하며, 현재 포괄적인 테스트가 없습니다. 이 도구가 저 외의 누구에게도 유용할 것이라고 생각하지 않지만, 만드는 것은 재미있었고 분명히 확장될 것입니다. 코드는 이 리포에서 찾을 수 있습니다.