서론
// .\app\blog\[slug]\page.js
export default async function Post(props) {
const slug = props.params.slug;
const postRes = await fetch(`http://localhost:3000/${slug}.md`);
const data = await test.text();
return <>{data}</>;
}
전편에서는
slug와 같은 이름의 markdown 파일을
public 폴더에 만들었다.
하지만 출력된 내용은
문자열 그대로인 것으로 보인다.
이번에는 Markdown을 html형식으로 만들어 볼 생각이다.
md(markdown)을 파싱(parsing)하는 방법?도구?는 여러가지가 있다.
조금 유의해야 하는 점은
Next.js를 사용하고 있기 때문에
html으로 파싱하는 것이 아니라
js (jsx)으로 파싱해야 한다.
Next.js에서는 mdx를 많이 사용하는 것 같다.
Next.js 공식 MDX 사용 설명
나도 원래 MDX를 사용할까 많이 검색해봤지만...
그냥 md 파일을 사용하고 싶어서
다른 방법을 찾아봤다.
결국 사용한 것은 markdown-to-jsx
,
<Markdown> 컴포넌트이다.
Markdown 컴포넌트
사용법이 간단하고,
현재 코드의 const data = await test.text();
data 변수를 그대로 사용할 수 있었다.
markdown-to-jsx 설치
npm i markdown-to-jsx
터미널에 명령어를 입력해서 설치.
Markdown 컴포넌트 사용
// .\app\blog\[slug]\page.js
import Markdown from "markdown-to-jsx";
export default async function Post(props) {
const slug = props.params.slug;
const postRes = await fetch(`http://localhost:3000/${slug}.md`);
const data = await test.text();
return <Markdown>{data}</Markdown>;
}
사용법은 아주 간단하다.
Markdown 컴포넌트를 불려오고
자녀로 markdown내용을 문자열로 사용한다.
간단히 예시로 설명하면
<Markdown># h1제목</Markdown>
위의 내용은 브라우저에서
아래의 html으로 파싱된다.
<article>
<h1>h1 제목</h1>
</article>
img - Image 변경
테스트해보니
이미지가 제대로 나오지 않고 오류 경고도 나온다.
markdown-to-jsx
에서 이미지는
기본적으로 img태그로 출력된다.
하지만
next.js에서는
img태그를 사용하지 말라고 경고한다.
next.js은 SSR으로
직접 외부 이미지를 사용하지 않는 것을 추천하는 것 같다.
그리고 직접 테스트한 결과.
이미지의 경로나 형식에 따라서
Image컴포넌트는 대부분 정상 표시되지만
img태그는 이미지가 깨지는 경우가 있다.
그래서 options 변수를 만들었다.
const options = {
overrides: {
img: ({ src, alt, ...props }) => <Image width={500} height={500} alt={alt} src={src} {...props} />,
},
};
상세 설명과 사용법은
[npmjs 설명 안내문]에서 확인 가능하다.
간단히 설명하면...
원래 img 태그를 Image 컴포넌트로 대체하고,
img에 받았던 속성도 Image의 속성으로 지정했다.
추가로 Image 컴포넌트는 필수로 크기가 필요해서
임의로 width={500}
height={500}
으로 지정했다.
그리고
Markdown컴포넌트에 옵션을 추가했다.
// .\app\blog\[slug]\page.js
import Markdown from "markdown-to-jsx";
export default async function Post(props) {
const slug = props.params.slug;
const postRes = await fetch(`http://localhost:3000/${slug}.md`);
const data = await test.text();
const options = {
overrides: {
img: ({ src, alt, ...props }) => <Image width={500} height={500} alt={alt} src={src} {...props} />,
},
};
return <Markdown options={options}>{data}</Markdown>;
}
결과
브라우저로 결과을 받을 때,
각 태그가 잘 만들어져서 표시된다.
하지만 아무런 디자인이 없다.
tailwind css를 사용했기 때문에
아무 스타일이 없는 상태이다.