<aside> 🗓️

2026-09-03 ~ 2026-09-04, inote-blog의 Tiptap 기반 노션 스타일 에디터(src/shared/ui/editor)를 만들면서 겪은 이슈를 증상 → 원인 → 해결 순으로 정리합니다.

</aside>

요약

# 이슈 원인 한 줄 요약
1 @tiptap/suggestion 예제 코드가 안 맞음 v3부터 tippy.js 없이 자체 위치 계산(props.mount) 지원
2 @tiptap/core import 에러 pnpm strict node_modules — 간접 의존성 직접 import 불가
3 Placeholder 안 보임 속성만 달아줄 뿐 CSS는 직접 추가해야 함
4 마크다운 원문 붙여넣기가 안 됨 text/html 유무에 따라 붙여넣기 경로가 완전히 갈림
5 표(테이블)가 전혀 렌더링 안 됨 에디터 스키마에 테이블 노드 자체가 없었음 (StarterKit 기본 미포함)
6 렌더링된 화면에서 복사한 코드블록이 깨짐 최초 가설이 틀렸음 — 실제론 두 가지 다른 원인이 섞여 있었음

1. @tiptap/suggestion v3 API가 예전 자료와 다름

증상: 온라인 튜토리얼 대부분이 tippy.js로 팝업 위치를 수동 계산하는 예제.

원인: 설치된 버전(v3.31)은 API가 바뀌어서 tippy.js가 필요 없음.

해결: 예제를 그대로 베끼지 않고 설치된 패키지의 타입 정의(.d.ts)를 직접 읽음 — render()의 onStart에서 props.mount(element)를 호출하면 Floating UI 기반 위치 계산·스크롤 추적을 라이브러리가 알아서 처리. tippy.js는 추가했다가 다시 제거.

낡은 기억/예제로 라이브러리 코드를 짜면 안 쓰는 의존성만 늘어난다는 교훈 — 이후 세션에서도 계속 적용.


2. @tiptap/core "Module not found"

증상: @tiptap/core를 직접 import하면 모듈을 찾을 수 없다는 에러.

원인: @tiptap/react가 내부적으로 사용하긴 하지만, pnpm의 strict node_modules 구조에서는 간접(phantom) 의존성을 직접 import할 수 없음.

해결: @tiptap/core를 package.json에 직접 의존성으로 추가.


3. Placeholder 텍스트가 안 보임

증상: @tiptap/extension-placeholder를 추가했는데 빈 에디터에 안내 문구가 안 뜸.

원인: 이 확장은 data-placeholder 속성만 달아줄 뿐, 실제로 보여주는 CSS(::before + content: attr(data-placeholder))는 별도로 넣어야 함.

해결: globals.css에 아래 규칙 추가.

.tiptap p.is-editor-empty:first-child::before {
  content: attr(data-placeholder);
  color: #a1a1aa;
  float: left;
  height: 0;
  pointer-events: none;
}