React
에서Markdown
을 랜더링하려면 우선Markdown
을React
컴포넌트로 변환해야합니다. 예를 들어,Markdown
의 헤딩은html
의h1
,h2
로 변환하는 작업이 필요합니다.
이러한 변환을 쉽게해주는 라이브러리가 바로 react-markdown
입니다👏👏👏
npm install react-markdown
위의 명령어를 통해 react-markdown
을 설치해줍니다. 그리고 리액트 프로젝트에서 다음과 같이 마크다운을 생성합니다.
export default function Blog() {
const markdownText = `
# 안녕하세요!
저는 현재 리액트에서 \`react-markdown\`를 이용하여 **마크다운**을 랜더링하고 있습니다.
`;
return (
<div>Blog</div>
);
}
이어서 react-markdown
을 불러옵니다.
import React from "react";
import ReactMarkdown from "react-markdown";
export default function Blog() {
const markdownText = `
# 안녕하세요!
저는 현재 리액트에서 \`react-markdown\`를 이용하여 **마크다운**을 랜더링하고 있습니다.
`;
return (
<div style={{ width: "100%", display: "flex", justifyContent: "center" }}>
<div style={{ maxWidth: "768px", width: "100%" }}>
<ReactMarkdown>
{markdownText}
</ReactMarkdown>
</div>
</div>
);
}
백틱(backtick) 안에 백틱을 추가해야할때는 역슬래시를 이용하여 이중으로 사용할 수 있습니다.
저는 간단한 스타일을 추가하였습니다. (정렬이 안되어 있으면 꼴보기가 싫..)
그 결과 다음과 같이 마크다운이 랜더링됩니다. 하지만 벨로그의 백틱(backtick)을 이용한 코드 강조처럼 react-markdown이 강조가 되지 않습니다. 이러한 것은 직접 css 작업을 해줘야합니다.
다음과 같이 code 태그의 스타일을 지정해주고 컴포넌트에서 css를 불러와줍니다.
code {
padding: 3px 6px;
border: none;
border-radius: 3px;
background-color: #e9ecef;
font-size: 1.6rem;
font-family: "Pretendard", "Malgun Gothic", sans-serif;
}
그랬더니 다음과 같이 제대로 작성됩니다.
직접 마크다운을 작성해서 불러오는 것 외에 .md
파일 자체를 랜더링하려면 react-hook
의 useEffect
와 useState
를 이용하여 파일을 가져와야합니다.
다음과 같이 작성해줍니다.
import React, { useEffect, useState } from "react";
import ReactMarkdown from "react-markdown";
import "../../styles/markdown.css";
export default function Blog() {
const [markdown, setMarkdown] = useState("");
useEffect(() => {
fetch("./01.md")
.then((response) => response.text())
.then((text) => setMarkdown(text));
}, []);
return (
<div style={{ width: "100%", justifyContent: "center", display: "flex" }}>
<div style={{ maxWidth: "768px", width: "100%" }}>
<ReactMarkdown>
{markdown}
</ReactMarkdown>
</div>
</div>
);
useEffect
내부에서 fetch
를 사용하여 ./01.md
경로의(index.html 기준) Markdown
파일을 호출합니다.fetch
로 반환된 response
에서 text()
메서드를 사용하여 텍스트 데이터를 추출합니다.setMarkdown
함수를 사용하여 markdown
상태에 업데이트합니다.Markdown
파일이 랜더링되게 합니다.01.md
파일의 위치는 다음과 같습니다.
다음과 같은 .md 파일을 랜더링 시켰더니..
코드를 나타내는 마크다운은 개발자 모드를 열어서 확인해보니 pre
태그 자식 요소로 code
태그로 구성됩니다. 그런데 이러한 코드블록이 벨로그처럼 표시되지 않습니다..😭
이때에는 언어별로 class를 생성해주는 rehype-highlight
라이브러리를 사용해야합니다.
npm install rehype-highlight
import rehypeHighlight from "rehype-highlight";
return (
<div style={{ width: "100%", justifyContent: "center", display: "flex" }}>
<div style={{ maxWidth: "768px", width: "100%" }}>
<ReactMarkdown rehypePlugins={[rehypeHighlight]}>
{markdown}
</ReactMarkdown>
</div>
</div>
);
rehype-highlight
를 import
해주고 ReactMarkdown
에 rehypePlugins
를 추가하여 rehypeHighlight
를 옵션값으로 넣어줍니다.
그 후, 개발자 모드에서 열어보면 다음과 같이 pre
code
태그에 class
가 추가된 것을 확인하실 수 있습니다.
그럼 이제 언어별로 직접 css 수정을 하🥊
언어별로 css를 직접 수정할 필요없이 이미 만들어져있는 라이브러리를 사용하면됩니다.
npm install highlight.js
highlight.js
를 설치하시고 css파일을 import
해주면됩니다.
import "highlight.js/styles/a11y-dark.css";
그럼 다음과 같이 언어별로 마크다운이 아주 예쁘게 생성된 것을 보실 수 있습니다.
다른 스타일을 원하시면 node_modules > highlight.js > styles
폴더에 너무나도 많은 코드 스타일의 css가 있습니다. 이중에서 마음에 드는걸 사용하시면됩니다.
추가로 highlightjs 공식홈페이지에서 미리보기로 코드 스타일을 확인하실 수 있습니다!
코드 태그가 너무 이뻐졌당~😻😻
위와 같은 간단한 md 파일을 랜더링한다고 했을 때
태그 네임이 그대로 출력되는 불상사가 일어나게 된다.. 이러한 이슈를 해결하기 위해서는 rehype-raw
라이브러리를 이용해야합니다.
rehype-raw
는 React Markdown
에서 사용되는 rehype
플러그인 중 하나입니다. 해당 플러그인은 Markdown
을 HTML
로 변환할 때 HTML
태그를 랜더링하는 방법을 제어하는 플러그인입니다.
rehype-raw
를 React Markdown
에 추가하면 HTML 코드가 특수 문자로 이스케이프되어 안녕하세요
가 태그 네임 없이 올바르게 랜더링됩니다.
아래의 명령어로 rehype-raw
를 설치합니다.
npm install rehype-raw
그런 다음 다음과 같이 코드를 작성합니다.
import React, { useEffect, useState } from "react";
import ReactMarkdown from "react-markdown";
import rehypeHighlight from "rehype-highlight";
import rehypeRaw from "rehype-raw"; // 추가된 부분
import "../../styles/markdown.css";
import "highlight.js/styles/a11y-dark.css";
export default function Blog() {
const [markdown, setMarkdown] = useState("");
useEffect(() => {
fetch("./01.md")
.then((response) => response.text())
.then((text) => setMarkdown(text));
}, []);
return (
<div style={{ width: "100%", justifyContent: "center", display: "flex" }}>
<div style={{ maxWidth: "768px", width: "100%" }}>
// 추가된 부분
<ReactMarkdown rehypePlugins={[rehypeHighlight, rehypeRaw]}>
{markdown}
</ReactMarkdown>
</div>
</div>
);
}
그럼 정상적으로 태그 네임없이 출력되는 모습!
굿드👍👍
감사합니다. 이런 간단한 방법이 있었네요