TiptapEditor2.0 (next.js)

KIP·2022년 6월 1일
1

next를 쓰다보니 ssr에 걸맞는 에디터를 쓰기가 굉장히 불편해졌고 ,
구글에도 많은 정보가 없기도 하고.. next에서도 이 에디터를 사용할 사람을 위해 최대한 필요한 기능들 (마크다운까지는 할 수 있을지 모르겠다)을 한국어로 설명하면서 docs에 있는 기능들에 대한 사용법까지 공유하려고 한다.

우선 내가 사용할 게시판의 기능은 html태그를 innerText에 사용할 수 있으면서, 이미지들을 업로드 시에 백엔드 쪽에 데이터를 남겨주기.
최종적으로 글을 작성할 때 <div>hi</div> <img src="www.fddffd.com"/> 같은 형태로 넘겨주는 작업이다.

여러 에디터를 거쳐본 결과, 어떠한 에디터든 결국 하나를 완벽하게 하면 나머지는 비슷하다는 결론이 난다. ssr이든 csr이든 결국 ref로 접근하는 방법과 각 에디터마다 제공하는 기능들에 대해서 커스터마이징하는건 비슷한 구조로 동작하기 때문이다.

최대한 https://tiptap.dev/ 이 사이트에서 제공해주는 것들로 기능을 구현할 것이고, 쓰일 기능들. 어떻게 써야하는지에 대해서 알아보자.

(에디터를 능숙하게 쓰시는 분이라면 저에게 조언을..)


제일 처음부터 난항이 있었다. 예전에 quill을 쓸 때도 생겼는데
리액트의 버전과 에디터의 버전이 맞지 않을 때 생긴다. 이번에 쓸 Tictac2.0은 리액트 17 || 18 버전 밑에서 사용시 에러가 떴다.
제일 편한 방법은 기존 리엑트의 버전을 uninstall후 리액트의 버전을 업그레이드 시키는 방법이다(항상 최신버전이 좋은 것 만은 아니다).

https://tiptap.dev/installation/nextjs
처음 연습을 하기 위해서 새 디렉토리를 만든 후 installation을 따라했다. 이까지는 크게 문제가 없었다.


여기서부터 extensions라는 용어가 나온다. 우리가 보통 input태그에서 type이나 image요소를 가져올 때 태그 안에 있는 요소들을 꺼내서 사용했지만 에디터의 경우(내가 사용하는 antd라이브러리도 거의 비슷)는 그 기능들에 대해서 class나 function 형태로 사용한다.

젤 처음 사진을 html의 이미지로 넣기 위해서 했던 작업을 살펴보자.
https://tiptap.dev/examples/default 여기에 각종 예시들이 있고,
https://tiptap.dev/examples/images 여기를 들어오면 이미지에 관련된 코드예시들이 있다(꼭 확인).


에디터를 살펴보면 installation -> settings -> commands -> sourcecode -> usage 순으로 되어있다. install은 말 그대로 기능을 쓰기위해 npm이나 yarn을 통해 install하는 것이니 생략하고(내가 css를 바꾸고 싶다면 Tiptap홈페이지에 들어가 css styling과 같은 키워드를 검색하면 잘 나온다)
image를 처리하는 방법을 이 순서대로 한번 진행해보려한다.


Settings

settings는 기본 옵션에 대한 설정을 얘기한다. 즉 내가 이미지를 어디선가 가져올 때, 그 이미지가 base64형식이면 복사를 허용할 것인지, 에디터안에 복사시 어디로 복사할 것인지에 대한 것들이다.

내가 커스터마이징할 에디터를 기준으로 예시를 들어보겠다


이미지에 setting값들을 바꿔주는 기능:
autolink
openOnClick
linkOnPaste
HTMLAttributes

이 기능들은 위와같이 extensions에서 바꿔줄 수 있다.
이 4개의 기능들에 대해서

이와 같은 설명과 함께 적어놨다. 앞으로는 사진이 아닌 link와 여러가지 기능들도 설명할 것이기 때문에 각 기능들에 대한 정확한 설명은 하지않고 얘가 어떤 기능을 가졌는지 정도만 설명하겠다.


commands

이미지에 대한 명령어를 찾아보니 setImage()라는 기능이 나온다.
우선은 Tiptap에서 제공해준 예시대로 나도 onClcik event에 대해서 작업해보겠다.

  const onClickImg = () =>{
    const url = window.prompt('URL')

    if (url) {
      console.log(editor)
  
      
      editor.chain().focus().setImage({ src: url }).run()}
      

버튼 클릭 후 링크를 받아 setImage를 사용했다. 여기서 사진을 받아오면 현재 내가 클릭하고 있는 곳에 사진이 등록되는데, 이때 사진의 크기는 제각각 다르다. 아직 Tiptap에서도
개발이 안된상태라고 한다.


이렇게 되면 img태그에 대한 설정 값과 eventHandler에 대해서 적용했다.
나머지 기능들도 이와 유사하게 되기때문에 연습이 필요함을 느꼈다.


추가작업 (이미지 리사이징)

리사이징을 해주는 에디터가 있다고 하는데, 에디터에서 적용가능한지는 아직 체크해보지 않았다. 수작업으로 진행한 후 에디터를 이용하는 방법을 찾아볼 예정

사진 개별마다 리사이징을 하는 것이 아닌 텍스트 내부에서 사진의 크기를 일정하게 맞춰본다.

첫번째 시도=> 우선 이미지를 불러온 후 이미지 classname(나의 경우 settings에 class를 contentImg라고 명명)에 접근.

    if (url) {
      console.log(editor)
  
      
      editor.chain().focus().setImage({ src: url }).run()
      /* 이미지의 사진 배열로 담기 */
      const img = []
      /* 배열에다가 사진들을 담는다. spread문법을 사용하지 않으면 이전 값들이 모두 사라짐.*/
      img.push(...document.getElementsByClassName('contentImg'))
      /*  첫번째와 2번째 사진에 테스트 진행*/
      img[0].style.width  = '50px'
      if(img[1]){
        img[1].style.width = '100px'
      }
      console.log(img)
      /*  에디터 내부의 태그들의 상태를 html로 보여준다. (이밖에 getJSON과 getText도 있다) */
      console.log(editor.getHTML())


    }

결과


내가 지정해준대로 첫번째와 두번째사진의 width값이 바뀌었다.

배열에다가 사진들을 담았으므로, 배열 내장 함수를 이용해 모두 같은 width값을 지정해보자.

img.forEach((v) => v.style.width = '50px') 를 이용해 모든 사진을 50px로 설정해 모든 사진의 값들의 사이즈를 조정.

여기서 조금 어려워진다.
나는 지금 onClick event에 대한 사진 값들만 resizing을 했기 때문에, keyboardEvent에 대해서는 적용되지 않는다.
즉, 사진을 지우고 crtl+z를 누르면 예전 사이즈가 나오는 것이다.
그래서 https://tiptap.dev/guide/custom-extensions/#events
여기에 들어간다.

여기는 게시글 내부의 상태의 변화에 따라, 혹은 처음 에디터가 create될 때등의 상태에 따라 변화를 줄 수 있다.


여기에 update는 게시글 내부에 어떤 변화가 생길 때마다 작동되는 함수.
아까 onClick event에 대한 코드를 복사 후

onUpdate() {
      const img = []
      /* 배열에다가 사진들을 담는다. spread문법을 사용하지 않으면 이전 값들이 모두 사라짐.*/
      img.push(...document.getElementsByClassName('contentImg'))
      /*  첫번째와 2번째 사진에 테스트 진행*/
   
      img.forEach((v) => v.style.width = '50px')
      console.log(img)
      /*  에디터 내부의 태그들의 상태를 html로 보여준다. (이밖에 getJSON과 getText도 있다) */
      console.log(editor.getHTML())
     console.log(editor)
  },

와 같이 담아준다. 최적화는.. 당장은.. 신경쓰지 않을 예정..

우선 이처럼 진행하면 이미지 리사이징은 업데이트시 마다 바뀌기 때문에 onClick을 해 이미지를 업로드하는 경우와 keyboardEvent에 대해서도 리사이징을 한다.

우선 내가 사용할 에디터에서 이미지에 대한 설정은 완료했다.

계속해서 기타 기능들을 추가작업 후 여기 공유할 예정이다.

0개의 댓글