형식의 강제는 때로 작성 흐름을 끊는다
기존 구조에서는 frontmatter의 title, date, tags, summary, draft, slug가 사실상 필수처럼 동작했다. 여기서 title은 글 제목, slug는 URL 경로로 사용된다.
문제는 작성 경험이다.
글쓰기의 본질은 기록과 전달인데, 매번 메타데이터부터 채우게 만들면 집중이 깨진다. 특히 date, tags, summary, slug처럼 UI에서 직접 소비되지 않는 값까지 강제하면, 필수 입력의 실익보다 마찰 비용이 더 커진다.
반면 독자에게 핵심인 정보는 결국 제목과 본문이다.
따라서 작성자 관점에서는 최소 정보만으로 저장·발행이 가능해야 하고, 나머지 메타데이터는 필요할 때 선택적으로 보완할 수 있어야 한다.
실제로 드러난 문제: 글 상세 페이지 404
.md 파일명을 URL에 그대로 반영하던 구간에서는, 파일명에 공백이나 특수문자가 포함될 때 라우팅 매칭이 깨져 상세 페이지가 404로 떨어졌다. 목록에서는 글이 보이는데 상세 페이지 진입이 실패하는 경험은 서비스 신뢰도를 크게 떨어뜨린다.
그렇다고 이 문제를 해결하겠다고 파일명에서 공백·특수문자 사용 자체를 금지하는 건 좋은 접근이 아니다. 파일명은 작성자의 작업 맥락에서 읽기 쉬워야 하고, 가독성은 실제 운영 효율과도 직결되기 때문이다.
문제를 없애기 위해 표현력을 제한하는 대신, 표현은 유지하고 URL만 안전하게 변환하는 방식이 옳다.
옵시디언 중심 워크플로우에 맞추기
이 블로그는 로컬 Markdown 파일 기반으로 운영된다.
- 옵시디언에서 글 작성
- 원격 저장소 푸시
- CI/CD 실행 및 빌드
- 배포
즉, 빌드 시점에 파일명을 안전한 URL로 변환하면 된다.
또한 옵시디언 특성상 “파일명 = 글 제목” 흐름이 자연스럽기 때문에, frontmatter.title을 강제하지 않아도 된다.
해결 방법
1) frontmatter 유연화
frontmatter 필드를 optional로 전환했다.
빈 문자열, null, YAML 빈 값(field:)도 전처리로 안전하게 허용한다.
2) 제목 처리
표시용 제목은 다음 우선순위로 결정한다.
frontmatter.title이 있으면 사용- 없으면
.md파일명(확장자 제거)을 제목으로 사용
3) URL 처리
URL은 파일명을 그대로 쓰지 않고 kebab-case로 자동 변환한다.
slug가 있으면 우선 사용하고, 없으면 파일명 fallback을 URL-safe로 변환한다.
function toUrlSegment(value: string): string {
const normalized = value
.normalize("NFKC")
.toLowerCase()
.trim()
.replace(/['"`]/g, "")
.replace(/&/g, " and ")
.replace(/[^\p{Letter}\p{Number}._-]+/gu, "-")
.replace(/-+/g, "-")
.replace(/^-+|-+$/g, "");
return normalized.length > 0 ? normalized : "post";
}
function deriveUrlPath(slug: string | undefined, relativePath: string): string {
const fallback = relativePath.replace(/\.(md|mdx)$/i, "");
const source = slug?.trim();
if (source) return source.replace(/^\/+|\/+$/g, "");
return fallback.split("/").filter(Boolean).map(toUrlSegment).join("/");
}
변환 예시
Why Direct-to-Storage Uploads with Presigned URLs.md
→why-direct-to-storage-uploads-with-presigned-urlsNestJS Review Notes from a Todo API.md
→nestjs-review-notes-from-a-todo-apiAI & DB "Review".md
→ai-and-db-review
이제 slug를 수동 입력하지 않아도 안정적인 URL이 자동 생성된다. 파일명 작성에도 제한을 두지 않아 가독성에 어려움이 없고, 본질인 글 작성 자체에 집중할 수 있다.