README는 마크다운으로 잘 써놨는데, 이걸 회사 CMS나 이메일에 넣으려니 HTML이 필요합니다. 변환기에 붙여넣으면 끝일 것 같지만, 표가 깨지거나 줄이 엉뚱하게 붙고, 가끔은 남의 마크다운을 변환해 그대로 올렸다가 보안 사고가 납니다. 변환할 때 실제로 무엇을 챙겨야 하는지 정리합니다.
마크다운이 HTML로 어떻게 바뀌나
기본 문법이야 #이 제목, *가 강조로 바뀌는 것은 익숙합니다. 까다로운 건 표나 취소선 같은 확장 문법입니다.
PiPi Worlds 마크다운 변환 도구는 GitHub 스타일 마크다운(GFM)을 따릅니다. 표를 넣으면 <table>, <thead>, <td>로 펼쳐지고, ~~취소선~~은 <del>old</del>이 됩니다. 자동 링크도 지원합니다. CommonMark가 정의한 표준 마크다운에 GFM 확장을 더한 형태라, 깃허브에서 보던 그 결과를 그대로 복사해 쓸 수 있습니다.
미리보기는 정화되고, 복사 소스는 원본이다
여기서 가장 중요한 구분이 나옵니다. 화면에 보이는 미리보기와 복사 버튼이 주는 HTML 소스는 다릅니다.
미리보기는 페이지에 반영되기 전에 DOMPurify로 정화됩니다. 그래서 마크다운에 <script>나 onerror 같은 위험 요소가 숨어 있어도 미리보기에서는 실행되지 않습니다. 반면 복사용 HTML 소스는 가공 없는 변환 결과입니다. 예를 들어 Hi <img src=x onerror="alert(1)"> <script>alert(2)</script>를 변환하면, 소스에는 그 onerror와 <script>가 그대로 남아 있습니다. 이 차이를 모르면 위험합니다.
그래서 어디서 한 번 더 정화해야 하나
판단 기준은 단순합니다. 마크다운의 출처를 신뢰할 수 있느냐입니다.
내가 쓴 README나 문서를 변환하는 거라면 복사한 소스를 그대로 써도 됩니다. 하지만 사용자가 입력한 마크다운(댓글, 게시글 등)을 변환해 웹에 표시한다면, 복사한 raw HTML을 그대로 올리는 순간 XSS(교차 사이트 스크립팅)의 통로가 됩니다. <script>만 막아서는 부족하고 onerror 같은 이벤트 속성도 막아야 합니다. 신뢰할 수 없는 입력은 반드시 서버에서 다시 정화하세요.
| 출처 | 복사 소스 그대로 사용 |
|---|---|
| 내가 쓴 문서 | 가능 |
| 사용자 입력(댓글 등) | 서버에서 재정화 필요 |
줄바꿈 한 번이 줄을 안 바꾸는 이유
자잘하지만 자주 당황하는 지점입니다. 마크다운에서 엔터를 한 번 쳤는데 HTML에서 줄이 안 바뀝니다.
표준 마크다운은 줄바꿈 한 번을 부드러운 줄바꿈(soft wrap)으로 봅니다. 줄1과 줄2를 엔터 하나로 나눠도 같은 <p> 문단 안에 이어집니다. 문단을 진짜로 나누려면 사이에 빈 줄을 넣어야 합니다. 한 문단 안에서 줄만 강제로 바꾸려면 줄 끝에 공백 두 칸을 두면 됩니다. 메일이나 CMS에서 줄 간격이 의도와 다르게 나온다면 대개 이 규칙 때문입니다.
그 마크다운, 어디서 변환하고 있나
마지막은 변환 장소 이야기입니다. 초안, 회의록, 비공개 명세를 HTML로 바꿀 때 그 텍스트가 어디론가 전송되는 도구라면, 공개 전의 내용이 외부 서버를 거치게 됩니다.
PiPi Worlds 마크다운 변환 도구는 변환이 전부 브라우저 안에서 실행됩니다. 입력은 전송되지 않으므로 초안과 비공개 메모가 내 기기에만 남습니다. 실시간 미리보기로 결과를 확인하고, 정화 여부를 의식하며 소스를 복사하세요. HTML 안에 base64 데이터가 보이면 Base64 도구로, JSON 조각이 섞여 있으면 JSON 포맷터로 이어서 확인하면 됩니다.