Python Markdown으로 HTML 출력 시 이미지 캡션을 덧붙여주기
Python Markdown을 비롯해 다양한 마크다운 렌더러(HTML 변환기)의 결과물을 보면 이미지 캡션(설명 혹은 타이틀)을 따로 표시해 주도록 만들어 주지는 않는다. 그저 이미지의 alt 속성에 해당 내용을 넣어서 접근성을 향상해 주는 정도다. 물론 이미지 위에 커서를 놓고 잠시 기다리면 해당 캡션 내용이 뜨기도 하지만 그걸 원하는 건 아니다.
개인적으로도 이 문제 아닌 특징(?) 때문에 마크다운 문서에 이미지를 첨부할 때는 늘 아래와 같이 캡션을 이미지 하단에 별도로 덧붙여서 작성했었다.

*이미지 설명*
이렇게 써서 HTML로 출력하면 이미지 밑에 캡션 내용이 기울어짐 스타일로 보인다. 어떻게든 원하는 대로 쓸 수는 있는 셈이다.
하지만 문제는 보다시피 똑같은 내용이 반복된다는 점이다. 마크다운 문서에 같은 내용의 라인이 연속으로 보이는 게 그렇게 편하진 않다. 거기다 하나를 고치면 다른 하나도 같이 고쳐줘야 하는 귀찮음도 유발한다. 이게 관련이 있는지는 모르겠지만 애드센스 자동광고가 이미지와 수동으로 붙인 캡션 사이에 붙는 경우도 많았다.
그래서 이를 해결하기 위해 캡션이 자동으로 붙는 기능을 만들고 싶어졌다. 거기다 HTML5에 맞는 식으로 이미지를 figure로 감싸고 figcaption으로 캡션을 붙여주는 방식으로 출력해서 조금이라도 애드센스가 이상하게 붙는 문제를 해결하고 싶었다.
쉽게 될 줄 알았지만 결국 강제로(?) 집행했다
Python Markdown 확장은 꽤나 저레벨로 다룰 수 있어서 쉽게 될 줄 알았는데 생각보다 확장을 이용하는 방법은 쉽지 않았다. 개인적으로 작성해 쓰는 여러 확장들과의 충돌도 상당한 걸림돌이었기도 했고 말이다.
그래서 결국은 강제로 문제를 해결하기로 했다. 마크다운은 HTML 태그를 지원하니 차라리 이미지 문법을 HTML 태그로 미리 치환하면 해결될 것 같아서다.
그래서 아래와 같은 코드가 탄생했다.
import re
def update_image_caption(text: str) -> str:
pattern = r'!\[(.*?)\]\((.*?)\)'
replacement = r'''<figure>
<img src="\2" alt="\1" />
<figcaption>\1</figcaption>
</figure>'''
return re.sub(pattern, replacement, text)
보다시피 그냥 정규표현식으로 마크다운 텍스트에서 이미지 문법의 내용을 강제로 HTML 코드로 미리 바꿔버리는 식이다. 이렇게 하면 마크다운 모듈이 HTML로 출력할 때 위 내용은 그대로 출력된다.
사용법은 당연하게도 마크다운 원문 텍스트 내용을 먼저 위 함수로 변환시키고 이를 HTML로 출력하게 하면 된다.
import markdown
text = load_markdown_file(...)
# 렌더링 전에 미리 이미지 문법을 태그로 변환
updated_text = update_image_caption(text)
md = markdown.Markdown(...)
html = md.convert(updated_text)
위 샘플은 대충 작성한(pseudo) 코드라 실제로 동작하지는 않으니 주의하자. 뭐 하여간 이런 식으로 쓸 수 있다는 말이다.
잘 돌아가나?
샘플 코드가 이렇게 있다고 치자.

이 마크다운 문서를 앞서 이야기한 프로세스로 HTML로 출력하니 아래와 같이 바뀌었다.
<figure>
<img src="path/to/img.jpg" alt="이 이미지는 집에 갔습니다." />
<figcaption>이 이미지는 집에 갔습니다.</figcaption>
</figure>
결과적으로 가장 첫 문제였던 마크다운 문서에서 중복 텍스트가 보이는 거슬리는 상황은 완벽하게 해결되었다.
그렇다면 애드센스 자동 광고가 이미지랑 캡션 사이에 끼어드는 일은... 해결이 안 되었다. 처음에는 애드센스 측이 알아서 잘 대응하나 싶었는데 좀 시간이 지나자 다시 이미지와 캡션 사이에 광고를 끼워 넣는 일이 잦았다. 아니 일부러 이렇게 광고를 배치하는 건 같은데 좀 보기에는 많이 안 좋아서 불만스럽다.
하여간 완벽하게 해결된 건 아니지만 그래도 가장 첫 목적은 이루었고 아직까진 딱히 큰 부작용도 없는 것 같아 만족하는 편이다.
다만 작은 부작용이 하나 있는데 굳이 바꾸지 말아야 할 코드 블록 문법 내부까지 간섭한다는 점이 있다. 이 부작용은 다음 시리즈(?)를 위해 남겨두자.
이것 말고도 부작용이 더 있긴 하다. 마크다운 문서에서 미리 이미지 문법의 내용을 HTML 코드를 변환한 다음에 HTML로 출력시키기 때문에 Python Markdown에서 만약 Treeprocessor를 이용한 확장을 사용 중이라면 이 확장에서 미리 변환된 부분이 제대로 액세스 안 되는 문제를 겪을 수도 있다. 물론 해결이 어느 정도 가능한 것 같긴 한데 개인적으론 시도하다 귀찮아져서 확장 안 쓰는 방법으로 포기했고 편해졌다. 하하....