Next.js
Markdown 코드 블럭이 깨졌을 때 배운 것
블로그 글의 코드 블럭이 배포 환경에서만 이상하게 렌더링됐다. 원인은 remark 플러그인 순서였다.
로컬에서는 멀쩡하게 보이는 코드 블럭이 배포하고 나면 이상하게 보이는 걸 겪었다. 백틱 세 개짜리 펜스가 그대로 텍스트로 출력되거나, 언어 하이라이팅이 안 되거나. 원인을 찾는 데 생각보다 오래 걸렸다.
먼저 확인할 것
렌더링 결과를 HTML로 직접 본다. 코드 블럭이 제대로 파싱됐다면 <pre><code class="language-bash"> 같은 구조가 나와야 한다. 텍스트만 덩그러니 있으면 remark가 펜스드 코드 블럭을 처리하지 못한 것이다.
curl -s https://yourblog.com/some-post | grep -A5 '<pre>'
remark 플러그인 순서 문제
Next.js에서 MDX를 쓸 때 next.config.mjs에 remark/rehype 플러그인을 추가한다. 문제는 플러그인 실행 순서가 중요하다는 것이다.
// next.config.mjs
import createMDX from '@next/mdx';
import remarkGfm from 'remark-gfm';
import rehypePrettyCode from 'rehype-pretty-code';
import rehypeSlug from 'rehype-slug';
const withMDX = createMDX({
options: {
remarkPlugins: [remarkGfm],
rehypePlugins: [
rehypeSlug,
// rehype-pretty-code는 코드 블럭을 변환하므로 다른 코드 관련 플러그인보다 먼저 와야 한다
[rehypePrettyCode, { theme: 'github-dark' }],
],
},
});
내 경우에는 rehype-raw가 rehype-pretty-code보다 먼저 실행되면서 이미 변환된 HTML을 다시 파싱하다가 코드 블럭이 뭉개지는 현상이 있었다.
로컬과 배포가 다른 이유
로컬에서는 개발 모드로 실행하기 때문에 MDX 변환이 다르게 동작할 수 있다. npm run build && npm start로 프로덕션 빌드를 로컬에서 먼저 확인하는 습관이 필요하다. 이걸 했다면 배포 전에 잡았을 것이다.
코드 블럭 안의 특수문자
{, } 같은 중괄호는 MDX에서 JSX 표현식으로 해석될 수 있다. 코드 블럭 안에서도 마찬가지다. 이런 경우에는 이스케이프하거나 String.raw로 감싸야 한다. 특히 템플릿 리터럴이나 Bash 변수를 포함한 코드 예제에서 자주 발생한다.
{/* 문제 */}
```bash
echo ${HOME}
{/* 해결: 백슬래시 이스케이프 */}
echo $\{HOME\}
## 검증 루틴
마크다운 파서가 얽혀 있는 프로젝트라면 글을 올리기 전에 빌드 결과에서 HTML을 직접 확인하는 게 번거롭지만 확실하다. 코드 블럭 깨짐은 화면에서 바로 보이는 버그라 배포 후에 발견하면 민망하다.