본문으로 건너뛰기

시리즈

Obsidian 기술블로그 파이프라인

sync-posts는 Obsidian Markdown을 어떻게 Docusaurus 글로 바꾸는가

· 약 2분
dev-burnern
Developer

핵심 요약

scripts/sync-posts.mjs는 Obsidian에서 작성한 Markdown을 Docusaurus가 안정적으로 빌드할 수 있는 블로그 글로 정규화한다. 핵심은 글쓴이가 매번 메타데이터와 링크 문법을 손으로 맞추지 않아도 되도록, 파일 경로와 본문을 기준으로 필요한 정보를 자동 보정하는 것이다.

이 스크립트는 글 작성 도구와 배포 도구 사이의 번역 계층이다. Obsidian의 빠른 기록 경험은 유지하고, 공개 블로그에는 Docusaurus가 이해할 수 있는 구조만 남긴다.

문제 상황

Obsidian은 개발 기록을 빠르게 남기기 좋지만, 그 문법이 정적 블로그에 그대로 맞지는 않는다. [[문서]] 형태의 wiki link는 Docusaurus 라우트가 아니고, > [!note] 같은 callout은 Docusaurus admonition과 다르다.

frontmatter도 반복 비용이 있다. 글이 늘어나면 category, tags, slug, authors, draft를 매번 같은 기준으로 채워야 한다. 이 작업을 사람이 직접 하면 누락과 불일치가 생기기 쉽다.

구현 방식

sync 단계는 먼저 posts/ 아래의 Markdown과 MDX 파일을 순회한다. Excalidraw, 내부 문서, 숨김 폴더처럼 공개 블로그에 올리지 않을 파일은 제외한다.

각 글은 gray-matter로 frontmatter와 본문을 분리한 뒤 정규화한다. title이 없으면 첫 번째 H1에서 가져오고, date가 없으면 안전한 기본값을 넣는다. categorytags는 파일 경로에서 생성하며, slug는 직접 지정하지 않았을 때 경로 기반으로 만든다.

본문 변환은 코드 블록을 먼저 보호한 뒤 수행한다. 코드 블록 안의 [[...]]나 callout 예제가 실제 링크로 바뀌면 안 되기 때문이다. 이후 Obsidian callout을 Docusaurus admonition으로 바꾸고, wiki link는 실제 대상 파일을 찾아 블로그 permalink로 변환한다.

마지막으로 공개 글만 모아 static/posts.json을 만든다. 이 파일은 검색 페이지와 시리즈 내비게이션에서 사용한다. draft: true 글은 작성 중인 상태로 보고 검색 인덱스와 AI 검색 문맥에서 제외한다.

검증 방법

핵심 변환 로직은 Vitest로 검증한다. 숫자 접두어 제거, tag 정규화, slug 정규화, 경로 기반 category/tag 추출, callout 변환, wiki link 변환, frontmatter 기본값 보정이 테스트 대상이다.

로컬에서는 npm run sync로 경고 모드 동기화를 실행한다. CI와 배포 전에는 npm run sync:strict를 사용한다. strict 모드는 slug 충돌, broken wiki link, 처리 실패, 메타데이터 품질 문제를 실패로 보고 빌드를 막는다.

개선 방향

다음 단계는 변환 결과를 더 관찰 가능하게 만드는 것이다. 예를 들어 broken wiki link 리포트를 별도 파일로 남기고, 글별 변환 전후 diff를 요약하면 배포 전에 문제를 더 빨리 찾을 수 있다.

또한 slug 충돌은 현재 strict 실패 조건이지만, 앞으로는 충돌 후보를 더 친절하게 제안할 수 있다. 파일 경로 기반 slug를 유지하되, 같은 이름의 글이 늘어날 때 어떤 경로에서 충돌했는지 명확히 보여주는 방향이 좋다.