React-quill에서 tiptap 으로 - 2부

SeongHyeon Bae·2023년 11월 5일
1

1부 에서 작성한 글에 이어 2부를 작성해보려고 한다. 2부에서는 어떻게 lowlight로 게시글의 코드블럭에 색상을 넣었는지 많은 삽질과정을 확인해보자.

codeblock

왜 코드블럭에 색상을 넣어야할까?

아래의 두 코드블럭만 비교해봐도 쉽게 알 수 있다. 얼마나 가독성에 있어서 차이가 나는지...

const a = 1;
const b = 2;
console.log(a+b);
const a = 1;
const b = 2;
console.log(a+b);

우리 프로젝트는 개발자를 위한 커뮤니티이기에 문법 색상을 넣는것은 필수라고 생각했고 사용할 수 있는 2가지 라이브러리를 찾아보았다.

  1. Prism.js
  2. lowlight

Prism.js

Prism.js 는 syntax highliter 중 가장 유명하고 많이 쓰이는 라이브러리 이다. 웹 사이트에서 볼 수 있듯이 React 공식문서를 포함한 많은 곳에서 사용되고 있다. 많이 사용된다는 것은 업데이트도 자주 된다는 의미일 것이고 정보도 많기에 적용 해보려고 시도했었다.

적용하는 방식은 inline으로 head 파일에 다운받은 css(스타일링 색상),js(파싱을 위한 함수)을 다음과 같이 적용해 볼 수도 있다.

바닐라 스크립트 환경이였으면 충분히 적용해볼만 했지만 npm으로 관리하는 것이 편할것이라 판단 되어 Prismjs 모듈을 설치하여 진행하였다.

NEXTJS 환경에서는 게시글 을 참고하여 CSR 시에 Prism.highlightAll() 함수를 실행하여 해당 컴포넌트의 code 블럭에 색상을 넣고싶었다. 다음과 같이 코드를 작성해보았다.

import React, { useEffect } from 'react';
import { useEditor, EditorContent } from '@tiptap/react';
import ToolBar from '../Toolbar';

//tiptap
import StarterKit from '@tiptap/starter-kit';
import Highlight from '@tiptap/extension-highlight';

import Prism from 'prismjs';
import 'prismjs/themes/prism-tomorrow.css';
interface TiptapProps {
  content: string;
}

const Tiptap = ({ content }: TiptapProps) => {
  const editor = useEditor({
    extensions: [StarterKit, Highlight],
  });
  useEffect(() => {
    Prism.highlightAll();
  }, []);
  useEffect(() => {
    if (content) {
      editor?.commands.setContent(content);
    }
  }, [content]);
  return (
    <div className="border-2">
      <ToolBar editor={editor} />
      <EditorContent
        id="tiptap"
        editor={editor}
        onClick={() => editor?.commands.focus()}
      />
    </div>
  );
};

export default Tiptap;

하지만 결과는 적용되지 않았다...!!!(그렇게 쉽게 될리가 없지...)

그럼 원인이 뭘까? 고민을 해보고 몇가지 디버깅을 해보았다.

  1. NEXTJS 환경에서 안되는건가?
  2. Tiptap과 호환이 되지 않는걸까?
  3. 내 프로젝트와 의존성 문제가 발생했나?

일단 1번의 경우 이전 참고 사이트가 있는것을 보면 NEXT 환경에서도 된다는 것으로 판단하였다. 그럼 2번 문제가 가장 클것인데... 그래서 tiptap으로 작성된 html 코드를 정적으로 작성해보고 결과를 확인해보았다.

<pre>
	<code className="language-js">
		const a = 1; const b= 2; console.log(a+b);
	</code>
</pre>

오! 작동이 잘 되는것을 확인할 수 있었다.!!

이 결과로 Prism.highlight() 함수는 해당 컴포넌트 의 codeblok을 확인하고 스타일링을 하는데 Tiptap의Content 내부로는 들어가지 않거나 혹은 게시글은 정적인 코드가 아닌 동적 코드이기에 useEffect가 계속해서 작동이 되지 않아서 그런걸 수도 있겠다라고 생각했다.

후자의 경우 dependency에 content상태를 넣어 타이핑을 칠떄마다 Prism.highlight()를 실행할 수도 있겠지만 그건 원하지 않았다. 그래서 Tiptap에서 추천하는 lowlight 라이브러리를 사용하였다.

lowlight

tiptap에서 lowlight 사용법에 대해서 자세히 설명되어있으므로 그대로 구현했는데 다음과 같은 에러가 발생되었다. (억까의 시작)

이때 쫌 승질이 났다... 하라는대로 했는데 왜 없다는거야!!!

Tiptap은 업데이트가 늦다는 지인의 말이 생각이나 설마 lowligt 버전 업데이트되면서 변경됐나 싶었다. 이럴땐 lowlight 공식문서를 확인해보자.

역시나... tiptap 공식문서에서 사용되는 lowlight 버전은 v2.7.0 이고 현재 최신버전은 v3.1.0 이라 메이저 버전 업데이트로 인해 export 하는 값이 변경되었다. 이에 따라 사용법도 바뀐것이다.!! 버전 호환성 문제는 자주 발생하지만 적응이 안된다 하하하

그래서 먼저 3.1.0 버전으로 적용을 해보고 문제가 발생하면 공식문서 버전인 2.7.0으로 특정 버전을 설치하여 해결해보려 하였다.

오오~~ 드디어 codeblock에 색상이 들어오기 시작했다!👏 하지만 새로운 문제가 발생했다.

문제상황

const a= 1; 이라는 코드를 복사 붙여넣기를 했는데 이상하게 메타태그와 함께 html 코드까지 붙여넣기가 된다는 문제였다...

이거 만만치 않을거 같다는 예감이 있었다... 붙여넣기에서 문제가 발생한거 같으니 Tiptap에서 관련 정보가 있나 찾아보았다.

참고를 보면 정확하게 나의 상황과 같지는 않지만 addNodeView 와 같은 함수를 확인할 수 있었다.

그럼 addNodeView 을 이용하여 현재 html에서 내부 TEXT 만 받아와서 return 값으로 넘겨주면 되지않을까?

콘솔을 찍어가며 내부 프로퍼티 탐색 후 위 생각처럼 구현해보았는데 잘 되지않았다. 역시 쉬운건 없다... Syntax Highligh 없어도 되지않을까? 잠깐 유혹에 넘어갈뻔 했지만 다시 마음을 다잡고 에러 분석을 해보았다.

디버깅

먼저 뭐가 문제일까 논리적으로 생각해보자.

  1. 이 또한 NEXTJS 환경문제?
  2. 나의 프로젝트와 의존성 문제?
  3. lowlight의 3.1.0 버전의 문제?

스택오버플로우나 lowlight 깃이슈를 봐도 nextJS 문제는 확인할 수 없었다. 그럼 2,3번일 가능성이 있는데 2번 먼저 디버깅을 해보았다.

의존성 문제가 있는지 확인하기 위해서 나는 항상 새 프로젝트 에서 해당 라이브러리만 설치하여 동작 시켜본다. 예전에는 로컬에서 확인했었지만 이번에는 CodeSandbox라는 좋은 플랫폼을 알게되어 사용해 보았다. 코드 직접 만든 독립적인 환경에서 실행해보니 다음과 같이 잘 작동하는 것을 알 수 있다. 그럼 2번 문제라고 생각이 되어서 어떻게 해결을 해야 하나 고민이 많았다.

하지만 생각보다 어이없게 yarn-lock 파일을 제거한 뒤 yarn install을 통해 재설치하니 의존성 문제가 해결되어 정상적으로 코드 복붙이 잘 되어버렸다.😫 아마도 기존에 깔려있는 모듈과 충돌이 발생해서 이러한 버그가 발생한게 아닐까 싶다.

마무리

끝은 조금 엉성하지만 문제가 발생했을 때 하나하나 디버깅을 해보며 독립적인 환경에서 어떠한 것이 문제인지 해결하는 능력을 키웠다.👍

혹시 잘못된 부분이나 더 나은 해결방법이 있으면 댓글로 알려주시면 감사하겠습니다.🙇🏻‍♂️

profile
FE 개발자

0개의 댓글