왜 마크다운 유틸리티가 필요한가?
프로젝트에서 마크다운을 사용하다 보면, 코드 블록이나 일반 텍스트를 작성할 때 들여쓰기를 자연스럽게 하게 됩니다. 그런데 대부분의 마크다운 라이브러리는 들여쓰기를 제대로 인식하지 못해, 의도하지 않은 <p> 태그나 <code> 블록이 생성되는 문제가 발생합니다.
예를 들어, 다음과 같이 작성한 경우를 생각해 봅시다.
This is a paragraph
This is a second paragraph
위 코드는 4칸 이상 들여쓰기가 있기 때문에, 마크다운 파서는 두 번째 줄을 코드 블록으로 처리해 버립니다. 결과적으로 HTML은 다음과 같이 렌더링됩니다.
<p>This is a paragraph</p>
<pre><code>This is a second paragraph
</code></pre>
이 문제를 피하려면 모든 들여쓰기를 제거하고 한 줄로 작성해야 하는데, 이는 가독성을 떨어뜨리고 유지보수를 어렵게 만듭니다.
이 글에서는 이 문제를 해결하는 커스텀 마크다운 유틸리티를 소개하고, Astro와 Svelte를 포함한 다양한 프레임워크에서 활용하는 방법을 다룹니다.
참고: 이 유틸리티는 Splendid Labz에서 제작한
@splendidlabz/utils패키지에 포함되어 있습니다. 자세한 내용은 원문 링크를 참고하세요.
마크다운 유틸리티의 핵심 기능
이 유틸리티는 들여쓰기 문제를 해결하여, 코드가 어떻게 들여쓰기 되어 있든 항상 올바른 HTML을 생성합니다.
// markdown 유틸리티 사용 예시
import { markdown } from '@splendidlabz/utils';
const content = `
This is a paragraph
This is a second paragraph
`;
// 들여쓰기를 유지한 채 올바른 HTML 생성
const html = markdown(content);
// 출력: <p>This is a paragraph</p><p>This is a second paragraph</p>
// inline 옵션을 true로 설정하면 <p> 태그 없이 반환
const inlineHtml = markdown(content, { inline: true });
Astro에서 활용하기
Astro 컴포넌트에서 이 유틸리티를 사용하는 방법은 간단합니다. 아래 코드를 참고하세요.
---
// src/components/Markdown.astro
import { markdown } from '@splendidlabz/utils';
const { inline = false, content } = Astro.props;
const slotContent = await Astro.slots.render('default');
// content prop 또는 슬롯 콘텐츠를 처리
const html = markdown(content || slotContent, { inline });
---
<div class="markdown-body" set:html={html} />
사용 예시:
<Markdown>
### 제목
여기에 마크다운 본문을 작성합니다.
</Markdown>
Svelte에서 활용하기
Svelte는 슬롯에서 동적 콘텐츠를 읽을 수 없기 때문에, prop으로 전달하는 방식을 사용합니다.
<!-- src/lib/Markdown.svelte -->
<script>
import { markdown } from '@splendidlabz/utils';
export let content = '';
export let inline = false;
$: html = markdown(content, { inline });
</script>
<div class="markdown-body">
{@html html}
</div>
사용 예시:
<Markdown content="### Svelte에서 마크다운 사용하기\n- 항목 1\n- 항목 2" />
React와 Vue에서도 쉽게 확장 가능
React와 Vue도 동일한 원리로 적용할 수 있습니다. React에서는 dangerouslySetInnerHTML을 사용하고, Vue에서는 v-html 디렉티브를 사용하면 됩니다.
// React 예시
import { markdown } from '@splendidlabz/utils';
function Markdown({ content, inline = false }) {
return <div dangerouslySetInnerHTML={{ __html: markdown(content, { inline }) }} />;
}
<!-- Vue 예시 -->
<template>
<div v-html="html"></div>
</template>
<script setup>
import { markdown } from '@splendidlabz/utils';
import { computed } from 'vue';
const props = defineProps({ content: String, inline: Boolean });
const html = computed(() => markdown(props.content, { inline: props.inline }));
</script>
마크다운 유틸리티 사용 시 주의사항
이 유틸리티는 편리하지만, 몇 가지 주의할 점이 있습니다.
- 보안: 사용자 입력을 마크다운으로 렌더링할 경우, XSS 공격에 취약할 수 있습니다. 반드시
sanitize-html같은 라이브러리로 HTML을 정화하세요. - 성능: 매우 큰 마크다운 문서를 처리할 때는 성능 저하가 발생할 수 있습니다. 필요한 경우 캐싱을 고려하세요.
- 문법 지원: 모든 마크다운 문법을 지원하지 않을 수 있습니다. 팀 내에서 사용할 문법을 미리 정의해 두는 것이 좋습니다.
다음 단계: 더 나은 개발 경험을 위한 도구
이 유틸리티 외에도 Splendid Labz는 레이아웃, Astro 컴포넌트, Svelte 컴포넌트 등 개발 경험(DX)을 향상시키는 다양한 도구를 제공합니다. 관심이 있다면 Splendid Utils를 방문해 보세요.
결론
마크다운 들여쓰기 문제는 많은 개발자들이 겪는 불편함입니다. 이 유틸리티를 사용하면 코드의 가독성을 유지하면서도 올바른 HTML을 생성할 수 있어, 개발 생산성이 크게 향상됩니다.
Astro, Svelte, React, Vue 등 어떤 프레임워크를 사용하든 쉽게 통합할 수 있으니, 한번 적용해 보시길 권장합니다.
함께 보면 좋은 글
- AWS Verified Permissions로 구현하는 실전 세분화 인가 Convera 사례에서 배우는 것
- NVIDIA Blackwell Ultra, AI 추론의 숨은 병목 소프트맥스를 해결하다
