Tiptap 라이브러리로 텍스트 에디터 만들기
텍스트 에디터를 만들기 위해 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는 없어서 새로 만든 것.
그럼 이런 귀여운 텍스트 에디터가 완성된다.

