개발/프로젝트

Tiptap 라이브러리로 텍스트 에디터 만들기

xuwon 2025. 5. 27. 15:11

텍스트 에디터를 만들기 위해 Tiptap 라이브러리를 사용해 봤다.
 

Tiptap 라이브러리

ProseMirror를 기반으로 한 모던하고 확장 가능한 Rich Text Editor!
Next.js, React, Vue, Svelte 등 다양한 프레임워크와 잘 통합되고 마크다운처럼 텍스트를 구조적으로 관리할 수 있는 기능을 제공한다.

 

Tiptap 주요 특징

1. ProseMirror 기반
- 마크다운처럼 텍스트 구조를 명확하게 파악할 수 있는 트리 기반 편집기
2. 확장성
- Extension을 통해 기능을 자유롭게 추가하거나 수정 가능
3. Headless 구조
- 원하는 UI 직접 구성 가능!
4. React/Vue 지원
- @tiptap/react, @tiptap/vue-3 패키지 사용

 

Tiptap 구성 요소


1. useEditor
에디터 인스턴스를 생성하는 훅.
확장, 초기 콘텐츠, 이벤트 핸들러 등 설정!

const editor = useEditor({
  extensions: [StarterKit],
  content: '<p>Hello Tiptap!</p>',
});


2. EditorContent
React 컴포넌트로, 에디터를 실제로 렌더링하는 부분

<EditorContent editor={editor} />

 

3. Extensions
기능 (ex. italic, color, highlight 등)은 모두 확장으로 이루어짐.
내장 확장과 커스텀 확장을 조합하여 사용!

// 기본 서식
import StarterKit from '@tiptap/starter-kit';

// 텍스트 스타일, 색상, 하이라이트
import TextStyle from '@tiptap/extension-text-style';
import Color from '@tiptap/extension-color';

// 사용자 정의 하이라이트
import { customHighlight } from '@/extension/customHighlight';

 


나는 최대한 간단하게 하려고 이탤릭, 취소선, 형광펜, 글씨 컬러 이렇게만 넣었다.

const editor = useEditor({
  extensions: [
    StarterKit,
    TextStyle,
    Color.configure({ types: ['textStyle'] }),
    customHighlight,
    Placeholder.configure({ placeholder: '오늘 당신의 하루는 어땠나요?' }),
  ],
  content: '',
});

 
1. StarterKit는 Tiptap에서 제공하는 기본 확장 패키지이다.
(bold, italic, strike 등...)
2. TextStyle은 텍스트에 스타일 속성을 적용할 수 있게 하는 익스텐션
color, fontSize 등을 추가하려면 이 익스텐션이 필요하다.
3. Color 확장 (TextStyle 노드에 대해 색상을 적용하도록 설정한 것)
4. customHighlight는 내가 만든 하이라이트 확장
색상을 변경하려고 만들었다.

import Highlight from '@tiptap/extension-highlight';

export const customHighlight = Highlight.extend({
  addOptions() {
    return {
      ...this.parent?.(),
      multicolor: false,
      HTMLAttributes: {
        class: 'custom-highlight',
        style: 'background-color: #81C784;',
      },
    };
  },
});

이렇게~..
5. Placeholder.configure(...)는 플레이스홀더를 넣기 위해 추가했다.
6. content: ' '는 에디터 초기 콘텐츠를 설정하는 것이다.


 <EditorContent
  editor={editor}
  className="focus:outline-none border border-1 border-main-yellow p-3 rounded-b-xl iphoneSE:h-[300px] min-h-[400px] bg-bg-yellow"
/>

스타일을 넣어서 텍스트 에디터를 만들었다.
근데 툴바가 자동으로 적용되는게 아니라서... Toolbar.tsx를 만들었다.
 

if (!editor) return null;

우선 에디터가 생성 안되면 툴바도 렌더링하지 않게 했다.
 

const toggleColor = (editor: Editor, color: string) => {
  const currentColor = editor.getAttributes('textStyle').color;

  if (currentColor === color) {
    editor.chain().focus().unsetColor().run();
  } else {
    editor.chain().focus().setColor(color).run();
  }
};

toggleColor 함수

: 현재 색상이 클릭한 색상이면 unsetColor()로 해제!
아니면 setColor()로 적용

editor.chain().focus().toggleItalic().run();
editor.chain().focus().toggleStrike().run();
editor.chain().focus().toggleHighlight().run();
editor.chain().focus().unsetColor().run();

그리고 이런 식으로 버튼을 선택할 때마다 스타일이 토글되게끔 버튼에 온클릭 이벤트로 넣어주었다.
toggleItalic, toggleStrike 등은 모두 tiptap이 제공해주는 건데, toggleColor는 없어서 새로 만든 것.
그럼 이런 귀여운 텍스트 에디터가 완성된다.