블로그 다이어그램 렌더러를 Pele로 바꾸기.
시발점
이제 막 블로그를 꾸미고 있다. Firefly 템플릿을 적용하고 설정과 코드를 하나씩 살펴보다가, 글에 Mermaid 다이어그램을 넣을 수 있다는 걸 발견했다.
그러자 전에 옵시디언 쪽에서 봤던 Pele가 떠올랐다.
아직 글도 별로 없는데 렌더러부터 바꿀 필요가 있나 싶었지만, 블로그를 손보는 김에 붙여보고 싶었다.
처음에는 Mermaid.js를 교체하면 될 줄 알았다. 그런데 코드를 열어보니 이 블로그 템플릿은 이미 Merman으로 빌드할 때 SVG를 만들고 있었다.
이미 충분히 빠르겠지만, 그냥 생각한 거 바꾸기로 했다.
Pele는 무엇인가
Pele는 Mermaid 문법을 읽어 SVG를 만드는 렌더러다.
이름은 화산과 불의 여신 펠레에서 따왔다고 한다. 맨 처음 봤을 때, 화산 같기도 사람의 옆모습 같기도 했던 아이콘이 정말 이중적 의미를 담고 있었을 줄은 몰랐다.
아이콘 이쁘지 않나. 되게 잘 만든 아이콘 같은데.
공식 홈페이지는 Pele의 장점을 다음과 같이 소개한다. 아래 수치는 Pele에서 주장하는 Pele와 Mermaid.js의 공식 비교다.
| 항목 | Pele | Mermaid.js |
|---|---|---|
| gzip 압축 번들 크기 | 230 kB | 1.6 MB |
| 렌더링 시간 | 0.05–0.3 ms | 6–82 ms |
| 직접 의존성 수 | 0 | 23 |
| 테마 설정 | CSS 변수 | 테마 설정 객체 |
공식 소개의 표현으로는 최대 500배 빠르다고 한다.
뭐 자기네들 기술이 제일 좋다고 하겠으니 저렇게 극단적인 수치가 아닐 수도 있지만, 빠른 건 확실하겠지.
Astro에 Pele 연결하기
블로그 템플릿에서 제공하는 기존 구조를 유지하면서 다이어그램을 만드는 부분만 바꿨다.
적용한 Pele 버전은 1.8.0이다.
먼저 Pele 자체의 사용법은 짧다. render()에 Mermaid 문법을 전달하면 SVG 문자열을 받을 수 있다. 다음 코드는 Pele가 설치된 프로젝트에서 .mjs 파일로 실행할 수 있다.
import { render } from "pele";
const source = `flowchart LR A[가] --> B[나] --> C[다]`;
const { svg } = render(source, { idPrefix: "example-0", fontFamily: "system-ui, sans-serif", autoDirection: false,});
console.log(svg);구조
정적 블로그를 직접 만들어 본 사람들은 알겠지만, remark-*, rehype-*라는 라이브러리를 매우 많이 볼 수 있다.
- remark:
- rehype:
그래서 이 블로그에서는 작성할 코드는 생각보다 적었다.
remark: 다이어그램 코드 블록 찾기
src/plugins/remark-pele.js는 언어가 mermaid 코드 블록을 골라낸다.
일반 코드 하이라이터로 넘어가지 않도록 노드 타입을 바꾸고, 다음 단계에서 읽을 원본을 남긴다.
import { visit } from "unist-util-visit";
export function remarkPele() { return (tree) => { visit(tree, "code", (node) => { if (node.lang === "mermaid") { const code = node.value; node.type = "pele"; node.data = { hName: "div", hProperties: { className: ["pele-source"], "data-pele-code": code, }, hChildren: [{ type: "text", value: code }], }; node.value = undefined; } }); };}rehype: 원본을 SVG로 바꾸기
src/plugins/rehype-pele.mjs에서는 pele-source 요소를 찾아 원본을 render()에 전달한다. 아래는 실제 플러그인의 렌더링 부분을 발췌한 코드다.
remark에서 변환된 html 구조를 토대로 pele의 렌더링을 적용시키면 된다.
const { svg } = render(source, { idPrefix: `pele-${diagramIndex++}`, ...options,});
node.children = [ h( "div", { class: `${DIAGRAM_WRAPPER} ${PELE_WRAPPER}` }, fromHtml(svg, { fragment: true }).children, ),];마지막으로 astro.config.mjs에서 remarkPele와 [rehypePele, peleConfig]를 기존 플러그인 목록에 등록했다.
가장 마음에 든 변화
바꾸고 보니 의미없는 변경은 아니었다.
무려 css로 색상을 관리할 수 있게 됐다.
…
사실 theme 기능을 merman에서도 지원은 하고 있었다. 그게 조금 귀찮게 생겼을 뿐이지.
아무튼 좋은게 좋은 거니까.
배경과 노드 색상은 블로그가 이미 쓰는 변수에 연결해서 통일성을 유지하기 쉬워졌다.
꼭 바꿔야 했을까
사실 꼭 필요한 작업은 아니었다. 이미 Merman으로 빌드할 때 SVG를 만들고 있었고, 블로그에 성능 문제를 느낄 만큼 다이어그램이 많은 것도 아니었다.
속도 때문에 바꿔야 할 이유도 없었다.
이제 블로그 꾸미는 것도, 이쯤 손봤으니 여기에 넣을 글을 써야겠다.
이래놓고 또 꾸미러 갈 수도 있겠지만.
후원 및 공유
글이 도움이 되셨다면 후원하거나 공유해 주세요.

