**discourse-to-markdown**는 클라이언트가 Accept: text/markdown 헤더를 보내거나 콘텐츠 URL에 .md를 붙일 때 포럼 콘텐츠를 Markdown으로 반환하는 새로운 플러그인입니다.
우리는 https://discourse.roots.io의 자체 포럼에서 이를 실행하고 있습니다:
curl -H "Accept: text/markdown" https://discourse.roots.io/latest
curl https://discourse.roots.io/t/serve-your-wordpress-posts-as-markdown/30321.md
LLM에 HTML을 공급하는 것은 비용이 많이 들며, 콘텐츠만 포함된 Markdown을 서빙하면 토큰 사용량을 3~5배까지 줄일 수 있습니다. 이는 더 저렴한 API 호출, 더 빠른 응답, 그리고 모델이 추론할 때 컨텍스트 윈도우에 더 많은 여유 공간을 의미합니다. 더 자세한 설명과 모든 사이트의 준비 상태 확인은 https://acceptmarkdown.com을 참고하세요.
클라이언트가 Markdown을 요청하는 방법
세 가지 진입점이 있습니다:
Accept: text/markdown헤더 (LLM에 이상적).mdURL 접미사- Discovery (모든 HTML 응답은
Link: <...>; rel="alternate"; type="text/markdown"헤더와<head>내의<link rel="alternate">태그를 통해 해당 Markdown 버전을 광고하며, RSS 피드는 Markdown 버전으로 가리키는<atom:link>를 포함합니다)
지원되는 경로
| 경로 | HTML | Markdown |
|---|---|---|
| 토픽 | /t/:slug/:id |
/t/:slug/:id.md |
| 단일 게시글 | /t/:slug/:id/:post_number |
/t/:slug/:id/:post_number.md |
| 카테고리 | /c/:slug/:id |
/c/:slug/:id.md |
| 태그 | /tag/:tag |
/tag/:tag.md |
| 최신 | /latest |
/latest.md |
| 인기 | /top |
/top.md |
| 핫 | /hot |
/hot.md |
| 사용자 활동 | /u/:username/activity |
/u/:username/activity.md |
설치
플러그인을 app.yml에 추가합니다:
hooks:
after_code:
- exec:
cd: $home/plugins
cmd:
- git clone https://github.com/roots/discourse-to-markdown.git
컨테이너를 재빌드합니다:
cd /var/discourse
./launcher rebuild app
그런 다음 관리자 → 설정 → 플러그인 → Markdown 출력에서 활성화합니다.
변환에 대한 참고 사항
이 플러그인은 raw가 아니라 Discourse의 cooked HTML을 변환합니다. cooked HTML은 독자가 보는 렌더링된 표현으로, 원박스(oneboxes)가 확장되고, 멘션이 링크되며, 인용이 출처를 명시한 상태입니다. 이는 독자가 실제로 보는 것을 보존하고, 어떤 GFM 호환 렌더러에서도 출력을 이동 가능하게 유지합니다. Discourse 전용 구조(인용, 원박스, 디테일, 멘션, 해시태그, 이모지, 라이트박스, 투표)는 변환 전에 적절히 재작성됩니다.
변환된 Markdown은 post.id + post.updated_at을 키로 사용하여 게시글별로 Redis에 캐시되며, 편집 시 자동으로 무효화됩니다.
설정
| 설정 | 기본값 | 목적 |
|---|---|---|
discourse_to_markdown_enabled |
false |
플러그인의 마스터 스위치 |
discourse_to_markdown_md_urls_enabled |
true |
HTML 경로의 쌍으로 .md URL 접미사를 허용 |
discourse_to_markdown_strict_accept |
false |
클라이언트의 Accept 헤더가 text/html과 text/markdown을 모두 제외할 때 406 Not Acceptable 반환 |
discourse_to_markdown_emit_vary |
true |
캐시가 서로 다른 표현을 교차 서빙하지 않도록 Markdown 및 406 응답에 Vary: Accept 출력 |
discourse_to_markdown_include_post_metadata |
true |
Markdown 표현에 URL, 카테고리, 태그, 작성자, 타임스탬프 포함 |
리소스
- 소스/이슈: GitHub - roots/discourse-to-markdown: A Discourse plugin that serves post content as Markdown via Accept headers and .md URLs · GitHub
- acceptmarkdown.com — 콘텐츠 협상을 통해 에이전트에 Markdown 서빙 및 사이트 준비 상태 확인
- RFC 9110 §12.5.1 — Proactive Negotiation — 이 플러그인이 구현하는 사양
- RFC 7763 —
text/markdown미디어 타입 등록 - MDN — Content negotiation — 개념에 대한 접근하기 쉬운 소개
- 전체 사양 + 개발자 문서 목록은 acceptmarkdown.com/reference를 참고하세요