25.블로그 포스트 작성 및 에디터 기능 추가, Next.js에 마크다운 에디터 추가하기

최근 몇 년간 블로그와 콘텐츠 관리 시스템에서 마크다운(Markdown)의 사용이 급증했습니다.
마크다운은 간편하고 직관적인 문법을 제공하여, 사용자가 텍스트를 쉽게 포맷할 수 있게 해줍니다.
이번 포스트에서는 Next.js를 기반으로 마크다운 에디터를 추가하는 방법에 대해 자세히 설명하겠습니다.
또한 블로그 포스트 작성 및 에디터 기능 추가에 필요한 기술 스택과 구성 요소에 대해서도 다룰 것입니다.

1. Next.js 개요

Next.js는 React 기반의 정적 웹사이트 및 서버 사이드 렌더링(SSR) 웹 애플리케이션을 구축하기 위한 프레임워크입니다.
Next.js는 SEO 친화적이며, 페이지 최적화 및 코드 스플리팅을 자동으로 처리하여 성능을 극대화합니다.
이외에도 API 라우팅, 이미지 최적화, 정적 생성 등 다양한 기능을 제공하여 개발자들이 생산성을 높일 수 있도록 돕습니다.

Next.js 설치 및 설정

Next.js 프로젝트를 시작하려면 Node.js 및 npm이 설치되어 있어야 합니다.
다음 명령어를 통해 Next.js 프로젝트를 생성할 수 있습니다.

npx create-next-app my-blog

2. 마크다운 및 마크다운 에디터

마크다운은 텍스트 기반의 경량 마크업 언어로, HTML과 유사한 형식을 사용하여 문서의 구조를 정의할 수 있습니다.
마크다운을 활용하면 블로그 글 작성 시 포맷팅이 간편하고 빠르게 진행될 수 있습니다.
이번 섹션에서는 간단한 마크다운 문서를 작성해 보겠습니다.

마크다운 예시


# 제목 1
## 제목 2
### 제목 3

이것은 두 번째 단락입니다.

- 리스트 항목 1
- 리스트 항목 2
- 리스트 항목 3

[링크 텍스트](http://example.com)

**강조된 텍스트**
    

3. Next.js에 마크다운 에디터 추가하기

Next.js 프로젝트에 마크다운 에디터를 추가하기 위해 여러 패키지를 설치하고 설정해야 합니다.
다음은 우리가 사용할 주요 패키지 목록입니다.

  • react-markdown: 마크다운을 React 컴포넌트로 변환합니다.
  • react-quill: WYSIWYG 마크다운 에디터를 제공합니다.
  • remark-gfm: GitHub 스타일 마크다운을 지원합니다.

패키지 설치

아래 명령어를 사용하여 필요한 패키지를 설치합니다.

npm install react-markdown react-quill remark-gfm

에디터 컴포넌트 만들기

React 컴포넌트를 사용하여 마크다운 에디터를 만들고, 이를 Next.js에 통합합니다.
components/MarkdownEditor.js라는 파일을 생성하고 다음 코드를 추가합니다.


import React, { useState } from 'react';
import ReactQuill from 'react-quill';
import 'react-quill/dist/quill.snow.css'; // 스타일 추가

const MarkdownEditor = () => {
    const [text, setText] = useState('');

    return (
        

미리보기

); }; export default MarkdownEditor;

페이지에서 에디터 사용하기

이제 작성한 에디터 컴포넌트를 페이지에서 사용해 보겠습니다.
pages/index.js 파일에 아래의 코드를 추가합니다.


import MarkdownEditor from '../components/MarkdownEditor';

export default function Home() {
    return (
        

블로그 포스트 작성

); }

4. 마크다운 파일 저장 및 불러오기

작성한 내용은 어딘가에 저장되어야 합니다. 이번 섹션에서는 마크다운 파일을 저장하고 불러오는 로직을 구현합니다.
파일 시스템 모듈을 사용하여 만들 수 있습니다.

파일 시스템 사용하기


import fs from 'fs';
import path from 'path';

const filePath = path.join(process.cwd(), 'posts', 'my-post.md');

const savePost = (content) => {
    fs.writeFileSync(filePath, content);
};

const loadPost = () => {
    return fs.readFileSync(filePath, 'utf8');
};
    

요청 핸들러 구축하기

Next.js의 API 라우트를 사용하여 클라이언트와 서버 간의 데이터 요청을 처리할 수 있습니다.
pages/api/posts.js 파일을 생성하고 POST, GET 요청을 처리하는 코드를 추가합니다.


export default function handler(req, res) {
    if (req.method === 'POST') {
        savePost(req.body.content);
        res.status(200).json({ message: '포스트 저장 완료' });
    } else {
        const content = loadPost();
        res.status(200).json({ content });
    }
}
    

5. 전체 구현 예시

위의 모든 코드를 모아 완성된 블로그 포스트 작성기 에디터를 구현해보겠습니다. 최종 코드는 아래와 같습니다.


// components/MarkdownEditor.js
import React, { useState, useEffect } from 'react';
import ReactQuill from 'react-quill';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import 'react-quill/dist/quill.snow.css';

const MarkdownEditor = () => {
    const [text, setText] = useState('');

    useEffect(() => {
        const loadPost = async () => {
            const response = await fetch('/api/posts');
            const data = await response.json();
            setText(data.content);
        };

        loadPost();
    }, []);

    const savePost = async () => {
        await fetch('/api/posts', {
            method: 'POST',
            body: JSON.stringify({ content: text }),
            headers: {
                'Content-Type': 'application/json',
            },
        });
    };

    return (
        

미리보기

); }; export default MarkdownEditor; // pages/index.js import MarkdownEditor from '../components/MarkdownEditor'; export default function Home() { return (

블로그 포스트 작성

); } // pages/api/posts.js import fs from 'fs'; import path from 'path'; const filePath = path.join(process.cwd(), 'posts', 'my-post.md'); const savePost = (content) => { fs.writeFileSync(filePath, content); }; const loadPost = () => { return fs.readFileSync(filePath, 'utf8'); }; export default function handler(req, res) { if (req.method === 'POST') { savePost(req.body.content); res.status(200).json({ message: '포스트 저장 완료' }); } else { const content = loadPost(); res.status(200).json({ content }); } }

6. 마무리

이번 포스트에서는 Next.js를 기반으로 마크다운 에디터를 추가하는 방법에 대해 알아보았습니다.
간단한 WYSIWYG 에디터를 통해 블로그 포스트를 작성하고, 서버에 데이터를 저장하는 방법까지 다뤘습니다.
앞으로 추가적인 기능을 구현하여 더욱더 풍부한 블로그 작성 경험을 제공할 수 있습니다.
Next.js의 애드온을 사용하여 자신만의 블로그 플랫폼을 만들어 보세요!