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


'개발 > 프로젝트' 카테고리의 다른 글
새로고침/뒤로가기 시도 시 모달 띄우기 (0) | 2025.05.27 |
---|---|
스크롤 기반 싱글 페이지 라우팅 구현하기 (0) | 2025.04.04 |
[리팩토링] 새로고침 해도 검색 결과가 남아있도록 하기 (5) | 2025.02.28 |
Zustand로 API 호출 및 상태 관리하기 (0) | 2025.02.28 |
Tailwind CSS + SCSS로 반응형 구현하기 (0) | 2025.02.25 |