[React+Typescript] WebEditor Summernote(with. jQuery)

anonymous-planet·2022년 6월 22일
1

React+Typescript

목록 보기
6/6

이번 포스팅은 WebEditor중 하나인 Summernote이다.

해당 Editor를 접할 기회가 생겼고, 다른 WebEditor를 사용해본적이 없기 때문에 다른 Editor에 비해서 장점을 말하기는 힘들겠지만 구현해보면서 느낀 장점/단점과 구현방법에 대해서 작성해볼 예정이다.

1. Summernote 장/단점

다른 웹에디터를 사용해보지 않아 다른 에디터에 비해 어떤지는 잘 모르기 때문에 내가 구현해보면서 느낀 장/단점에 대해서 작성해보겠다

1.1. 장점

  • 어느 정도 툴바 커스터마이징이 편리했다.
  • type을 지원해 typescript로 개발이 편리했다.
  • 다양한 callback함수를 지원한다.

1.2. 단점

  • jQuery 의존성(jQuery 없이 사용 불가)

    요즘 같이 jQuery를 지양하려는 추세에서 이건 큰 단점이라 생각한다.

  • bootstrap 의존성

    bootstrap으로 인해 사용하고 있는 스타일과 충돌이 발생할수 있는 이슈가 있어, 이거또한 큰 단점으로 다가왔다.
    summernote-lite버전의 경우 bootstrap없이 사용이 가능하지만 자잘한 버그들이 존재한다.
    (제가 기존 스타일과 bootstrap스타일 충돌을 막는 방법을 모릅니다.)

  • npm 설치 불가

    이 부분에대해서는 내가 못찾은 부분일수도 있지만 찾지 못했고, public폴더 밑에 있는 index.html에서 스크립트 태그를 이용해 include 시켜 사용 했다. 이것또한 단점으로 보였다.

2. 구현

bootstrap을 사용하는 버전을 사용해서 구현했다.

2.1. js,css 추가

public/index.html에
jQuery(js), 부트스트랩(js,css), 서머노트(js,css) 이렇게 총 5개를 include시켜 줘야하며 여기서 주의점은 summernote.js에서 jQuery를 사용하기 때문에 summernote.js보다 jQuery를 먼저 include시켜줘야 한다.

(summernote-lite버전을 사용할경우는 jQuery, summernote(js,css) 이렇게 3가지만 include해주면 된다.)

(cdn에서 갖고오지 않고 js 파일을 받아 프로젝트에 추가 시켜줄경우는 위에 파일들과 font폴더도 추가 시켜줘야한다. 언어 설정을 위해서는 + 언어 js파일도 추가)

<script src="https://code.jquery.com/jquery3.5.1.min.js"></script>

<link href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>

<link href="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote.min.js"></script>

2.2. type설치

jQuery와 summernote의 타입을 설치해준다.
(jQuery타입을 추가 시켜주지 않을경우 $를 찾지 못하는 것 같다.) - Typescript를 사용하지 않을 경우는 패스

npm install @types/jquery @types/summernote

2.3. Editor.tsx

summernote 구현부분이다.

import { useEffect } from "react";
// summernote오류날경우 import만해준다
// import summernote from "summernote";


export default function WEditor() {
  useEffect(() => {

    // summernote옵션 설정
    const config: Summernote.Options = {
      tabDisable: true, // 키보드 Tab키를 사용가능할게 할지(Default false)
      // toolbar에 넣을 항목들 정의
      toolbar: [
        // 작성해준 순서대로 toolbar에 삽입된다.
        // 중복으도 선언가능하며, toolbar삽입 위치를 자유롭게하기 위해서 중복으로 타입이 되어있어 보인다.
        ["font", ["bold", "italic", "underline", "superscript"]],
        ["fontsize", ["fontsize", "fontname", "color"]],
      ],

      // 사용하고 싶은 fontSize들만 정의
      fontSizes: ["10", "12", "14", "16"],

      // 사용하고 싶은 Color들 정의, [[[]]] 이란걸 주의하자!, 최종안에 배열의 색상값이 한줄에 표시된다.
      // 아래처럼 선언할시 첫번째줄 red 하나, 두번째줄 black하나, 세번째줄 yellow 하나 이렇게 나타난다.
      colors: [[["red"]], [["black"]], [["yellow"]]],

      // fontSize단위
      fontSizeUnits: ["px"],

      // placeholder이다.
      placeholder: "아무말이나 작성해주세요!",

      // tooltip에 언어를 설정하는것같은데, 사용을 원할 경우 언어 summernote-ko.js파일도 추가가 필요 해보인다.
      lang: "ko-KR",

      // !!중요!! Callback 함수 정의, 많이 쓰일것같다.
      // 사용해본 몇가지만 작성할예정이며 이것저것 많아 보인다.
      callbacks: {
        onInit: () => {
          // editor가 초기화 되었을 때 이벤트 발생
        },
        onChange: (contents: string, $editable: JQuery) => {
          // editor내용이 변결 될때마다 이벤트 발생
        },
        onKeyup: (ev: KeyboardEvent) => {
          // keyboard버튼 눌렀다가 땠을 때 이벤트 발생 ev.key를 통해 누른 버튼의 값을 갖고올수있디ㅡ
        },
        onKeydown: (ev: KeyboardEvent) => {
          // keyboard버튼 눌렀을 때 이벤트 발생
        },
        onPaste: (e: Event & { originalEvent: ClipboardEvent }) => {
          // editor에 붙여넣기 했을 때
          // 파라미터 타입에 originalEvent를 추가 시켜준건 붙여넣기할 텍스트를 갖고 오기 때문이다.(하단 참고)
          
          // 붙여넣기할 텍스트를 갖고오는 부분이다.
          const clipboardData = e.originalEvent.clipboardData?.getData("text");
        },
      },
    };
    
    // summernote초기화 및 렌딩(?)
    //JSX부분에 summernote를 id로 갖는 태그는 div/textarea 둘다 가능하며 차이점은 없어 보인다.(공식사이트에서는 div로 되어있는걸 본것같다.)
    $("#summernote").summernote(config);
  }, []);

  // 저정 버튼 눌렀을때 호출되는 함수
  const onEditorSaveHanlder = () => {
    // editor에 작성된 텍스트 내용을 갖고온다
    // html태그를 포함한 내용이다.
    const content = $("#summernote").summernote("code");

    console.log(content);
  };

  return (
    <>
      <div style={{ width: "800px" }}>
        <textarea id="summernote"></textarea>
      </div>
      <div>
        <button onClick={onEditorSaveHanlder}>저장!</button>
      </div>
    </>
  );
}

2.4. 결과

3. 후기

지극히 개인적인 생각으로

jQuery(OK), bootstrap(OK) - 사용이 나쁘지않다
jQuery(OK), bootstrap(NO) - 라이트 버전을 이용해서 구현 가능하지만, 버그를 수정하거나 감수해야한다.
jQuery(NO), bootstrap(NO) - 바로 다른 에디터를 찾아보자

개인적인 생각으로는 jQuery, bootstrap의 의존성은 큰 단점으로 다가왔고 bootstrap이 없이 사용가능한 lite버전의 자잘한 버그는 크게 느껴졌으며, 나에게 웹에디터 구현의 기회가 온다면 jQuery, bootstrap전부를 사용해야 하는 이상 다른 에디터를 찾아 볼 것 같다.

profile
취미로 Front-End를 즐기는 Back-End개발자 입니다.

2개의 댓글

comment-user-thumbnail
2023년 6월 27일

안녕하세요 글 잘 읽어보았습니다.
질문이 있는데 Summernote.Options을 타입으로 사용하려는데
Summernote타입을 찾아오지 못하는 타입 오류가 발생하더라구요
Summernote타입도 다운받고 했는데 이유를 모르겠습니다ㅠ

1개의 답글