Velog와 비슷한 블로그 프로젝트: React에서 Markdown 사용하기

derek·2024년 10월 15일
0

개인적으로 Velog와 유사한 블로그 프로젝트를 만들고 있다. Velog처럼 Markdown 언어를 표시할 수 있는 기능을 찾던 중, react-markdown이라는 라이브러리를 발견했다. 이 라이브러리는 기본적인 Markdown 렌더링을 지원하며, 추가적으로 remark-gfm 플러그인을 사용하면 URL 링크 및 테이블을 이쁘게 표시할 수 있다.

라이브러리 설치

우선, 다음 명령어로 필요한 라이브러리를 설치한다:

yarn add react-markdown remark-gfm

라이브러리를 사용할 때는 페이지나 컴포넌트에 직접 적용하기보다, 별도의 컴포넌트를 만들어 라이브러리를 감싸는 것이 중요하다. 이렇게 하면, 나중에 다른 라이브러리로 교체하더라도 애플리케이션 전반에 미치는 영향을 최소화할 수 있기 때문이다.

Markdown Example

Markdown Component

스타일링 적용

그러나 이렇게만 하면 Markdown이 아래와 같이 브라우저에 표시되긴 하지만, 기본적인 스타일링이 적용되어 있지 않는다. 이는 TailwindCSS의 기본 typography가 reset되어 있기 때문이다.

Unstyled Markdown

TailwindCSS에서 제공하는 typography 플러그인을 사용하면 이 문제를 해결할 수 있다. 아래 두 가지 단계를 진행해야 한다:

  1. TailwindCSS typography 플러그인 설치:
yarn add @tailwindcss/typography
  1. Tailwind 설정 파일에 플러그인 추가:
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    // ...
  },
  plugins: [
    require('@tailwindcss/typography'),
    // ...
  ],
}

이제 우리가 만든 컴포넌트에서 적용하면, Markdown이 다음과 같이 표시된다. 하지만 좀 심심하니까 다음 스텝에서 커스터마이징을 해보자

Completed Markdown

추가적인 Markdown 커스터마이징 하기

더 나아가 Markdown을 더 꾸미고 싶다면, react-syntax-highlighter와 같은 라이브러리를 참고해 봐야한다.

라이브러리 설치는 다음과 같이 진행한다:

yarn add react-syntax-highlighter

Type Error

문서에서 제공하는 예시를 추가하면, 위와 같이 타입 에러가 발생할 수 있다. 이 경우, 타입을 추가해 주어야 한다.

yarn add -D @types/react-syntax-highlighter

타입 에러를 수정했다면, 이제 코드를 다음과 같이 수정해야 한다:

import React from 'react';
import { createRoot } from 'react-dom/client';
import Markdown from 'react-markdown';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { dark } from 'react-syntax-highlighter/dist/esm/styles/prism';

const markdown = `Here is some JavaScript code:

~~~js
console.log('It works!')
~~~
`;

createRoot(document.body).render(
  <Markdown
    children={markdown}
    components={{
      code(props) {
        const { children, className, ...rest } = props;
        const match = /language-(\w+)/.exec(className || '');
        return match ? (
          <SyntaxHighlighter
            {...rest}
            PreTag="div"
            children={String(children).replace(/\n$/, '')}
            language={match[1]}
            style={dark}
          />
        ) : (
          <code {...rest} className={className}>
            {children}
          </code>
        );
      },
    }}
  />
);

여기서 ref의 타입이 맞지 않는 에러가 발생할 경우, 아래처럼 구조 분해 할당으로 ref를 꺼내서 사용하지만 않으면 된다

Code Error

마지막으로, Next.js의 이미지 컴포넌트로 변경하고 싶다면, 이미지에 대한 코드를 작성해주시면 된다.

Final Markdown

위처럼 여백이 많아서, max-w 클래스를 max-w-none으로 변경해주었다.

Real Final Markdown

이렇게 하여 위와 같이 더욱 세련된 Markdown 뷰어를 완성할 수 있었다 :)

profile
derek

0개의 댓글