03 / 가이드
Markdown에서 HTML로: 깨끗한 발행 워크플로
Markdown이 왜 오래가는 소스 형식인지, 제한된 변환기가 실제로 무엇을 지원하는지, 새니타이징과 링크 규칙이 출력을 안전하게 지키는 방법, HTML 왕복이 무엇을 잃는지, 그리고 문서·블로그 파이프라인에서 변환이 자리 잡는 위치.
Markdown은 보내기가 아니라 소스다
발행 파이프라인에는 도구, 호스팅, 리디자인을 견디는 마스터 형식이 필요합니다. 일반 텍스트 Markdown이 그 마스터입니다. 어떤 편집기에서도 읽히고, 버전 관리에서 diff가 되고, 올해 그것을 렌더링하는 HTML 템플릿과 무관합니다.
이것이 작동하게 하는 규율은 단방향 흐름입니다. Markdown은 사람이 편집하고, HTML은 변환기가 생산하며, 아무도 출력을 손으로 패치하지 않습니다. 보낸 HTML에 손 수정이 들어가는 순간 마스터가 둘이 되고, 둘은 결국 어긋납니다.
- 이식성이식성: Markdown 파일은 모든 편집기에서 열리고, 마이그레이션 프로젝트 없이 HTML, PDF, 슬라이드, 문서 시스템으로 변환됩니다.
- diff 가능리뷰 가능성: 산문 변경은 깨끗한 줄 diff로 드러나지만, HTML 마스터는 한 단어 수정을 태그와 속성 속에 파묻습니다.
- 스타일이 아니라 구조관심사의 분리: 소스는 구조——제목, 목록, 인용——만을 담고 타이포그래피는 테마가 결정하므로, 리디자인이 아카이브를 건드리는 일이 없습니다.
지원되는 서브셋이 변환하는 것——평탄화되는 것
의도적인 변환기가 서브셋만 지원하는 데는 이유가 있습니다. 지원되는 구조가 하나 늘 때마다 아무도 리뷰하지 않은 마크업을 밀반입할 통로가 하나 늘기 때문입니다. 변환에 의지하기 전에, 콘텐츠가 그 선을 기준으로 어디에 있는지 파악하세요.
Markdown 및 HTML 작업 영역이 변환하는 것은 정확히 이 서브셋입니다. Markdown 문법으로 쓴 이미지는 대체 텍스트와 링크로 퇴보하고, 생 HTML로 쓴 표는 그리드를 잃고 셀 텍스트만 남깁니다. 서브셋 안에서 작성하면 발행 시점에 놀랄 일이 없습니다.
- 깨끗한 변환깨끗하게 변환됨: 최대 6단계 제목, 단락, 굵게, 기울임, 취소선, 인라인 코드, 펜스 코드 블록, 순서 있는 목록과 없는 목록, 블록 인용, 가로줄, 인라인 링크.
- 알려진 손실평탄화되거나 사라짐: 임베디드 이미지, 표, 각주, 작업 목록, 생 HTML 블록은 서브셋에 대응되는 표현이 없어서 사라지거나 일반 텍스트로 퇴보합니다.
- 실제 글로 테스트테스트는 간단합니다. 대표적인 글을 변환하고 출력을 읽으세요. 결과에 없는 것은 처음부터 계약에 없던 것입니다.
새니타이징은 추가 단계가 아니라 발행의 일부다
변환된 HTML은 페이지에 주입될 운명이며, 주입되는 마크업은 공격 표면입니다. 깨끗한 파이프라인은 기본으로 새니타이즈합니다. 스크립트, 스타일, iframe, 폼, 임베드, 이미지는 단호하게 제거되고, 알 수 없는 태그는 텍스트로 풀리며, 속성은 벗겨집니다.
미리보기 패널은 새니타이즈된 출력을 렌더링하고 원격 리소스를 절대 로드하지 않으므로, 적대적 마크업을 붙여 넣어도 도구 자체가 외부로 신호를 보낼 수 없습니다.
- 활성 콘텐츠 제거능동적 동작을 싣는 요소——script, style, iframe, object, embed, svg, form, video, audio, img——는 무력화가 아니라 내용째로 제거됩니다.
- 속성 벗기기속성은 통째로 사라집니다. 인라인 스타일도, 이벤트 핸들러도, 소스에서 밀반입된 클래스도 없습니다. 앵커는 스킴 검사를 통과할 때만 href를 유지합니다.
- 침묵이 아니라 보고작업 영역은 제거한 것——삭제된 노드와 벗겨낸 속성의 개수——을 보고하므로, 새니타이징은 조용한 변형이 아니라 눈에 보이는 사건입니다.
링크는 안전한 스킴만 남긴다
렌더링된 문서는 대부분 링크이며, 링크야말로 새니타이징이 구체화되는 곳입니다. 변환기는 http, https, mailto URL과 페이지 내 #프래그먼트만 받습니다. 그 외——javascript:, data:, 프로토콜 상대 트릭——는 href를 잃고 일반 텍스트로 렌더링됩니다.
변환기를 표준으로 정하기 전에 허용 목록을 콘텐츠와 대조하세요. FTP 미러나 커스텀 앱 스킴에 정당하게 링크하는 문서 세트는 그 링크들을 수동으로 보존해야 합니다. 제정신인 새니타이저가 자동으로 통과시키지 않기 때문입니다.
- 스킴 허용 목록살아남은 링크에는 rel="noreferrer noopener"가 찍혀서, 따라간 링크가 열어준 페이지를 보거나 스크립팅할 수 없습니다.
- noopener noreferrer같은 규칙이 양방향으로 적용됩니다. Markdown에 쓰인 링크는 변환 시 검사되고, 붙여 넣은 HTML에서 발견된 href는 새니타이징 후 다시 검사됩니다.
- 라벨은 살아남는다링크가 스킴을 잃어도 라벨 텍스트는 남습니다. 깨진 내비게이션이 즉시 드러나며, 조용한 javascript: 페이로드를 싣고 발행되지 않습니다.
돌아오는 길은 진짜 것들을 잃는다
HTML을 Markdown으로 변환하는 것은 왕복이 아니라 구출입니다. 서브셋이 이해하는 구조——제목, 단락, 강조, 목록, 인용, 코드——는 무사히 돌아오지만, 나머지는 변환이 시작되기도 전에 새니타이저가 버렸습니다.
HTML-에서-Markdown은 더 이상 통제하지 못하는 페이지——오래된 CMS보내기, 렌더링된 HTML로만 남은 문서——에서 산문을 끌어내는 수단으로 다루세요. 그런 다음 왕복이 고칠 수 없는 것을 고칩니다. 이미지를 다시 넣고, 표를 다시 짜고, 그 후로는 Markdown을 마스터로 유지하는 것입니다.
- 표 붕괴표는 붕괴합니다. 서브셋에 표 문법이 없어서 셀의 그리드가 셀 텍스트의 나열이 되므로, 표 형식 데이터는 다시 작성하거나 CSV보내기로 대신해야 합니다.
- 미디어 제거이미지, 비디오, 인터랙티브 임베드는 설계상 사라집니다. Markdown이 조립되기 전에 새니타이저가 활성 콘텐츠로 제거했기 때문입니다.
- 텍스트가 스타일보다 오래 산다서브셋 밖의 서식——span, div, 클래스, 앵커 대상——은 흔적을 남기지 않습니다. 텍스트는 살아남고 프레젠테이션은 살아남지 못합니다.
문서·블로그 워크플로에서 변환이 자리 잡는 곳
변환 단계는 발행 시점에 글당 한 번 실행됩니다. Markdown으로 초고를 쓰고 리뷰하고, 새니타이즈된 HTML로 변환하고, 렌더링 결과를 검증한 뒤 발송합니다. 모든 것이 브라우저 탭 안에서 일어나며 초고는 업로드되지 않습니다. 콘텐츠가 미발표 출시일 때 특히 중요합니다.
- 발행 시점 단계작업 영역은 최대 256 KiB의 소스를 받아 최대 512 KiB의 출력을 만듭니다. 책 한 챕터 규모에는 넉넉합니다. 한도를 넘으면 조용히 자르는 대신 명시적 오류를 보고합니다.
- 명시적 한도출력을 CMS 필드에 복사하거나 파일로 다운로드하세요. 두 경로 모두 미리보기가 보여준 그 새니타이즈된 문서를 가져갑니다.
- 패치 말고 재변환Markdown은 그것이 설명하는 코드 옆에서 버전 관리하고, 매 수정 후에 오래된 HTML을 패치하는 대신 다시 변환하세요.
구조화된 텍스트에는 루틴이 어울립니다.
Markdown 초고와 JSON 페이로드는 같은 규율을 공유합니다. 먼저 파싱하고, 구조를 검사하고, 리뷰 전체를 당신의 기기에 머무르게 하는 것입니다.